Lập trình quay trở lại đoạn trước trong backstack


218

Nói rằng tôi có một hoạt động có các đoạn được thêm vào theo chương trình:

private void animateToFragment(Fragment newFragment, String tag) {
    FragmentTransaction ft = getFragmentManager().beginTransaction();
    ft.replace(R.id.fragment_container, newFragment, tag);
    ft.addToBackStack(null);
    ft.commit();
}

Cách tốt nhất để trở về mảnh trước đó có thể nhìn thấy là gì?

Tôi đã tìm thấy chức năng nút back của Trigger khi nhấp vào nút trong Android nhưng tôi nghĩ việc mô phỏng một sự kiện phím trở lại không phải là cách phù hợp để thực hiện (và tôi cũng không thể làm cho nó hoạt động được):

dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));

Gọi điện finish()chỉ đóng hoạt động mà tôi không quan tâm.

Có cách nào tốt hơn để đi về điều này?

Câu trả lời:


354

Nhìn vào các getFragmentManager().popBackStack()phương thức (có một số để lựa chọn)

http://developer.android.com/reference/android/app/FragmentManager.html#popBackStack ()


91
getFragmentManager().popBackStackImmediate();đã lừa Cảm ơn.
Aske B.

1
Tôi sẽ đặt phương pháp này ở đâu? Trong tab của tôi nghe?
rasen58

1
không nhìn thấy mã, thật khó để nói ... nhưng nó sẽ đi vào phần mã được thực thi khi bạn muốn "đóng" đoạn hiện tại và quay lại đoạn trước đó.
kẹt

1
những gì về getSupportFragmentManager ()
ViliusK

5
Đừng quên thêm "addToBackStack (" tag ")" vào mã của bạn. "FragmentManager.beginTransaction (). thay thế (R.id.content_frame, đoạn) .addToBackStack (" tag "). commit ();" nếu bạn viết addToBackStack (null), nó sẽ tự xử lý nhưng nếu bạn đưa ra một thẻ, bạn nên xử lý thủ công.
Khaled Saif

129

Để giải thích các câu trả lời khác được cung cấp, đây là giải pháp của tôi (được đặt trong Hoạt động):

@Override
public void onBackPressed(){
    FragmentManager fm = getFragmentManager();
    if (fm.getBackStackEntryCount() > 0) {
        Log.i("MainActivity", "popping backstack");
        fm.popBackStack();
    } else {
        Log.i("MainActivity", "nothing on backstack, calling super");
        super.onBackPressed();  
    }
}

5
và tại sao điều đó xảy ra. Trong ví dụ phân đoạn developer.android.com/training/basics/fragments/index.html họ không vượt qua sự kiện bị áp đảo và họ vẫn có thể sao lưu đoạn. Tôi đã sử dụng trasaction.addToBackStack (null); Nhưng không có gì xảy ra. Bạn có thể giải thích lý do tại sao ?
Murtaza Khursheed Hussain

@MurtazaHussain có lẽ bạn nên hỏi một câu hỏi mới nếu bạn muốn giúp đỡ về vấn đề này. Thật khó để thấy những gì đang diễn ra mà không cần xem thêm mã.
Kyle Falconer

2
Trong trường hợp của tôi, tôi đã phải làm fm.getBackStackEntryCount() > 1để gọi lại hoạt động khi chỉ có đoạn đầu tiên trong ngăn xếp.
Facundo Olano

3
Android đã làm điều này cho bạn: "Khi có các đối tượng FragmentTransaction trên ngăn xếp phía sau và người dùng nhấn nút Quay lại, FragmentManager bật giao dịch gần đây nhất khỏi ngăn xếp phía sau và thực hiện hành động ngược lại (chẳng hạn như xóa một đoạn nếu giao dịch đã thêm nó). " (Nguồn)
artkoenig

29

Khi chúng tôi đang cập nhật / thêm các đoạn,

Nên bao gồm .addToBackStack().

getSupportFragmentManager().beginTransaction()
    .add(detailFragment, "detail") // Add this transaction to the back stack (name is an optional name for this back stack state, or null).
    .addToBackStack(null)
    .commit();

Sau đó, nếu chúng tôi cung cấp getFragments.popBackStackImmediate()sẽ trả về đúng nếu chúng tôi thêm / cập nhật các đoạn và quay trở lại màn hình hiện tại.


7

Thêm các dòng đó vào Phương thức onBackPression () của bạn. Phương thức popBackStackImmediate () sẽ đưa bạn trở lại đoạn trước nếu bạn có bất kỳ đoạn nào trên ngăn xếp phía sau `

if(getFragmentManager().getBackStackEntryCount() > 0){
     getFragmentManager().popBackStackImmediate();
}
else{
    super.onBackPressed();
}

`


5

Giải pháp này hoạt động hoàn hảo cho điều hướng phân đoạn dựa trên thanh dưới cùng khi bạn muốn đóng ứng dụng khi nhấn lại vào đoạn chính.

Mặt khác, khi bạn đang mở đoạn thứ cấp (đoạn trong đoạn) được định nghĩa là "Chi tiết" trong mã của tôi, nó sẽ trả về trạng thái của đoạn chính trước đó. Chúc mừng!

Hoạt động bên trong nhấn trở lại đặt này:

Fragment home = getSupportFragmentManager().findFragmentByTag("DetailedPizza");

if (home instanceof FragmentDetailedPizza && home.isVisible()) {
    if (getFragmentManager().getBackStackEntryCount() != 0) {
        getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
} else {
    //Primary fragment
    moveTaskToBack(true);
}

Và khởi chạy các đoạn khác như thế này:

Fragment someFragment = new FragmentDetailedPizza();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.container_body, someFragment, "DetailedPizza");
transaction.addToBackStack("DetailedPizza");
transaction.commit();

3

Những câu trả lời này không hoạt động nếu tôi không thêm addToBackStack () vào giao dịch phân đoạn của mình, nhưng, bạn có thể sử dụng:

getActivity().onBackPressed();

từ bất kỳ mảnh vỡ của bạn để quay trở lại một bước;


1

Lập trình trở lại đoạn trước bằng mã sau.

if ( getFragmentManager().getBackStackEntryCount() > 0) 
{
          getFragmentManager().popBackStack();
          return;
}
super.onBackPressed();

1

Để làm cho đoạn đó trở lại, chỉ cần thêm đoạn đó vào backstack mà bạn muốn quay lại, ví dụ:

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Fragment fragment = new LoginFragment();
        //replacing the fragment
        if (fragment != null) {
            FragmentTransaction ft = ((FragmentActivity)getContext()).getSupportFragmentManager().beginTransaction();
            ft.replace(R.id.content_frame, fragment);
            ft.addToBackStack("SignupFragment");
            ft.commit();
        }
    }
});

Trong trường hợp trên, tôi đang mở LoginFragmentkhi Button buttonđược nhấn, ngay bây giờ người dùng đang ở trong SignupFragment. Vì vậy, nếu addToBackStack(TAG)được gọi, ở đâu TAG = "SignupFragment", sau đó khi nhấn nút quay lại LoginFragment, chúng tôi quay lại SignUpFragment.

Chúc mừng mã hóa!


Tôi nghĩ, TAG không ảnh hưởng, thậm chí có thể là null.
CoolMind

1

Bằng cách thêm fragment_tran.addToBackStack(null)vào mảnh cuối cùng, tôi có thể quay lại mảnh cuối cùng.

thêm đoạn mới :

view.findViewById(R.id.changepass).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
            transaction.replace(R.id.container, new ChangePassword());
            transaction.addToBackStack(null);
            transaction.commit();
        }
    });

1

Tôi đến đây tìm kiếm hoặc cùng một ý tưởng, và trong khi đó tôi đã tự mình nghĩ ra, điều mà tôi tin là nó không tệ và hoạt động nếu với ViewPager.

Vì vậy, những gì tôi đã làm là ghi đè phương thức onBackPression trong hoạt động chính giữ viewPager và đặt nó luôn quay trở lại trừ đi 1 vị trí cho đến khi đến đoạn đầu tiên, sau đó đóng hoạt động.

@Override
public void onBackPressed() {
    if(viewPager.getCurrentItem()>0){
        viewPager.setCurrentItem(viewPager.getCurrentItem()-1);
    } else {
        super.onBackPressed();
        this.close();
    }
}

private void close(){
    this.finish();
}

Điều này có thể có một nhược điểm, như nó chỉ quay lại một chiều mỗi lần, vì vậy nó có thể không hoạt động tốt nếu có các tab và bạn chuyển vị trí với các đoạn bị bỏ qua, (đi từ 0 đến 2, và sau đó nhấn lại sẽ đưa bạn vào 1, thay vì 0)

Đối với trường hợp của tôi tho, với 2 đoạn trong viewPager không có tab, nó thực hiện công việc độc đáo.


Câu hỏi tương tự đã được trả lời. stackoverflow.com/questions/10863572/
hy

0

Hãy thử mã dưới đây:

@Override
    public void onBackPressed() {
        Fragment myFragment = getSupportFragmentManager().findFragmentById(R.id.container);
        if (myFragment != null && myFragment instanceof StepOneFragment) {
            finish();
        } else {
            if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
                getSupportFragmentManager().popBackStack();
            } else {
                super.onBackPressed();
            }
        }
    }
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.