วิธีการบังคับให้รูปแบบทั้งหมดดูการรีเฟรช?


173

ฉันต้องการบังคับให้มุมมองทรัพยากรเค้าโครงหลักที่จะวาดใหม่ / รีเฟรชในพูดว่าวิธีการ Activity.onResume () ฉันจะทำสิ่งนี้ได้อย่างไร

ตามมุมมองเลย์เอาต์หลักฉันหมายถึงหนึ่ง ('R.layout.mainscreen' ด้านล่าง) ที่เรียกว่าใน Activity.onCreate () ของฉันดังนี้: -

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

คุณได้ลองตั้งชื่อ Linear / Relative / AnythingLayout ที่ล้อมรอบของคุณแล้วโทรหา findViewById จากนั้นจึงโทรหาโมฆะ () ในสิ่งนั้นหรือไม่ (ฉันใส่นี้เป็นคำตอบ แต่ผมไม่ทราบว่าถ้าพ่อแม่ไม่ถูกต้องยังเลิกเด็กและฉันไม่ได้อยู่ที่ไหนสักแห่งที่ฉันสามารถทดสอบมัน.)
เบนวิลเลียมส์

ขอขอบคุณ! ฉันยังคงดิ้นรนกับเรื่องนี้ คุณช่วยดูสิ่งที่ฉันโพสต์ด้านล่าง ฉันต้องการรหัสนี้ (หรืออื่น ๆ ) เพื่อทำให้ธีมของฉันรีเฟรช ...
MickeyR

คำตอบ:


149

หากต้องการตอบคำถามอย่างเคร่งครัด: ใช้โมฆะ ():

โมฆะสาธารณะเป็นโมฆะ () ตั้งแต่: API ระดับ 1

ทำให้มุมมองทั้งหมดไม่ถูกต้อง หากมองเห็นได้จะมีการเรียกใช้ onDraw (Canvas) ในอนาคต ต้องเรียกใช้จากเธรด UI หากต้องการโทรจากเธรดที่ไม่ใช่ UI ให้โทร postInvalidate ()

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

ตอนนี้เมื่อกิจกรรมดำเนินการต่อมันทำให้ทุกมุมมองวาดตัวเอง ไม่จำเป็นต้องมีการโทรเพื่อทำให้เป็นโมฆะ () ในการใช้ชุดรูปแบบตรวจสอบให้แน่ใจว่าคุณทำก่อนที่จะดึงมุมมองใด ๆ เช่นก่อนหน้าsetContentView(R.layout.mainscreen);

โมฆะสาธารณะ setTheme (ที่เหลือ int) ตั้งแต่: API ระดับ 1

ตั้งค่าธีมพื้นฐานสำหรับบริบทนี้ โปรดทราบว่าสิ่งนี้ควรถูกเรียกก่อนมุมมองใด ๆ จะถูกสร้างอินสแตนซ์ในบริบท (ตัวอย่างก่อนที่จะเรียก setContentView (มุมมอง) หรือขยาย (int, ViewGroup)

การอ้างอิงเอกสาร API อยู่ที่นี่: http://developer.android.com/reference/android/view/ContextThemeWrapper.html#setTheme%28int%29

เนื่องจากเมธอด onDraw () ทำงานกับมุมมองที่อินสแตนซ์แล้ว setTheme จะไม่ทำงาน ฉันไม่มีประสบการณ์เกี่ยวกับชุดรูปแบบ แต่มีสองตัวเลือกทางเลือกที่ฉันสามารถคิดได้:

  1. โทร setTheme ใน onCreate () แทนหรือ
  2. ทำซ้ำ setContentView (R.layout.mainscreen); เพื่อบังคับให้จัดโครงสร้างใหม่ทั้งหมด

ขอบคุณมาก! สิ่งนี้ทำงานได้ดี แต่ฉันไม่เห็นสิ่งที่ฉันคาดไว้ ก่อนเรียกใช้รหัสของคุณฉันเรียกใช้ Activity.setTheme (newtheme) แต่การโทรที่ไม่ถูกต้อง () นี้ไม่ทำให้ธีมเปลี่ยนไป (เช่นจากมืดเป็นสว่าง) ควรทำให้โมฆะ () สามารถทำเช่นนั้นได้หรือไม่
MickeyR

@ MickeyR ไม่มันไม่ควร ตรวจสอบคำตอบที่อัปเดตของฉัน หากทั้งสองตัวเลือกไม่ทำงานคุณจะต้องเริ่มกิจกรรมใหม่
Aleadam

ตัวเลือก (1) ใช้งานได้ แอพของฉันจะเริ่มต้นด้วยชุดรูปแบบที่ถูกต้อง แต่ถ้าฉันเปลี่ยนในขณะที่ทำงานฉันต้องเริ่มต้นแอพใหม่อีกครั้งเพื่อให้ onCreate () ถูกเรียกอีกครั้ง
MickeyR

ตัวเลือก (2) เป็นเส้นทางที่ฉันต้องการใช้ ดังนั้นเมื่อธีมเปลี่ยนไปในขณะที่ทำงานฉันต้องการ onRestart () เพื่อทำสิ่งนี้: - setTheme (getPreferenceTheme ()); และ setContentView (R.layout.main); แต่นี่ไม่เปลี่ยนธีมของฉัน ฉันไม่สามารถใช้ตัวเลือกที่สองนี้เพื่อทำงาน ... ?!
MickeyR

ฉันเข้าใจว่าเพื่อให้ได้ตัวเลือก (2) การทำงานฉันต้อง 'ขยายมุมมองลำดับชั้นใหม่' ฉันได้ลองทำสิ่งต่าง ๆ เพื่อให้ได้สิ่งนี้ แต่ฉันไม่แน่ใจว่าสิ่งนี้หมายความว่าอย่างไรและทำอย่างไร
MickeyR

41

ลอง getWindow().getDecorView().findViewById(android.R.id.content).invalidate();


3
ขอบคุณมาก! คำตอบเดียวกันฉันโพสต์ข้างต้นเพื่อ Aleadam โมฆะนี้ () ไม่ได้ทำให้ชุดรูปแบบของกิจกรรมรีเฟรชซึ่งเป็นสิ่งที่ฉันต้องการ
MickeyR

36

ลองrecreate()มันจะทำให้กิจกรรมนี้ถูกสร้างขึ้นใหม่


4
ฉันลองตัวเลือกทั้งหมดในชุดข้อความนี้และนี่เป็นตัวเลือกเดียวที่ทำงานกับผลข้างเคียงที่ไม่พึงประสงค์น้อยที่สุด
swooby

1
ถ้าฉันต้องการสิ่งนี้ให้ทำตามonResumeวิธี นี่ให้ห่วงฉันไม่ได้: /
Kamil Witkowski

ฉันไม่แนะนำให้ใช้จนกว่าคุณจะต้องการจริงๆ คุณสามารถบันทึกการตั้งค่าสถานะบางอย่างในการตั้งค่าที่ใช้ร่วมกันเพื่อหลีกเลี่ยงการวนซ้ำไม่สิ้นสุด
Mohanad ALKHOULI

ใช้งานได้ แต่ฉันจะไม่แนะนำให้ใช้ในแอพโหมดการใช้งานจริง ฉันต้องการเฉพาะโหมด debug เท่านั้นดังนั้นผลข้างเคียงของการรีเฟรช UI ทั้งหมดนั้นไม่สำคัญ
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

ว้าว .. ฉันยังลองใช้วิธีแก้ปัญหาทั้งหมดที่เสนอ แต่ดูเหมือนว่าจะเป็นงานเดียว แต่มันก็น่ากลัว ...
Rik van Velzen

ฉันไม่รู้ว่าทำไม @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

คุณต้องรีเฟรชมุมมองของคุณจากนั้นคุณต้องเรียกใช้ฟังก์ชันการวาดอีกครั้ง หลังจากล้างมุมมองก่อนหน้า
Datta Kunde

4

เพียงตั้งค่ามุมมองเนื้อหาของคุณในการดำเนินการต่อ

setContentView (R.layout.yourview) ภายใน onResume ..

ตัวอย่าง:

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

สวัสดีฉันลองและข้อมูลเดียวกันในลิสต์วิวถูกดึงสองครั้งดังนั้นถ้าฉันมี 4 แถวและรีเฟรชควรเพิ่มแถวที่ห้าแทนฉันจบด้วย 10, 15 จากนั้น 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

ฉันมีปัญหานี้เช่นกัน แต่หลังจากการใช้งานของ Farhan setContentView()ฉันก็ทำเช่นนั้น อย่างไรก็ตามการใช้setContentView()โดยตัวมันเองยังไม่เพียงพอ ฉันพบว่าฉันต้องเติมความคิดเห็นทั้งหมดของฉันด้วยข้อมูล เพื่อแก้ไขปัญหานี้ฉันเพิ่งดึงรหัสนั้นออกไปยังวิธีอื่น (ฉันเรียกมันว่าบิลด์) และในonCreateวิธีการของฉันฉันเรียกว่าบิลด์นั้น ตอนนี้เมื่อใดก็ตามที่เหตุการณ์ของฉันเกิดขึ้นที่ฉันต้องการให้กิจกรรมของฉัน "รีเฟรช" ฉันเพิ่งเรียกบิลด์ให้ข้อมูลใหม่ (ซึ่งฉันผ่านเป็นพารามิเตอร์ในการสร้าง) และฉันมีกิจกรรมรีเฟรช


2

นี้ดูเหมือนจะเป็นปัญหาที่รู้จักกัน


setTheme หาได้เมื่อฉันเริ่มกิจกรรมใหม่ (โทรเสร็จสิ้น () แล้วเริ่ม startActivity () ฉันไม่สามารถได้รับมันจะฟื้นฟูรูปแบบโดยไม่ต้องรีสตาร์ทกิจกรรมของฉัน ...
MickeyR

0

ฉันไม่รู้ว่ามันปลอดภัยหรือไม่ แต่มันก็ใช้ได้กับฉัน ฉันวิ่งเข้าไปในปัญหานี้ด้วยตัวเองและพยายามinvalidate()แล้วrequestLayout()แต่ก็ไม่มีประโยชน์ ดังนั้นฉันเพียงแค่เรียกฉันonCreate(null)ทั้งหมดอีกครั้งและมันทำงานได้ หากไม่ปลอดภัยโปรดแจ้งให้เราทราบ หวังว่านี่จะช่วยให้ใครบางคนที่นั่น


คุณกำลังตั้งค่า SaveInstanceState เป็น null ซึ่งอาจทำให้เกิดพฤติกรรมที่ไม่คาดคิด สำหรับข้อมูลเพิ่มเติม: 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()


-1

ไม่แน่ใจว่ามันเป็นวิธีการที่ดีหรือไม่ แต่ฉันเรียกสิ่งนี้ทุกครั้ง:

setContentView(R.layout.mainscreen);

-8

เพียงเรียกกิจกรรมอีกครั้งโดยใช้ความตั้งใจ ตัวอย่างเช่นเพื่อรีเฟรชเลย์เอาต์ของ MainActivity ให้ทำดังนี้:

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

2
นั่นน่าเกลียด! เมื่อคุณทำสิ่งนี้คุณเพียงแค่เพิ่มกิจกรรมใหม่ในสแต็คดังนั้นเมื่อคุณกดปุ่มย้อนกลับคุณจะกลับไปที่กิจกรรมเดียวกัน
Daniel Beltrami
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.