แสดงส่วนซ่อนใน Android


100

ฉันกำลังพัฒนาแอพพลิเคชั่นที่มีชิ้นส่วน 2 ชิ้นและฉันต้องการแสดงการซ่อนตามความต้องการของฉัน รหัสต่อไปนี้มีตัวอย่างง่ายๆของปัญหาของฉัน Fragmentactivity แบบธรรมดานี้ประกอบด้วยปุ่ม 1 ปุ่มและส่วนรายการเดียว

ตัวอย่างง่ายๆนี้ทำงานได้อย่างไม่มีที่ติ แต่ฉันไม่พอใจกับการแสดงส่วนซ่อน หากคุณลบ layout.setVisibility (View.GONE); จากรหัสแล้ว ft.hide (f); จะไม่ซ่อนส่วน ในความเป็นจริงเราไม่ได้ซ่อนชิ้นส่วนเรากำลังซ่อนภาชนะ

คำถามของฉันคือวิธีนี้เป็นวิธีแสดงชิ้นส่วนซ่อนหรือไม่ หากไม่เป็นเช่นนั้นโปรดอธิบายด้วยตัวอย่างทดสอบวิธีซ่อนและแสดง Fragments เนื่องจากผู้คนจำนวนมากกำลังประสบปัญหานี้

 public class MainActivity extends FragmentActivity implements OnClickListener {

        Fragment1 f;
        Button b;
        LinearLayout layout;
        Fragment myf;
        @Override
        public void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            b = (Button) findViewById(R.id.button1);
            layout = (LinearLayout) findViewById(R.id.ll);
            f = new Fragment1();
        }

        @Override
        public void onClick(View v) {

            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);

            if (f.isHidden()) {
                ft.show(f);
                layout.setVisibility(View.VISIBLE);
                b.setText("Hide");
            } else {
                ft.hide(f);
                b.setText("Show");
                layout.setVisibility(View.GONE);
            }
            ft.commit();
            // TODO Auto-generated method stub
        }

ทำไมคุณต้องตั้งค่าการเปิดเผยคอนเทนเนอร์? ควรใช้งานได้โดยไม่ต้องตั้งค่าการเปิดเผย
Andrii Chernenko

แน่นอนว่าควรใช้งานได้โดยไม่มีการมองเห็นคอนเทนเนอร์ แต่ไม่ทำงาน ได้โปรดกรุณาแบ่งปันตัวอย่างการทำงานง่ายๆกับฉัน แล้วฉันจะรู้ว่าฉันหายไปไหน
abidkhan303

1
ฉันเดาว่าคุณพยายามแสดง / ซ่อนอินสแตนซ์ของส่วนต่างๆในแต่ละครั้ง เมื่อคุณเพิ่มส่วนของคุณ (ฉันไม่เห็นชิ้นส่วนของโค้ดนี้) ให้เพิ่มด้วยแท็กแล้วเรียกคืนโดยแท็กนั้น (แทนที่จะพยายามจัดเก็บข้อมูลอ้างอิง) นั่นอาจเป็นสิ่งที่คุณขาดหายไป
Andrii Chernenko

คำตอบ:


162

อย่ายุ่งกับแฟล็กการมองเห็นของคอนเทนเนอร์ - FragmentTransaction.hide / show ทำเพื่อคุณเป็นการภายใน

ดังนั้นวิธีที่ถูกต้องในการดำเนินการนี้คือ:

FragmentManager fm = getFragmentManager();
fm.beginTransaction()
          .setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out)
          .show(somefrag)
          .commit();

หรือหากคุณใช้ android.support.v4.app.Fragment

 FragmentManager fm = getSupportFragmentManager();
 fm.beginTransaction()
          .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out)
          .show(somefrag)
          .commit();

5
เหตุใดคุณจึงแนะนำให้ไม่ยุ่งกับแฟล็กโดยตรง (ฉันไม่ได้โต้แย้งคำแนะนำของคุณเพียงแค่พยายามทำความเข้าใจ)
Ellen Spertus

1
ใช่ฉันอ่านแล้วในข้อความต้นฉบับของคุณ ฉันหวังว่าคุณจะสามารถเพิ่มเหตุผลสำหรับค่าใช้จ่ายเพิ่มเติมได้ ในระหว่างนี้ฉันได้ค้นพบบางอย่างเช่นตัวเลือกในการเพิ่มลงในกองหลัง
Ellen Spertus

2
เกิดข้อผิดพลาดได้ง่ายเนื่องจากคุณสามารถเปลี่ยนแฟล็กของคุณได้ที่ API ระดับต่ำและ API ระดับสูงและหากคุณไม่ระวัง (เช่นแฟล็กหลุดจากการซิงค์) คุณอาจกำลังไล่ตามบั๊กแปลก ๆ นั่นคือเหตุผลที่แนะนำให้ใช้ตัวจัดการส่วนเพื่อซ่อนและแสดงชิ้นส่วนของคุณ
numan salati

@numansalati สวัสดีมีความเข้ากันได้ใด ๆ (จากห้องสมุดสนับสนุน) รุ่นandroid.R.animator.fade_inและandroid.R.animator.fade_out?
ปลอบใจ

1
ด้วยคอนเทนเนอร์คุณสามารถตั้งค่าให้แสดงซ่อนหรือหายไปได้ ไม่มีตัวเลือก GONE เมื่อซ่อนชิ้นส่วน
ชิงทรัพย์รับบี

59

ในการเพิ่มเติมคุณสามารถทำได้ใน Fragment (ตัวอย่างเช่นเมื่อรับข้อมูลเซิร์ฟเวอร์ล้มเหลว):

 getView().setVisibility(View.GONE);

11
Fragment เป็นลูกของ Object และไม่ใช่ View ดังนั้นจึงไม่สามารถเรียก: fragment.setVisibility (View.INVISIBLE);
AndroidGeek

8
Ariàกำลังแนะนำสิ่งที่แตกต่างคือแนะนำให้รับมุมมองจากส่วนนั้นและตั้งค่าการมองเห็นให้หายไป
AlvaroSantisteban

10
ข้อควรระวังgetView()คือnullเมื่อยังไม่เริ่มต้น
TWiStErRob

23

สวัสดีคุณทำได้โดยใช้วิธีนี้เศษทั้งหมดจะยังคงอยู่ในคอนเทนเนอร์เมื่อเพิ่มครั้งแรกจากนั้นเราจะเปิดเผยชิ้นส่วนที่ต้องการและซ่อนชิ้นส่วนอื่น ๆ ไว้ในคอนเทนเนอร์

// Within an activity
private FragmentA fragmentA;
private FragmentB fragmentB;
private FragmentC fragmentC;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (savedInstanceState == null) {
        fragmentA = FragmentA.newInstance("foo");
        fragmentB = FragmentB.newInstance("bar");
        fragmentC = FragmentC.newInstance("baz");
    }
}


// Replace the switch method
protected void displayFragmentA() {
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    if (fragmentA.isAdded()) { // if the fragment is already in container
        ft.show(fragmentA);
    } else { // fragment needs to be added to frame container
        ft.add(R.id.flContainer, fragmentA, "A");
    }
    // Hide fragment B
    if (fragmentB.isAdded()) { ft.hide(fragmentB); }
    // Hide fragment C
    if (fragmentC.isAdded()) { ft.hide(fragmentC); }
    // Commit changes
    ft.commit();
}

โปรดดูhttps://github.com/codepath/android_guides/wiki/Creating-and-Using-Fragmentsสำหรับข้อมูลเพิ่มเติม ฉันหวังว่าฉันจะได้ช่วยเหลือทุกคน แม้ว่านี่จะเป็นคำถามเก่าก็ตาม


1
ดังนั้นคุณต้องมีอีกสองวิธีเช่น displayFragmentB () และ displayFragmentC ()?
temirbek

ใช่ @temirbek คุณสามารถทำตามวิธีการใช้วิธี displayFragmentA ()
mangu23

1
ถ้าคุณมีหลายชิ้นในหนึ่งกิจกรรม (2 หรือมากกว่า) และที่คุณกำลังใช้วิธีการดังกล่าวข้างต้นกรุณาใช้นี้ จะเขียนและอ่านได้ง่ายขึ้น
Maxime Claude

8
public void showHideFragment(final Fragment fragment){

    FragmentTransaction ft = getFragmentManager().beginTransaction();
    ft.setCustomAnimations(android.R.animator.fade_in,
                    android.R.animator.fade_out);

    if (fragment.isHidden()) {
        ft.show(fragment);
        Log.d("hidden","Show");
    } else {
        ft.hide(fragment);
        Log.d("Shown","Hide");                        
    }

    ft.commit();
}

1
ที่ถูกต้องคือ ft.setCustomAnimations (android.R.anim.fade_in, android.R.anim.fade_out);
Webserveis

8

ลองสิ่งนี้:

MapFragment mapFragment = (MapFragment)getFragmentManager().findFragmentById(R.id.mapview);
mapFragment.getView().setVisibility(View.GONE);

2

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

<LinearLayout style="@style/StHorizontalLinearView"
    >

    <fragment
        android:layout_width="match_parent"
        android:layout_height="390dp"
        android:layout_alignParentTop="true"
        />

</LinearLayout>

1
final Fragment fragment1 = new fragment1();
final Fragment fragment2 = new fragment2();
final FragmentManager fm = getSupportFragmentManager();
Fragment active = fragment1;

ใน onCreate หลังจาก setContentView ฉันซ่อนสองชิ้นส่วนและส่งมอบให้กับตัวจัดการแฟรกเมนต์ แต่ฉันไม่ได้ซ่อนส่วนแรกที่จะใช้เป็นบ้าน

fm.beginTransaction().add(R.id.main_container, fragment2, "2").hide(fragment2).commit();
fm.beginTransaction().add(R.id.main_container,fragment1, "1").commit();
 @Override
    public void onClick(View v) {
        Fragment another = fragment1;
         if(active==fragment1){
          another = fragment2;
         }
            fm.beginTransaction().hide(active).show(another).commit();
            active = another;
}

อ้างอิง: https://medium.com/@oluwabukunmi.aluko/bottom-navigation-view-with-fragments-a074bfd08711


1

ฉันอาจจะสายเกินไป แต่มันสามารถช่วยใครบางคนได้ในอนาคต
คำตอบนี้เป็นการดัดแปลงเพื่อmangu23 ตอบ
ฉันได้เพิ่ม for loop เท่านั้นเพื่อหลีกเลี่ยงการทำซ้ำและเพิ่มชิ้นส่วนเพิ่มเติมได้อย่างง่ายดายโดยไม่ต้องใช้รหัสสำเร็จรูป

อันดับแรกเราต้องมีรายการชิ้นส่วนที่ควรแสดง

public class MainActivity extends AppCompatActivity{
    //...
    List<Fragment> fragmentList = new ArrayList<>();
}

จากนั้นเราต้องเติมมันด้วยเศษของเรา

@Override
protected void onCreate(Bundle savedInstanceState) {
    //...
    HomeFragment homeFragment = new HomeFragment();
    MessagesFragment messagesFragment = new MessagesFragment();
    UserFragment userFragment = new UserFragment();
    FavoriteFragment favoriteFragment = new FavoriteFragment();
    MapFragment mapFragment = new MapFragment();

    fragmentList.add(homeFragment);
    fragmentList.add(messagesFragment);
    fragmentList.add(userFragment);
    fragmentList.add(favoriteFragment);
    fragmentList.add(mapFragment);
}

และเราต้องการวิธีที่จะทราบว่าชิ้นส่วนใดถูกเลือกจากรายการดังนั้นเราจึงต้องการgetFragmentIndexฟังก์ชัน

private int getFragmentIndex(Fragment fragment) {
    int index = -1;
    for (int i = 0; i < fragmentList.size(); i++) {
        if (fragment.hashCode() == fragmentList.get(i).hashCode()){
            return i;
        }
    }
    return index;
}

และสุดท้ายdisplayFragmentวิธีนี้จะเป็นดังนี้:

private void displayFragment(Fragment fragment) {
        int index = getFragmentIndex(fragment);
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        if (fragment.isAdded()) { // if the fragment is already in container
            transaction.show(fragment);
        } else { // fragment needs to be added to frame container
            transaction.add(R.id.placeholder, fragment);
        }
        // hiding the other fragments
        for (int i = 0; i < fragmentList.size(); i++) {
            if (fragmentList.get(i).isAdded() && i != index) {
                transaction.hide(fragmentList.get(i));
            }
        }
        transaction.commit();
    }

ด้วยวิธีนี้เราสามารถเรียกdisplayFragment(homeFragment)เช่น
สิ่งนี้จะแสดงHomeFragmentและซ่อนส่วนอื่น ๆ ในรายการโดยอัตโนมัติ
โซลูชันนี้ช่วยให้คุณสามารถต่อท้ายส่วนต่างๆได้มากขึ้นfragmentListโดยไม่ต้องทำซ้ำifคำสั่งในdisplayFragmentเวอร์ชันเก่า
ฉันหวังว่าใครบางคนจะพบว่าสิ่งนี้มีประโยชน์


0

สิ่งนี้ได้ผลสำหรับฉัน

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        if(tag.equalsIgnoreCase("dashboard")){

            DashboardFragment dashboardFragment = (DashboardFragment)
                    fragmentManager.findFragmentByTag("dashboard");
            if(dashboardFragment!=null) ft.show(dashboardFragment);

            ShowcaseFragment showcaseFragment = (ShowcaseFragment)
                    fragmentManager.findFragmentByTag("showcase");
            if(showcaseFragment!=null) ft.hide(showcaseFragment);

        } else if(tag.equalsIgnoreCase("showcase")){
            DashboardFragment dashboardFragment = (DashboardFragment)
                    fragmentManager.findFragmentByTag("dashboard");
            if(dashboardFragment!=null) ft.hide(dashboardFragment);

            ShowcaseFragment showcaseFragment = (ShowcaseFragment)
                    fragmentManager.findFragmentByTag("showcase");
            if(showcaseFragment!=null) ft.show(showcaseFragment);
        }

        ft.commit();

0

คำตอบที่นี่ถูกต้องและฉันชอบ @Jyo the Whiff เกี่ยวกับการแสดงและซ่อนการใช้งานส่วนยกเว้นวิธีที่เขามีในปัจจุบันจะซ่อนส่วนในการรันครั้งแรกดังนั้นฉันจึงเพิ่มการเปลี่ยนแปลงเล็กน้อยซึ่งฉันได้เพิ่มการตรวจสอบและแสดง isAdded ส่วนถ้ายังไม่ได้

public void showHideCardPreview(int id) {
    FragmentManager fm = getSupportFragmentManager();
    Bundle b = new Bundle();
    b.putInt(Constants.CARD, id);
    cardPreviewFragment.setArguments(b);
    FragmentTransaction ft = fm.beginTransaction()
        .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
    if (!cardPreviewFragment.isAdded()){
        ft.add(R.id.full_screen_container, cardPreviewFragment);
        ft.show(cardPreviewFragment);
    } else {
        if (cardPreviewFragment.isHidden()) {
            Log.d(TAG,"++++++++++++++++++++ show");
            ft.show(cardPreviewFragment);
        } else {
            Log.d(TAG,"++++++++++++++++++++ hide");
            ft.hide(cardPreviewFragment);
        }
    }

    ft.commit();
} 
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.