Lấy đối tượng phân đoạn hiện tại


175

Trong tôi main.xml

  <FrameLayout
        android:id="@+id/frameTitle"
        android:padding="5dp"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:background="@drawable/title_bg">
            <fragment
              android:name="com.fragment.TitleFragment"
              android:id="@+id/fragmentTag"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content" />

  </FrameLayout>

Và tôi đang thiết lập đối tượng mảnh như thế này

FragmentManager fragmentManager = activity.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment newFragment = new FragmentType1();
fragmentTransaction.replace(R.id.frameTitle, casinodetailFragment, "fragmentTag");

// fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();

Nó đang thiết lập các loại đối tượng Fragment ( FragmentType2,FragmentType3,...) khác nhau tại thời điểm khác nhau. Bây giờ tại một số thời điểm tôi cần xác định đối tượng nào hiện đang ở đó.

Trong ngắn tôi cần phải làm một cái gì đó như thế này:

Fragment currentFragment = //what is the way to get current fragment object in FrameLayout R.id.frameTitle

Tôi đã thử như sau

TitleFragment titleFragmentById = (TitleFragment) fragmentManager.findFragmentById(R.id.frameTitle);

    TitleFragment titleFragmentByTag = (TitleFragment) fragmentManager.findFragmentByTag("fragmentTag");

Nhưng cả hai đối tượng (titleFragmentById và titleFragmentByTag)null
tôi có bỏ lỡ điều gì không?
Tôi đang sử dụng Compatibility Package, r3và phát triển cho API level 7.

findFragmentById()findFragmentByTag()sẽ hoạt động nếu chúng ta đã thiết lập đoạn bằng cách sử dụng fragmentTransaction.replacehoặc fragmentTransaction.add, nhưng sẽ return nullnếu chúng ta đã đặt đối tượng ở xml (giống như những gì tôi đã làm trong phần của mình main.xml). Tôi nghĩ rằng tôi đang thiếu một cái gì đó trong các tệp XML của tôi.



Câu trả lời @CommonsWare có giúp bạn không, vì tôi vẫn nhận được null?
IntoTheDeep

Câu trả lời:


253

Bây giờ tại một số thời điểm tôi cần xác định đối tượng nào hiện đang ở đó

Gọi findFragmentById()trên FragmentManagervà xác định đoạn là ở bạn R.id.frameTitlechứa.


1
Cám ơn phản hồi của bạn. Nó sẽ hoạt động nếu chúng ta đã đặt phân đoạn bằng fragmentTransaction.replace hoặc fragmentTransaction.addnhưng sẽ không nhận được nếu chúng ta đã đặt nó ở xml. Xem chỉnh sửa của tôi 2
Labeeb Panampullan

9
@Labeeb P: Bạn không thể sửa đổi các đoạn được khai báo trong tài nguyên bố cục.
CommonsWare

Tạo một lớp để giữ tab / đoạn hiện đang hiển thị cũng sẽ hoạt động, tôi đã thử điều đó. Hy vọng không có thất bại.
Skynet

@CommonsWare findFragmentByTagtrả về null trong trường hợp ActionBarTab. Trong Activityđó tôi đang mở rộng ActionBarActivityđầu tiên tôi thêm các tab ActionBarvà sau đó tìm thấy nó!
Muhammad Babar

1
@MuhammadBabar: Bạn có thể thử executePendingTransactions()trên FragmentManagersau khi gọi commit()vào giao dịch, mặc dù tôi đã không cố gắng này. Hoặc bạn có thể sử dụng setContentView()để sử dụng tệp bố cục với <fragment>thẻ. Một trong hai điều đó xảy ra đồng bộ, và do đó đoạn sẽ tồn tại trong onCreate()chính cuộc gọi nơi bạn đã sử dụng executePendingTransaction()hoặc setContentView(). Mặt khác, thông thường FragmentTransactionđược xử lý không đồng bộ và thậm chí nó sẽ không bắt đầu khi thời gian onCreate()kết thúc.
CommonsWare

110

Thử cái này,

Fragment currentFragment = getActivity().getFragmentManager().findFragmentById(R.id.fragment_container);

điều này sẽ cung cấp cho bạn đoạn hiện tại, sau đó bạn có thể so sánh nó với lớp phân đoạn và thực hiện công cụ của bạn.

    if (currentFragment instanceof NameOfYourFragmentClass) {
     Log.v(TAG, "find the current fragment");
  }

Đặt dòng này ở đâu?
Anand Savć

9
Đôi khi, bạn phải sử dụng getSupportFragmentManager()thay thế và sẽ nhận được null mà không có supportphần
Muz

Xóa các trích dẫn từ xung quanh "TÊN LỚP FRAGMENT CỦA BẠN".
Alan Nelson

37

Tôi nghĩ rằng bạn có thể sử dụng sự kiện onAttachFragment có thể hữu ích để nắm bắt đoạn nào đang hoạt động.

@Override
public void onAttachFragment(Fragment fragment) {
    // TODO Auto-generated method stub
    super.onAttachFragment(fragment);

    Toast.makeText(getApplicationContext(), String.valueOf(fragment.getId()), Toast.LENGTH_SHORT).show();

}

3
tôi có thể có được đoạn nào tôi đính kèm. Suy nghĩ của tôi là khi tôi thay đổi hướng thì tôi cần hiển thị cùng một góc nhìn chứ không phải một góc nhìn khác vậy làm thế nào để làm điều này.
Nhà phát triển Androi

7
Điều này không hoạt động vì nó không cập nhật đoạn hoạt động khi bạn quay lại.
Justin

1
@Justin vì vậy chúng tôi chỉ cần sử dụng onDetach với danh sách điểm yếu
hãy đăng ký

12

Tôi nghĩ bạn nên làm:

Fragment currentFragment = fragmentManager.findFragmentByTag("fragmentTag");

Lý do là vì bạn đặt thẻ "FragmentTag" thành đoạn cuối cùng bạn đã thêm (khi bạn gọi thay thế).


Cảm ơn tôi đã sửa nó. Đó là một lỗi đánh máy trong khi viết câu hỏi này. Nó sẽ hoạt động nếu chúng ta đã đặt phân đoạn bằng fragmentTransaction.replace hoặc fragmentTransaction.addnhưng sẽ không nhận được nếu chúng ta đã đặt nó ở xml. Xem bản chỉnh sửa của tôi 2
Labeeb Panampullan

Cảm ơn bạn rất nhiều! Giải quyết vấn đề của tôi!
Jonas Gröger

2
giải pháp này không có nghĩa là bạn phải đặt cùng một thẻ cho nhiều phân đoạn sao? nếu không, làm thế nào bạn biết fragmentTaglà thẻ cho đoạn hiện tại?
Thupten

12

Bạn có thể lấy danh sách các mảnh vỡ và tìm đến cái cuối cùng.

    FragmentManager fm = getSupportFragmentManager();
    List<Fragment> fragments = fm.getFragments();
    Fragment lastFragment = fragments.get(fragments.size() - 1);

Nhưng đôi khi (khi bạn điều hướng trở lại) kích thước danh sách vẫn giữ nguyên nhưng một số yếu tố cuối cùng là null. Vì vậy, trong danh sách tôi đã lặp lại đoạn cuối không null và sử dụng nó.

    FragmentManager fm = getSupportFragmentManager();
    if (fm != null) {
        List<Fragment> fragments = fm.getFragments();
        if (fragments != null) {
            for(int i = fragments.size() - 1; i >= 0; i--){
                Fragment fragment = fragments.get(i);
                if(fragment != null) {
                    // found the current fragment

                    // if you want to check for specific fragment class
                    if(fragment instanceof YourFragmentClass) {
                        // do something
                    }
                    break;
                }
            }
        }
    }

3
Đừng sử dụng getFragments()phương pháp này. Nó được đánh dấu @hidevà không được cho là có trong thư viện hỗ trợ. Nó không nên được coi là một phần của API đã xuất.
James Wald

Heh, sau đó họ nên tạo ra một phương pháp cho phép bạn làm chính xác những gì getFragments(), bởi vì bạn cần nó khá thường xuyên. Tôi nghĩ rằng nó thực sự có sẵn công khai bây giờ, quá.
EpicPandaForce

10

Đây là giải pháp đơn giản nhất và làm việc cho tôi.

1.) bạn thêm đoạn của bạn

ft.replace(R.id.container_layout, fragment_name, "fragment_tag").commit();

2.)

FragmentManager fragmentManager = getSupportFragmentManager();

Fragment currentFragment = fragmentManager.findFragmentById(R.id.container_layout);

if(currentFragment.getTag().equals("fragment_tag"))

{

 //Do something

}

else

{

//Do something

}

9

Nó có thể bị trễ nhưng tôi hy vọng nó sẽ giúp được người khác, @CommonsWare đã đăng câu trả lời đúng.

FragmentManager fm = getSupportFragmentManager();
Fragment fragment_byID = fm.findFragmentById(R.id.fragment_id);
//OR
Fragment fragment_byTag = fm.findFragmentByTag("fragment_tag");

9
Điều này không cho phép bạn có được đoạn hoạt động, vì bạn không nhất thiết phải biết id hoặc thẻ.
Justin

7

Có lẽ cách đơn giản nhất là:

public MyFragment getVisibleFragment(){
    FragmentManager fragmentManager = MainActivity.this.getSupportFragmentManager();
    List<Fragment> fragments = fragmentManager.getFragments();
    for(Fragment fragment : fragments){
        if(fragment != null && fragment.getUserVisibleHint())
            return (MyFragment)fragment;
    }
    return null;
}

Nó làm việc cho tôi


6

Bạn có thể tạo trường trong Lớp Hoạt động của cha mẹ:

public class MainActivity extends AppCompatActivity {

    public Fragment fr;

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

}

Và sau đó bên trong mỗi lớp phân đoạn:

public class SomeFragment extends Fragment {

@Override
    public View onCreateView(LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {

        ((MainActivity) getActivity()).fr = this;
}

Trường 'fr' của bạn là đối tượng phân đoạn hiện tại

Nó cũng hoạt động với popBackStack ()


4

Tôi biết đã được một lúc, nhưng tôi sẽ ở đây trong trường hợp nó giúp được ai đó.

Các câu trả lời đúng cho đến nay là (và một trong những lựa chọn) một từ CommonsWare. Tôi đã có cùng một vấn đề như được đăng, sau đây

MyFragmentClass fragmentList = 
            (MyFragmentClass) getSupportFragmentManager().findFragmentById(R.id.fragementID);

tiếp tục trả về null. Lỗi của tôi thực sự ngớ ngẩn, trong tệp xml của tôi:

<fragment
    android:tag="@+id/fragementID"
    android:name="com.sf.lidgit_android.content.MyFragmentClass"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
/>

Lỗi là tôi đã có android: tag INSTEAD OF android: id .


2

Phản hồi @ Hammer làm việc cho tôi, tôi đang sử dụng để điều khiển nút hành động nổi

final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(final View view) {
            android.app.Fragment currentFragment = getFragmentManager().findFragmentById(R.id.content_frame);
            Log.d("VIE",String.valueOf(currentFragment));
            if (currentFragment instanceof PerfilFragment) {
                PerfilEdit(view, fab);
            }
        }
});

2

Nếu bạn đang mở rộng từ AbstractActivity, bạn có thể sử dụng phương thức getFragments ():

for (Fragment f : getFragments()) {
    if (f instanceof YourClass) {
        // do stuff here
    }
}

1

Nếu bạn đang xác định đoạn trong layour XML của hoạt động thì Activityhãy chắc chắn rằng bạn gọi setContentView()trước khi gọi findFragmentById().


1

Nếu bạn đang sử dụng BackStack ... và CHỈ nếu bạn đang sử dụng ngăn xếp phía sau, thì hãy thử điều này:

rivate Fragment returnToPreviousFragment() {

    FragmentManager fm = getSupportFragmentManager();

    Fragment topFrag = null;

    int idx = fm.getBackStackEntryCount();
    if (idx > 1) {
        BackStackEntry entry = fm.getBackStackEntryAt(idx - 2);
        topFrag = fm.findFragmentByTag(entry.getName());
    }

    fm.popBackStack();

    return topFrag;
}

0

Điều này sẽ cung cấp cho bạn tên lớp phân đoạn hiện tại ->

String fr_name = getSupportFragmentManager().findFragmentById(R.id.fragment_container).getClass().getSimpleName();

0
  1. Thực hiện kiểm tra (đoạn nào trong vùng chứa hoạt động) trong phương thức onStart;

    @Override
    protected void onStart() {
    super.onStart();
    Fragment fragmentCurrent = getSupportFragmentManager.findFragmentById(R.id.constraintLayout___activity_main___container);
    }
  2. Một số kiểm tra:

    if (fragmentCurrent instanceof MenuFragment) 
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.