Як змусити оновити макет перегляду?


173

Я хочу змусити вигляд основного макета ресурсу перемалювати / оновити, скажімо, метод Activity.onResume (). Як я можу це зробити?

Під головним переглядом макета я маю на увазі той ('R.layout.mainscreen' нижче), який викликається в моєму Activity.onCreate (), як це: -

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.mainscreen);
}

Чи спробували ви назвати свій додаючий Linear / Relative / WeverLayout, викликавши на ньому findViewById, а потім викликаючи недійсним ()? (Я поставив би це як відповідь, але не знаю, чи недійсні батьки також визнають недійсними дітей, і я не десь, я можу це перевірити.)
Бен Вільямс,

Дякую також! Я все ще борюся з цим, хоча. Чи можете ви поглянути на те, що я розмістив нижче. Мені потрібен цей код (чи інший?), Щоб викликати оновлення моєї теми ...
MickeyR

Відповіді:


149

Щоб суворо відповісти на питання: Використовуйте invalidate ():

публічна недійсність недійсна () Оскільки: API рівень 1

Недійсний весь погляд. Якщо вигляд видно, в якийсь момент в майбутньому буде викликано OnDraw (Canvas). Це потрібно викликати з потоку інтерфейсу користувача. Щоб зателефонувати з потоку, що не використовується UI, зателефонуйте postInvalidate ().

ViewGroup vg = findViewById (R.id.mainLayout);
vg.invalidate();

Тепер, коли активність поновлюється, вона змушує кожен Вид малювати себе. Не потрібно закликати недійсно (). Щоб застосувати тему, переконайтеся, що ви робите це перед тим, як намальовано будь-який вид, тобто перед цимsetContentView(R.layout.mainscreen);

public void setTheme (int залишається) З: API рівня 1

Встановіть базову тему для цього контексту. Зауважте, що це слід викликати перед тим, як будь-які представлення представлені у контексті (наприклад, перед викликом setContentView (Перегляд) або надути (int, ViewGroup)).

Довідкова інформація про API тут: http://developer.android.com/reference/android/view/ContextThemeWrapper.html#setTheme%28int%29

Оскільки метод onDraw () працює на вже створених вікнах, setTheme не працюватиме. Я сам не маю досвіду роботи з темами, але я думаю, що два альтернативні варіанти:

  1. call nameTheme в onCreate () замість цього, або
  2. повторити setContentView (R.layout.mainscreen); щоб змусити відновити весь макет.

Дякую ! Це працює нормально, але я не бачу, чого я очікував. Перед тим, як запустити ваш код, я запускаю Activity.setTheme (newtheme), але цей недійсний () виклик не призводить до зміни теми (наприклад, від темного до світлого). Чи повинен інвалід () мати можливість це зробити?
MickeyR

@MickeyR ні, не повинно. Перевір мою оновлену відповідь. Якщо ці два варіанти не працюють, вам потрібно буде перезапустити свою діяльність.
Алеадам

Варіант (1) працює. Мій додаток почнеться з правильної теми, але якщо я його зміню під час роботи, мені доведеться перезапустити додаток, щоб onCreate () викликався знову.
MickeyR

Варіант (2) - це маршрут, який я хотів пройти. Отже, коли тема змінюється під час запуску, я хотів, щоб onRestart () зробив це: - setTheme (getPreferenceTheme ()); і setContentView (R.layout.main); Але це не змінює мою тему. Я не можу змусити цей другий варіант працювати ...?!
MickeyR

Я зрозумів, що для отримання опції (2) працюю, мені потрібно "повторно завищити ієрархію перегляду". Я намагався досягти цього різних речей, але я не дуже впевнений, що це означає, ні як це зробити.
MickeyR

41

Спробуйте getWindow().getDecorView().findViewById(android.R.id.content).invalidate();


3
Дякую ! Таку ж відповідь я опублікував вище для Алеадама. Цей недійсний () не спричиняє оновлення теми діяльності, що саме мені потрібно.
MickeyR

36

Спробуйте, recreate()це призведе до відтворення цієї активності.


4
Я спробував усі варіанти в цій темі, і це єдиний, який працював з найменш небажаними побічними ефектами.
swooby

1
Що робити, якщо мені це потрібно зробити onResumeметодом. Це дайте мені нескінченну петлю: /
Каміль Вітковський

Ну, я не рекомендую використовувати його, поки вам справді не потрібно. Ви можете зберегти деякий прапор у спільних налаштуваннях, щоб уникнути нескінченного циклу.
Моханад АЛХОУЛІ

це працює, але я б не рекомендував використовувати його в додатку в режимі реального виробництва. Мені вона потрібна була лише для режиму налагодження, тому побічний ефект від оновлення всього інтерфейсу не є критичним.
drorsun

31

Рішення:

Хлопці, я спробував усі ваші рішення, але вони не працювали для мене, я повинен встановити setVisibility EditText на VISIBLE, і цей EditText повинен бути видно тоді в ScrollView , але я не зміг оновити кореневий вигляд, щоб набути чинності. Я вирішив свою проблему, коли мені потрібно оновити подання, тож я змінив видимість ScrollView на GONE, а потім знову встановив його на VISIBLE, щоб він набрав чинності, і він працював на мене. Це не точне рішення, але воно працювало лише.

 private void refreshView(){
    mScrollView.setVisibility(View.GONE);
    mScrollView.setVisibility(View.VISIBLE);
}

2
@MickeyR Прийміть відповідь, щоб люди могли легко знайти рішення
Naveed Ahmad

Уау .. Я також спробував усі запропоновані рішення, але це, здається, єдине працює, але це жахливо ...
Рік ван Вельцен

Я не знаю, чому @MickeyR не приймає цю відповідь
Naveed Ahmad

1
@NaveedAhmad Дякую! Після 4 годин виконання всього, що я міг, це було єдиним рішенням, яке спрацювало.
Codelicious

10

Виклик invalidate()або postInvalidate()кореневий макет, очевидно, НЕ гарантує, що представлення дітей будуть перероблені. У моєму конкретному випадку мій кореневий макет був TableLayout і мав декількох дітей класу TableRow та TextView. Виклик postInvalidate(), або requestLayout()навіть forceLayout()на кореневої об'єкт TableLayout не викликає ніяких TextViews в макеті , щоб бути перемальовані.

Отже, те, що я в кінцевому підсумку робив, був рекурсивно розбирати макет, шукаючи ці TextViews, а потім викликаючи postInvalidate()кожен з цих об'єктів TextView.

Код можна знайти на GitHub: https://github.com/jkincali/Android-LinearLayout-Parser


9

Інакше ви можете спробувати це також-

ViewGroup vg = (ViewGroup) findViewById (R.id.videoTitleTxtView);
 vg.removeAllViews();
 vg.refreshDrawableState();

4
Дякую за це! Але це видалило всі перегляди, які у мене були (TextView, кнопки тощо), але не повторно намалював їх - мій екран залишився порожнім ...
MickeyR

вам потрібно оновити подання праворуч, тоді вам потрібно зателефонувати знову. після очищення попереднього виду.
Датта Кунде

4

Просто встановіть перегляд вмісту в режимі onuseume

setContentView (R.layout.yourview) всередину onResume ..

Приклад:

@Override
public void onResume(){
super.onResume();
setContentView(R.layout.activity_main); 
postIncomeTotals();
}

Привіт, я спробував це, і ті самі дані в списку переглядаються двічі, отже, якщо у мене було 4 ряди, і оновлення повинно було додати п'ятий ряд, замість цього я закінчую 10, потім 15, ... що робити?
iOSAndroidWindowsMobileAppsDev

4

Спробуйте це вирішити для проблеми з тематикою:

@Override
public void onBackPressed() {
    NavUtils.navigateUpTo(this, new Intent(this,
            MyNeedToBeRefreshed.class));
}

3
Intent intent = getIntent();
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
finish();
startActivity(intent);

Це дозволяє перезавантажити зміни теми та приховати анімації.


3

У мене також була ця проблема, але слідуючи приводом Фархана щодо використання, setContentView()я зробив саме це. setContentView()проте використання їх було недостатньо. Я виявив, що мені довелося переповнити всі свої погляди інформацією. Щоб виправити це, я просто витягнув весь цей код до іншого методу (я назвав його збіркою), і в своєму onCreateметоді я просто викликаю цю збірку. Тепер, коли трапляється моя подія, я хочу, щоб моя активність "оновилася", я просто закликаю збирати, даю їй нову інформацію (яку я передаю як параметри для збирання), і я отримую оновлену активність.


2

Здається, це відома помилка .


setTheme знаходить, коли я перезапускаю свою діяльність (завершення виклику (), а потім startActivity ()). Я просто не можу змусити її оновити тему, не перезавантажуючи свою діяльність ...
MickeyR

0

Я не знаю, це безпечно чи ні, але це працювало на мене. Я начебто зіткнувся з цією проблемою я і спробував invalidate()і , requestLayout()але безрезультатно. Тож я просто зателефонував своїм onCreate(null)знову і це спрацювало. Якщо це небезпечно, будь ласка, повідомте мене. Сподіваюся, це допомагає комусь там.


Ви встановлюєте параметр saveInstanceState до нуля, що може спричинити несподівану поведінку. Для отримання додаткової інформації: stackoverflow.com/questions/15115975 / ...
PhilipB

0

Ось як я використовував для оновлення макета

Intent intent = getIntent();
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION);
finish();
startActivity(intent);

0

Щоб очистити представлення, що розширює ViewGroup, просто потрібно використовувати метод removeAllViews()

Так само (якщо у вас називається ViewGroup myElement):

myElement.removeAllViews()



-8

Просто знову зателефонуйте на активність за допомогою наміру. Наприклад, щоб оновити макет MainActivity, зробіть це так:

startActivity(new Intent(MainActivity.this, MainActivity.class));

2
Це потворно! Коли ви це зробите, ви просто додаєте нову активність у стеці, тож, натиснувши кнопку "назад", ви повернетесь до тієї самої діяльності.
Даніель Белтрамі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.