簡體   English   中英

導航抽屜,處理后退按鈕轉到上一個片段?

[英]Navigation drawer, handling the back button to go to previous fragments?

我正在使用內置導航抽屜來運行我的應用程序。 我不太明白如何處理后退按鈕。 當它被按下時,我希望它再次加載第一個片段。 片段1。

因此,當應用程序啟動時,您會看到 Fragment1 已啟動。 然后他們可以單擊 Fragment 2-5 轉到其他頁面。 在所有這些頁面中,我希望后退按鈕將用戶帶回 Fragment1。 用戶應該能夠通過后退按鈕退出應用程序的唯一地方是 Fragment1。

由於這一切都由 FragmentActivity 處理,因此我嘗試弄亂那里的后退按鈕。 但是,我不斷收到強制關閉錯誤:

(01-11 14:09:33.114: E/AndroidRuntime(8292): android.view.InflateException: Binary XML file line #7: Error inflating class fragment)

這是我到目前為止:

我確保像這樣將片段添加到后堆棧中:

fm.beginTransaction().replace(R.id.main, newFragment).addToBackStack("fragBack").commit();

返回鍵:

@Override
public void onBackPressed() {
    if (getSupportFragmentManager().findFragmentByTag("fragBack") != null) {
        
    }
    else {
        super.onBackPressed();
        return;
    }
    if (getSupportFragmentManager().getBackStackEntryCount() != 0) {
        Toast.makeText(getApplicationContext(), "Test", Toast.LENGTH_LONG).show();
        Fragment frag = getSupportFragmentManager().findFragmentByTag("fragBack");
        FragmentTransaction transac = getSupportFragmentManager().beginTransaction().remove(frag);
                transac.commit();
    }
    
}

有誰知道我需要做什么? 我是否需要在每個片段中調用 onBackPressed (如果可能的話)而不是控制抽屜的 FragmentActivity ? 在我過去的應用程序中,無論用戶在哪個 Fragment 上,我都可以通過后退按鈕關閉應用程序,但我現在正在制作的那個我希望后退按鈕返回到 Fragment1。

真的很感激一些幫助,謝謝。

項目點擊

@Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
            
            Fragment newFragment = new MapsPage();
            FragmentManager fm = getSupportFragmentManager();
            switch(i) {
            case 0:
                newFragment = new Fragment2();
                break;
            case 1:
                newFragment = new Fragment3();
                break;
            case 2:
                newFragment = new Fragment4();
                break;
            case 3:
                newFragment = new Fragment5();
                break;
            }
            fm.beginTransaction().add(R.id.main, newFragment).addToBackStack("fragback").commit();
            drawerLayout.closeDrawer(rl);
        }

代替:

fm.beginTransaction().replace(R.id.main, newFragment).addToBackStack("fragBack").commit();

稱呼:

fm.beginTransaction().add(R.id.main, newFragment).addToBackStack("fragBack").commit();

addToBackStack 與add

replace函數刪除前一個片段並放置新片段,因此在您的后台堆棧中始終只有一個片段。 因此,使用 add 函數將先前的片段保留在堆棧中。

要始終從 onBackPress 的任何片段轉到 fragemnt1,請嘗試執行以下操作:

getFragmentManager().popBackStack();
fm.beginTransaction().add(R.id.main, newFragment).addToBackStack("fragBack").commit();

這將從 backstack 中刪除最后一個事務並添加新的事務。 嘗試這個。

只是想報告我的發現,即使這個問題對於其他可能對已接受的答案有同樣問題的人來說有點老了。 對我來說,按照已接受的答案中建議的方法,使圖層重疊,很快使它們變得不可讀。 下面的代碼(改編自已接受的答案)避免了覆蓋,但仍將屏幕添加到后堆棧。

fragmentManager.beginTransaction().replace(R.id.container, fragment).addToBackStack("fragBack").commit();

在某些情況下,您必須使用替換,然后您無法使用 addtobackstack(),因此您可以在 MainActivity 中使用此代碼。 在這段代碼中,當您按下返回鍵時,您總是會轉到第一個片段(我稱之為 HomeFragment),而當您在 HomeFragment 中時,它會詢問兩次退出應用程序的時間。

 private Boolean exit = false;
@Override
    public void onBackPressed() {
        if (exit) {
            super.onBackPressed();
            return;
        }

    try {
        FragmentManager fragmentManager = getSupportFragmentManager();
        Fragment fragment = fragmentManager.findFragmentByTag("HOME");
        if (fragment != null) {
            if (fragment.isVisible()) {
                this.exit = true;
                Toast.makeText(this, "Press Back again to Exit", Toast.LENGTH_SHORT).show();
            }
        }
        else {
            fragment = HomeFragment.class.newInstance();
            getFragmentManager().popBackStack();
            fragmentManager.beginTransaction().replace(R.id.flContent, fragment, "HOME").commit();
        }
    } catch (Exception e) {

    }
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            exit = false;
        }
    }, 2000);
}
 - @Override
       public void onBackPressed() {
           DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
           int backstack = getSupportFragmentManager().getBackStackEntryCount();
           if (drawer.isDrawerOpen(GravityCompat.START)) {
               drawer.closeDrawer(GravityCompat.START);
           } else if (backstack > 0) {
              for (int i = 0; i < backstack; i++) {
                   getSupportFragmentManager().popBackStackImmediate();
            }
       } else {
           this.finish();
        }
    }

我有 4 個片段附加到底部導航活動,我最近遇到了這個問題並成功解決了如下我的活動代碼

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.NavigationUI;

import android.os.Bundle;
import android.view.MenuItem;

import com.google.android.material.bottomnavigation.BottomNavigationView;

public class BottomNavigationActivity extends AppCompatActivity
{
    NavController navController;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bottom_navigation);


        BottomNavigationView bottomNavigationView=findViewById(R.id.bottom_navigation);
        bottomNavigationView.setOnNavigationItemSelectedListener(navListener);

        getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,new FragmentHome()).commit();


    }

    public boolean onSupportNavigateUp() {
        return navController.navigateUp();
    }

    private BottomNavigationView.OnNavigationItemSelectedListener navListener= new
            BottomNavigationView.OnNavigationItemSelectedListener()
            {
                @Override
                public boolean onNavigationItemSelected(@NonNull MenuItem item)
                {

                    Fragment selectedFragment = null ;


                    switch (item.getItemId())
                    {

                        case R.id.nav_home:
                            selectedFragment = new FragmentHome();

                            break;

                        case R.id.nav_search:
                            BottomNavigationActivity.this.getSupportFragmentManager().beginTransaction()
                                    .addToBackStack(null)
                                    .commit();
                            selectedFragment=new FragmentSearch();
                            break;

                        case R.id.nav_cart:
                            BottomNavigationActivity.this.getSupportFragmentManager().beginTransaction()
                                    .addToBackStack(null)
                                    .commit();
                            selectedFragment=new FragmentCart();
                            break;

                        case R.id.nav_user:
                            BottomNavigationActivity.this.getSupportFragmentManager().beginTransaction()
                                    .addToBackStack(null)
                                    .commit();
                                selectedFragment= new FragmentAccount();
                                        break;


                    }

                    getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
                            selectedFragment).commit();

                    return true;

                }
            };


    @Override
    public void onBackPressed()
    {
        int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();
        if (backStackEntryCount == 0) {
            super.onBackPressed();
        } else
            {
            goHome();
        }
    }

    public void goHome()
    {
        //Following code will set the icon of the bottom navigation to active
        final BottomNavigationView mBottomNav = findViewById(R.id.bottom_navigation);
        MenuItem homeItem = mBottomNav.getMenu().getItem(0);
        mBottomNav.setSelectedItemId(homeItem.getItemId());
        getSupportFragmentManager().popBackStackImmediate();

        //To delete all entries from back stack immediately one by one.
        int backStackEntry = getSupportFragmentManager().getBackStackEntryCount();
        for (int i = 0; i < backStackEntry; i++) {
            getSupportFragmentManager().popBackStackImmediate();
        }
        //To navigate to the Home Fragment
        final FragmentHome homeFragment = new FragmentHome();
        FragmentTransaction myFragmentTransaction = getSupportFragmentManager().beginTransaction();
        myFragmentTransaction.replace(R.id.fragment_container, homeFragment, "HomeFrag Tag");
        myFragmentTransaction.commit();
    }
}

我建議onBackPressed()通過正確管理您的交易來避免完全覆蓋onBackPressed() 這將有助於避免在未來實施瘋狂的邏輯。

首先,我們需要設置一個私有類變量,以啟用初始化:

private boolean popNext = false;

下面的代碼允許我們通過將它放在堆棧上來設置初始返回函數。 此后每次當popNext設置為 true 時,我們都會彈出初始事務並推送新事務。 所以我們用1>Y事務替換1>X事務。

額外的嵌入式if語句處理選擇初始項,因為我們不想從1>1 開始 如果這是我們的初始案例,我們只需關閉抽屜。 另一種情況需要像后退按鈕一樣起作用,但我們需要記住將其設置為好像返回初始狀態!

if(popNext){
    if(i == INITIAL_POSITION){
        onBackPressed();
        mDrawerLayout.closeDrawer(mDrawerList);
        popNext = false;
        return;
    }
    getFragmentManager().popBackStackImmediate();
}
else{
    if(i == INITIAL_POSITION){
        mDrawerLayout.closeDrawer(mDrawerList);
        return;
    }
    popNext=true;
}
getFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, fragment)
.addToBackStack(null)
.commit();

注意:我的代碼使用getFragmentManager()而不是getSupportFragmentManager()這是一個本機函數,我相信從 Honeycomb 開始。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM