Bagaimana cara memaksa seluruh tampilan tata letak penyegaran?

173

Saya ingin memaksa tampilan sumber daya tata letak utama untuk menggambar ulang / menyegarkan, katakanlah metode Activity.onResume (). Bagaimana saya bisa melakukan ini?

Dengan tampilan tata letak utama, maksud saya yang ('Layarlay.mainscreen' di bawah) yang disebut di Activity.onCreate () saya, seperti ini: -

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.mainscreen);
}
MickeyR
sumber
Sudahkah Anda mencoba memberi nama Linear / Relative / whateverLayout, dengan memanggil findViewById di atasnya, dan kemudian memanggil invalidate () untuk itu? (Saya akan meletakkan ini sebagai jawaban, tetapi saya tidak tahu apakah orangtua yang batal juga membuat anak-anak tidak valid dan saya tidak berada di tempat yang bisa saya uji.)
Ben Williams
Terima kasih juga ! Saya masih berjuang dengan ini. Bisakah Anda melihat apa yang saya posting di bawah ini. Saya memerlukan kode ini (atau lainnya?) Untuk membuat tema saya menjadi
segar

Jawaban:

149

Untuk benar-benar menjawab pertanyaan: Gunakan invalidate ():

public void invalidate () Sejak: API Level 1

Batalkan seluruh tampilan. Jika tampilan terlihat, onDraw (Kanvas) akan dipanggil di beberapa titik di masa depan. Ini harus dipanggil dari utas UI. Untuk menelepon dari utas non-UI, panggil postInvalidate ().

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

Sekarang, ketika Kegiatan dilanjutkan, itu membuat setiap Tampilan untuk menggambar sendiri. Tidak boleh ada panggilan untuk membatalkan (). Untuk menerapkan tema, pastikan Anda melakukannya sebelum Lihat apa pun diambil, yaitu sebelumnyasetContentView(R.layout.mainscreen);

public void setTheme (int resid) Sejak: API Level 1

Tetapkan tema dasar untuk konteks ini. Perhatikan bahwa ini harus dipanggil sebelum tampilan ditampilkan dalam Konteks (misalnya sebelum memanggil setContentView (View) atau mengembang (int, ViewGroup)).

Referensi dokumen API ada di sini: http://developer.android.com/reference/android/view/ContextThemeWrapper.html#setTheme%28int%29

Karena metode onDraw () berfungsi pada Views yang sudah dipakai, setTheme tidak akan berfungsi. Saya sendiri tidak punya pengalaman dengan tema, tetapi dua opsi alternatif yang bisa saya pikirkan adalah:

  1. panggil setTheme di onCreate () sebagai gantinya, atau
  2. ulang setContentView (R.layout.mainscreen); untuk memaksa mengembalikan semua tata letak.
Aleadam
sumber
Terima kasih! Ini berjalan oke, tapi saya tidak melihat apa yang saya harapkan. Tepat sebelum menjalankan kode Anda, saya menjalankan Activity.setTheme (newtheme) tetapi panggilan yang tidak valid () ini tidak menyebabkan tema berubah (misalnya dari Gelap ke Terang). Haruskah invalidate () dapat melakukan itu?
MickeyR
@MickeyR tidak, seharusnya tidak. Periksa jawaban saya yang diperbarui. Jika kedua opsi tersebut tidak berfungsi, Anda harus memulai kembali Aktivitas Anda.
Aleadam
Opsi (1) tidak berfungsi. Aplikasi saya akan mulai dengan tema yang benar, tetapi jika saya mengubahnya saat berjalan, saya harus memulai kembali aplikasi saya sehingga onCreate () dipanggil kembali.
MickeyR
Opsi (2) adalah rute yang ingin saya ambil. Jadi, ketika tema diubah saat berjalan, saya ingin onRestart () melakukan hal ini: - setTheme (getPreferenceTheme ()); dan setContentView (R.layout.main); Tapi ini tidak mengubah tema saya. Saya tidak dapat mengaktifkan opsi kedua ini ...?!
MickeyR
Saya mengerti bahwa untuk mendapatkan opsi (2) berfungsi, saya perlu 'mengembang ulang hierarki tampilan'. Saya sudah mencoba berbagai hal untuk mencapai ini, tetapi saya tidak begitu yakin apa artinya ini atau bagaimana melakukan ini.
MickeyR
41

Mencoba getWindow().getDecorView().findViewById(android.R.id.content).invalidate();

keyboardsurfer
sumber
3
Terima kasih! Jawaban yang sama saya posting di atas untuk Aleadam. Invalidate () ini tidak menyebabkan tema aktivitas me-refresh yang saya butuhkan.
MickeyR
36

Coba recreate()ini akan menyebabkan Kegiatan ini diciptakan kembali.

Mohanad ALKHOULI
sumber
4
Saya mencoba semua opsi di utas ini, dan ini adalah satu-satunya yang bekerja dengan efek samping yang paling tidak diinginkan.
swooby
1
Bagaimana jika saya perlu melakukan ini dalam onResumemetode. Ini memberi saya infinte loop: /
Kamil Witkowski
Yah saya tidak menyarankan menggunakannya sampai Anda benar-benar membutuhkannya. Anda dapat menyimpan beberapa flag di preferensi bersama untuk menghindari loop tak terbatas.
Mohanad ALKHOULI
ini berfungsi tetapi saya tidak akan merekomendasikan menggunakannya dalam aplikasi mode produksi nyata. Saya hanya membutuhkannya untuk mode debug sehingga efek samping dari penyegaran seluruh UI tidak kritis.
drorsun
31

Larutan:

Guys Saya mencoba semua Solusi Anda tetapi mereka tidak bekerja untuk saya, saya harus mengatur setVisibility dari EditText ke VISIBLE dan EditText ini akan terlihat kemudian di ScrollView , tetapi saya tidak dapat me-refresh tampilan root untuk mulai berlaku. Saya memecahkan masalah saya, ketika saya perlu menyegarkan tampilan jadi saya mengubah visibilitas ScrollView ke GONE dan kemudian mengaturnya kembali ke VISIBLE untuk mengambil efek dan itu berhasil untuk saya. Ini bukan solusi yang tepat tetapi hanya berhasil.

 private void refreshView(){
    mScrollView.setVisibility(View.GONE);
    mScrollView.setVisibility(View.VISIBLE);
}
Naveed Ahmad
sumber
2
@MickeyR Harap terima jawaban, sehingga orang dapat menemukan solusinya dengan mudah
Naveed Ahmad
wow .. Saya juga mencoba semua solusi yang diusulkan tetapi ini tampaknya menjadi satu-satunya yang berfungsi, tetapi ini agak mengerikan ...
Rik van Velzen
Saya tidak tahu mengapa @MickeyR tidak menerima jawaban ini
Naveed Ahmad
1
@NaveedAhmad Terima kasih! Setelah 4 jam melakukan semua yang saya bisa, ini adalah satu-satunya solusi yang berhasil.
Codelicious
10

Memanggil invalidate()atau postInvalidate()pada tata letak root tampaknya TIDAK menjamin bahwa tampilan anak-anak akan digambar ulang. Dalam kasus khusus saya, tata letak root saya adalah TableLayout dan memiliki beberapa anak dari kelas TableRow dan TextView. Memanggil postInvalidate(), atau requestLayout()atau bahkan forceLayout()pada objek TableLayout root tidak menyebabkan TextViews di tata letak digambar ulang.

Jadi, apa yang akhirnya saya lakukan adalah secara rekursif mengurai tata letak mencari TextViews tersebut dan kemudian memanggil postInvalidate()masing-masing objek TextView tersebut.

Kode tersebut dapat ditemukan di GitHub: https://github.com/jkincali/Android-LinearLayout-Parser

jkincali
sumber
9

Kalau tidak, Anda dapat mencoba ini juga-

ViewGroup vg = (ViewGroup) findViewById (R.id.videoTitleTxtView);
 vg.removeAllViews();
 vg.refreshDrawableState();
Datta Kunde
sumber
4
Terima kasih untuk ini ! Tapi, ini menghapus semua Tampilan yang saya punya (TextView, Buttons dll) tetapi tidak menggambar ulang mereka - layar saya tetap kosong ...
MickeyR
Anda perlu menyegarkan tampilan Anda dengan benar, maka Anda perlu memanggil fungsi menggambar lagi. setelah membersihkan tampilan sebelumnya.
Datta Kunde
4

Cukup atur tampilan konten Anda di onresume

setContentView (R.layout.yourview) di dalam onResume ..

Contoh:

@Override
public void onResume(){
super.onResume();
setContentView(R.layout.activity_main); 
postIncomeTotals();
}
Farhan
sumber
Hai Saya mencoba ini dan data yang sama di listview ditarik dua kali, maka jika saya punya 4 baris dan refresh seharusnya menambahkan baris kelima, alih-alih saya berakhir dengan 10, lalu 15, ... apa yang harus saya lakukan?
iOSAndroidWindowsMobileAppsDev
4

Coba solusi ini untuk masalah tema:

@Override
public void onBackPressed() {
    NavUtils.navigateUpTo(this, new Intent(this,
            MyNeedToBeRefreshed.class));
}
Krilivye
sumber
3
Intent intent = getIntent();
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
finish();
startActivity(intent);

Ini memungkinkan Anda memuat ulang dengan perubahan tema dan menyembunyikan animasinya.

Kode terbalik
sumber
3

Saya juga mengalami masalah ini, tetapi mengikuti petunjuk Farhan tentang penggunaan, setContentView()saya melakukannya. menggunakan setContentView()dengan sendirinya tidak cukup. Saya menemukan bahwa saya harus mengisi kembali semua pandangan saya dengan informasi. Untuk memperbaikinya saya hanya menarik semua kode itu ke metode lain (saya menyebutnya build) dan dalam onCreatemetode saya, saya hanya memanggil build itu. Sekarang setiap kali acara saya terjadi bahwa saya ingin aktivitas saya "menyegarkan", saya sebut saja build, berikan informasi baru (yang saya sampaikan sebagai parameter untuk membangun) dan saya memiliki aktivitas yang disegarkan.

pengguna3612162
sumber
2

Tampaknya ini adalah bug yang dikenal .

Ben Williams
sumber
setTheme berfungsi menemukan ketika saya me-restart aktivitas saya (panggilan selesai () dan kemudian startActivity ()). Saya tidak bisa membuatnya untuk menyegarkan tema tanpa memulai kembali aktivitas saya ...
MickeyR
0

Saya tidak tahu apakah ini aman atau tidak tetapi itu berhasil untuk saya. Aku agak berlari ke dalam masalah ini sendiri dan mencoba invalidate()dan requestLayout()tetapi tidak berhasil. Jadi saya baru saja menelepon saya onCreate(null)lagi dan berhasil. Jika ini tidak aman, harap beri tahu saya. Semoga ini bisa membantu seseorang di luar sana.

Cai
sumber
Anda mengatur saveInstanceState ke nol yang dapat menyebabkan perilaku yang tidak terduga. Untuk informasi lebih lanjut: stackoverflow.com/questions/15115975/…
PhilipB
0

Ini adalah bagaimana saya digunakan untuk Me-refresh tata letak saya

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

Untuk menghapus tampilan yang memperluas ViewGroup, Anda hanya perlu menggunakan metode ini removeAllViews()

Sama seperti ini (jika Anda memiliki ViewGroup yang dipanggil myElement):

myElement.removeAllViews()
Mendongkrak'
sumber
0

Coba ini

view.requestLayout();
Milind Chaudhary
sumber
-1

Tidak yakin apakah itu pendekatan yang baik tetapi saya hanya menyebutnya setiap kali:

setContentView(R.layout.mainscreen);
Krzysztof Tkacz
sumber
-8

Panggil lagi aktivitas itu sendiri menggunakan niat. Misalnya untuk menyegarkan tata letak MainActivity, lakukan seperti ini:

startActivity(new Intent(MainActivity.this, MainActivity.class));
Anshul Aggarwal
sumber
2
Itu jelek! Ketika Anda melakukan ini, Anda hanya menambahkan aktivitas baru di tumpukan, jadi, ketika Anda menekan tombol kembali, Anda akan kembali ke aktivitas yang sama.
Daniel Beltrami