Làm cách nào để buộc toàn bộ bố cục Xem làm mới?


173

Tôi muốn buộc chế độ xem tài nguyên bố cục chính để vẽ lại / làm mới, nói phương thức Activity.onResume (). Tôi có thể làm cái này như thế nào ?

Theo chế độ xem bố cục chính, ý tôi là cái ('R.layout.mainscreen' bên dưới) được gọi trong Activity.onCreate () của tôi, như thế này: -

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

Bạn đã thử đặt tên tuyến tính / Relative / AnyLayout kèm theo của mình, gọi findViewById trên đó và sau đó gọi không hợp lệ () trên đó? (Tôi sẽ đặt câu hỏi này làm câu trả lời, nhưng tôi không biết nếu cha mẹ vô hiệu cũng làm mất hiệu lực của con cái và tôi không ở đâu tôi có thể kiểm tra nó.)
Ben Williams

Cũng cảm ơn ! Tôi vẫn đang vật lộn với điều này mặc dù. Bạn có thể xem những gì tôi đã đăng dưới đây. Tôi cần mã này (hoặc mã khác?) Để làm cho chủ đề của tôi được làm mới ...
MickeyR

Câu trả lời:


149

Để trả lời đúng câu hỏi: Sử dụng không hợp lệ ():

công khai void voidate () Kể từ: API Cấp 1

Vô hiệu toàn bộ khung nhìn. Nếu chế độ xem hiển thị, onDraw (Canvas) sẽ được gọi tại một số điểm trong tương lai. Điều này phải được gọi từ một chủ đề UI. Để gọi từ một luồng không phải UI, hãy gọi postInvalidate ().

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

Bây giờ, khi Hoạt động trở lại, nó làm cho mọi Chế độ xem tự vẽ. Không cần gọi để vô hiệu hóa (). Để áp dụng chủ đề, hãy đảm bảo bạn thực hiện trước khi bất kỳ Chế độ xem nào được vẽ, tức là trước khisetContentView(R.layout.mainscreen);

công khai void setTheme (int Resid) Kể từ: API Cấp 1

Đặt chủ đề cơ sở cho bối cảnh này. Lưu ý rằng điều này nên được gọi trước khi bất kỳ chế độ xem nào được khởi tạo trong Ngữ cảnh (ví dụ trước khi gọi setContentView (Chế độ xem) hoặc lạm phát (int, Viewgroup)).

Tham chiếu tài liệu API có tại đây: http://developer.android.com/reference/android/view/ContextThemeWrapper.html#setTheme%28int%29

Vì phương thức onDraw () hoạt động trên các Chế độ xem đã được khởi tạo, setTheme sẽ không hoạt động. Bản thân tôi không có kinh nghiệm về các chủ đề, nhưng hai lựa chọn thay thế tôi có thể nghĩ là:

  1. gọi setTheme trong onCreate () thay vào đó, hoặc
  2. làm lại setContentView (R.layout.mainscreen); để buộc tái hiện tất cả các bố trí.

Cảm ơn ! Điều này chạy ổn, nhưng tôi không thấy những gì tôi mong đợi. Ngay trước khi chạy mã của bạn, tôi chạy Activity.setTheme (newtheme) nhưng lệnh gọi () không hợp lệ này không làm cho chủ đề thay đổi (ví dụ: từ Dark sang Light). Có nên làm mất hiệu lực () để có thể làm điều đó?
MickeyR

@MickeyR không, không nên. Kiểm tra câu trả lời cập nhật của tôi. Nếu hai tùy chọn đó không hoạt động, bạn sẽ cần khởi động lại Hoạt động của mình.
Aleadam

Tùy chọn (1) không hoạt động. Ứng dụng của tôi sẽ bắt đầu với chủ đề chính xác, nhưng nếu tôi thay đổi nó trong khi chạy, tôi phải khởi động lại ứng dụng của mình để onCreate () được gọi lại.
MickeyR

Tùy chọn (2) là con đường tôi muốn đi. Vì vậy, khi chủ đề được thay đổi trong khi chạy, tôi muốn onRestart () thực hiện việc này: - setTheme (getPreferenceTheme ()); và setContentView (R.layout.main); Nhưng điều này không thay đổi chủ đề của tôi. Tôi không thể có tùy chọn thứ hai này để làm việc ...?!
MickeyR

Tôi hiểu rằng để có được tùy chọn (2) hoạt động, tôi cần phải 'tăng lại hệ thống phân cấp chế độ xem'. Tôi đã thử nhiều thứ khác nhau để đạt được điều này, nhưng tôi không thực sự chắc chắn điều này có nghĩa là gì và làm thế nào để làm điều này.
MickeyR

41

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


3
Cảm ơn ! Câu trả lời tương tự tôi đã đăng ở trên để Aleadam. Điều này không hợp lệ () không làm cho chủ đề hoạt động làm mới đó là những gì tôi cần.
MickeyR

36

Hãy thử recreate()nó sẽ khiến Hoạt động này được tạo lại.


4
Tôi đã thử tất cả các tùy chọn trong chuỗi này và đây là lựa chọn duy nhất hoạt động với các tác dụng phụ ít mong muốn nhất.
swooby

1
Điều gì nếu tôi cần điều này để làm trong onResumephương pháp. Điều này mang lại cho tôi vòng lặp vô hạn: /
Kamil Witkowski

Vâng, tôi không khuyên bạn nên sử dụng nó cho đến khi bạn thực sự cần. Bạn có thể lưu một số cờ trong tùy chọn chia sẻ để tránh vòng lặp vô hạn.
Mohanad ALKHOULI

Điều này hoạt động nhưng tôi không khuyên bạn nên sử dụng nó trong ứng dụng chế độ sản xuất thực. Tôi chỉ cần nó cho chế độ gỡ lỗi nên tác dụng phụ của toàn bộ giao diện người dùng là không quan trọng.
drorsun

31

Giải pháp:

Các bạn tôi đã thử tất cả các Giải pháp của bạn nhưng chúng không hiệu quả với tôi, tôi phải đặt setVisibility của EditText thành VISIBLE và Chỉnh sửa này sẽ hiển thị sau đó trong ScrollView , nhưng tôi không thể làm mới chế độ xem gốc để có hiệu lực. Tôi đã giải quyết vấn đề của mình, khi tôi cần làm mới chế độ xem, vì vậy tôi đã thay đổi chế độ hiển thị ScrollView thành Gone và sau đó đặt lại thành VISIBLE để có hiệu lực và nó hoạt động với tôi. Đây không phải là giải pháp chính xác nhưng nó chỉ hoạt động.

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

2
@MickeyR Vui lòng chấp nhận câu trả lời, để mọi người có thể tìm thấy giải pháp một cách dễ dàng
Naveed Ahmad

wow .. Tôi cũng đã thử tất cả các đề xuất được đề xuất nhưng đây dường như là cách duy nhất hoạt động, nhưng nó thật kinh khủng ...
Rik van Velzen

Tôi không biết tại sao @MickeyR không chấp nhận câu trả lời này
Naveed Ahmad

1
@NaveedAhmad Cảm ơn bạn! Sau 4 giờ làm tất cả những gì tôi có thể, đây là giải pháp duy nhất có hiệu quả.
Codelicy

10

Gọi điện thoại invalidate()hoặc postInvalidate()bố trí gốc rõ ràng KHÔNG đảm bảo rằng các khung nhìn của trẻ em sẽ được vẽ lại. Trong trường hợp cụ thể của tôi, bố cục gốc của tôi là TableLayout và có một vài đứa con của lớp TableRow và TextView. Việc gọi postInvalidate(), hoặc requestLayout()thậm chí forceLayout()trên đối tượng TableLayout gốc không khiến bất kỳ TextView nào trong bố cục được vẽ lại.

Vì vậy, những gì tôi đã làm cuối cùng là phân tích cú pháp bố cục tìm kiếm các TextView đó và sau đó gọi postInvalidate()từng đối tượng TextView đó.

Mã có thể được tìm thấy trên GitHub: https://github.com/jkincali/Android-LinearLayout-Parser


9

Nếu không, bạn cũng có thể thử điều này-

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

4
Cảm ơn vì điều đó ! Nhưng, điều này đã xóa tất cả các Chế độ xem tôi có (TextView, Nút, v.v.) nhưng không vẽ lại chúng - màn hình của tôi vẫn trống ...
MickeyR

bạn cần làm mới khung nhìn của mình ngay, sau đó bạn cần gọi lại hàm vẽ. sau khi làm sạch quan điểm trước đó.
Datta Kunde

4

Chỉ cần đặt chế độ xem nội dung của bạn trong onresume

setContentView (R.layout.yourview) bên trong onResume ..

Thí dụ:

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

Xin chào Tôi đã thử điều này và cùng một dữ liệu trong listview được kéo hai lần, do đó nếu tôi có 4 hàng và làm mới được cho là thêm một hàng thứ năm, thay vào đó tôi kết thúc với 10, rồi 15, ... tôi phải làm gì?
iOSAndroidWindowsMobileAppsDev

4

Hãy thử cách giải quyết này cho vấn đề theo chủ đề:

@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);

Điều này cho phép bạn tải lại với các thay đổi chủ đề và ẩn các hình ảnh động.


3

Tôi cũng gặp vấn đề này nhưng sau khi sử dụng Farhan, setContentView()tôi đã làm như vậy. sử dụng setContentView()bởi chính nó là không đủ tuy nhiên. Tôi thấy rằng tôi phải lấy lại tất cả các quan điểm của mình bằng thông tin. Để sửa lỗi này, tôi chỉ cần kéo tất cả mã đó ra một phương thức khác (tôi gọi nó là bản dựng) và trong onCreatephương thức của tôi, tôi chỉ gọi bản dựng đó. Bây giờ bất cứ khi nào sự kiện của tôi xảy ra là tôi muốn hoạt động của mình "làm mới", tôi chỉ cần gọi xây dựng, cung cấp cho nó thông tin mới (mà tôi chuyển vào dưới dạng tham số để xây dựng) và tôi có một hoạt động được làm mới.


2

Đây dường như là một lỗi đã biết .


setTheme hoạt động tìm thấy khi tôi khởi động lại hoạt động của mình (kết thúc cuộc gọi () và sau đó startActivity ()). Tôi chỉ không thể lấy nó để làm mới chủ đề mà không khởi động lại hoạt động của mình ...
MickeyR

0

Tôi không biết điều này có an toàn hay không nhưng nó hiệu quả với tôi. Tôi kinda chạy vào vấn đề này bản thân mình và cố gắng invalidate()requestLayout()nhưng vô ích. Vì vậy, tôi chỉ cần gọi lại onCreate(null)tất cả và nó đã làm việc. Nếu điều này không an toàn xin vui lòng cho tôi biết. Hy vọng điều này sẽ giúp ai đó ngoài kia.


Bạn đang đặt saveInstanceState thành null có thể gây ra hành vi không mong muốn. Để biết thêm thông tin: stackoverflow.com/questions/15115975/ từ
PhilipB

0

Đây là cách tôi sử dụng để làm mới bố cục của mình

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

0

Để xóa chế độ xem mở rộng Viewgroup, bạn chỉ cần sử dụng phương thức removeAllViews()

Giống như thế này (nếu bạn có Viewgroup được gọi myElement):

myElement.removeAllViews()


-1

Không chắc chắn nếu đó là cách tiếp cận tốt nhưng tôi chỉ gọi điều này mỗi lần:

setContentView(R.layout.mainscreen);

-8

Chỉ cần gọi lại hoạt động chính nó bằng cách sử dụng ý định. Ví dụ: để làm mới bố cục của MainActivity, hãy làm như sau:

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

2
Thật là xấu xí! Khi bạn làm điều này, bạn chỉ cần thêm một hoạt động mới trên ngăn xếp, vì vậy, khi bạn nhấn nút quay lại, bạn sẽ quay lại hoạt động tương tự.
Daniel Beltrami
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.