Hiển thị ẩn đoạn trong Android


98

Tôi đang phát triển ứng dụng có chứa 2 mảnh và tôi muốn hiển thị ẩn theo nhu cầu của mình. Đoạn mã sau đây có ví dụ đơn giản về vấn đề của tôi. Phân mảnh đơn giản này chứa 1 nút và một phân mảnh danh sách.

Ví dụ đơn giản này hoạt động hoàn hảo. nhưng tôi không hài lòng với đoạn ẩn hiện. Nếu bạn loại bỏ layout.setVisibility (View.GONE); từ mã sau đó ft.hide (f); sẽ không ẩn phân mảnh. Trong thực tế, chúng tôi không ẩn phân đoạn mà chúng tôi đang ẩn container.

Câu hỏi của tôi là, đây có phải là cách để hiển thị các đoạn ẩn không? Nếu không thì vui lòng giải thích bằng ví dụ đã thử nghiệm Cách ẩn và hiển thị Phân mảnh vì rất nhiều người đang gặp phải vấn đề này.

 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
        }

Tại sao bạn cần thiết lập khả năng hiển thị của vùng chứa? Nó sẽ hoạt động mà không cần thiết lập khả năng hiển thị.
Andrii Chernenko

Chính xác là nó sẽ hoạt động mà không có khả năng hiển thị của container nhưng nó không hoạt động. Xin vui lòng vui lòng chia sẻ ví dụ làm việc đơn giản với tôi. Sau đó, tôi sẽ biết nơi tôi đang thiếu.
abidkhan303,

1
Tôi đoán là bạn đang cố gắng hiển thị / ẩn các trường hợp khác nhau của phân mảnh mỗi lần. Khi bạn thêm phân đoạn của mình (nhân tiện, tôi không thấy đoạn mã này), hãy thêm nó bằng thẻ và sau đó truy xuất nó bằng thẻ đó (thay vì cố gắng lưu trữ tham chiếu đến nó). Đó có thể là những gì bạn đang thiếu.
Andrii Chernenko

Câu trả lời:


158

Đừng gây rối với các cờ hiển thị của vùng chứa - FragmentTransaction.hide / show thực hiện điều đó nội bộ cho bạn.

Vì vậy, cách chính xác để làm điều này là:

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

HOẶC nếu bạn đang sử dụng 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
Tại sao bạn lại khuyên bạn không nên đánh cờ trực tiếp? (Tôi không phản đối đề xuất của bạn, chỉ đang cố gắng hiểu nó.)
Ellen Spertus

1
Vâng, tôi đã đọc điều đó trong tin nhắn ban đầu của bạn. Tôi đã hy vọng bạn có thể thêm lời biện minh cho chi phí bổ sung. Trong khi chờ đợi, tôi đã phát hiện ra một số, chẳng hạn như tùy chọn thêm vào ngăn xếp phía sau.
Ellen Spertus

2
Nó dễ xảy ra lỗi vì bạn có thể thay đổi cờ của mình ở api cấp thấp và api cấp cao và nếu bạn không cẩn thận (tức là cờ không đồng bộ), bạn có thể đuổi theo những lỗi kỳ lạ. Đó là lý do tại sao bạn nên sử dụng trình quản lý phân mảnh để ẩn và hiển thị các phân đoạn của bạn.
numan salati

@numansalati Xin chào, có phiên bản nào tương thích (từ thư viện hỗ trợ) của android.R.animator.fade_inandroid.R.animator.fade_outkhông?
Solace

1
Với vùng chứa, bạn có thể đặt nó thành HIỂN THỊ, HIDE hoặc GONE. Không có tùy chọn GONE khi ẩn một phân đoạn.
Stealth Rabbi

57

Trong addittion, bạn có thể thực hiện trong Fragment (ví dụ: khi lấy dữ liệu máy chủ không thành công):

 getView().setVisibility(View.GONE);

11
Fragment là con của Object chứ không phải View nên không thể gọi :gment.setVisibility (View.INVISIBLE);
AndroidGeek

8
Arià đang đề xuất một điều gì đó khác biệt, đang gợi ý để có được tầm nhìn từ mảnh đó và đặt khả năng hiển thị của nó thành biến mất.
AlvaroSantisteban

10
Cẩn thận getView()có thể là nullkhi nó chưa được khởi tạo.
TWiStErRob

22

Xin chào, bạn làm điều đó bằng cách sử dụng cách tiếp cận này, tất cả các đoạn sẽ vẫn còn trong vùng chứa sau khi được thêm vào ban đầu và sau đó chúng tôi chỉ đơn giản là tiết lộ phân đoạn mong muốn và ẩn các đoạn khác trong vùng chứa.

// 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();
}

Vui lòng xem https://github.com/codepath/android_guides/wiki/Creating-and-Using-Fragment để biết thêm thông tin. Tôi hy vọng tôi có thể giúp đỡ bất cứ ai. Ngay cả khi nó là một câu hỏi cũ.


1
vì vậy bạn phải có thêm hai phương thức như displayFragmentB () và displayFragmentC ()?
temirbek

có @temirbek, bạn chỉ có thể làm theo cách phương thức displayFragmentA () được triển khai.
mangu23

1
Nếu bạn có nhiều phân đoạn trong một hoạt động (2 hoặc nhiều hơn) và bạn đang sử dụng phương pháp trên, hãy sử dụng phương pháp này . Nó sẽ dễ dàng hơn để viết và đọc.
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
đúng là ft.setCustomAnimations (android.R.anim.fade_in, android.R.anim.fade_out);
Webserveis

8

Thử cái này:

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

2

Từ mã của tôi, so với giải pháp trên, cách đơn giản nhất là xác định một bố cục có chứa phân đoạn, sau đó bạn có thể ẩn hoặc hiện phân đoạn bằng cách kiểm soát thuộc tính bố cục được căn chỉnh với cách xem chung. Không cần mã bổ sung trong trường hợp này và các thuộc tính triển khai bổ sung của phân đoạn có thể được chuyển đến bố cục bên ngoài.

<LinearLayout style="@style/StHorizontalLinearView"
    >

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

</LinearLayout>

0

Điều này đã làm việc cho tôi

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

các câu trả lời ở đây đều đúng và tôi thích @Jyo ý tưởng Whiff về triển khai hiển thị và ẩn phân đoạn ngoại trừ cách anh ấy có nó hiện tại sẽ ẩn phân đoạn trong lần chạy đầu tiên, vì vậy tôi đã thêm một chút thay đổi đó là tôi đã thêm kiểm tra và hiển thị isAdded mảnh vỡ nếu nó chưa có

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();
} 

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

Trong onCreate, sau setContentView, tôi đã ẩn hai phân đoạn và cam kết chúng với trình quản lý phân mảnh, nhưng tôi không ẩn phân đoạn đầu tiên sẽ đóng vai trò là nhà.

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;
}

Tham khảo: https://medium.com/@oluwabukunmi.aluko/bottom-navigation-view-with-fragment-a074bfd08711


0

Tôi có thể đã quá muộn nhưng nó có thể giúp ích cho ai đó trong tương lai.
Câu trả lời này là một sửa đổi cho mangu23 câu trả lời
Tôi chỉ thêm một vòng lặp for để tránh lặp lại và để dễ dàng thêm nhiều đoạn hơn mà không cần mã soạn sẵn.

Trước tiên, chúng tôi cần một danh sách các phân đoạn sẽ được hiển thị

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

Sau đó, chúng ta cần lấp đầy nó bằng các mảnh của chúng ta

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

Và chúng tôi cần một cách để biết phân đoạn nào đã được chọn từ danh sách, vì vậy chúng tôi cần getFragmentIndexhàm

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;
}

Và cuối cùng, displayFragmentphương pháp sẽ như thế này:

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();
    }

Bằng cách này, chúng ta có thể gọi displayFragment(homeFragment)ví dụ.
Điều này sẽ tự động hiển thị HomeFragmentvà ẩn bất kỳ phân đoạn nào khác trong danh sách.
Giải pháp này cho phép bạn nối thêm nhiều đoạn vào fragmentListmà không cần phải lặp lại các ifcâu lệnh trong displayFragmentphiên bản cũ .
Tôi hy vọng ai đó sẽ thấy điều này hữu ích.

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.