簡體   English   中英

從android中的片段管理工具欄的導航和后退按鈕

[英]Manage toolbar's navigation and back button from fragment in android

我所有的片段都是通過ActionBarActivity (mainActivity) 控制的,在 mainActivity 內部實現了一個DrawerLayout ,所有的子片段都通過 drawerLayout 的列表項點擊推送。 我面臨的問題是在通過 drawerLayout 推送片段后,我想將抽屜圖標更改為ToolBar后退圖標,以便用戶可以導航到上一個片段並在內部處理android.R.id.home的回調相同的片段或在 mainActivity 內部。

我正在使用的代碼是:

主活動.java

public class MainActivity extends ActionBarActivity {
    private DrawerLayout layoutDrawer;
    private ActionBarDrawerToggle drawerToggler;
    private Stack<Fragment> stack;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        stack = new Stack<Fragment>();
        layoutDrawer = (DrawerLayout) findViewById(R.id.layout_drawer);
        drawerToggler = new ActionBarDrawerToggle(this, layoutDrawer, toolbar,
                R.string.app_name, R.string.app_name);
        layoutDrawer.setDrawerListener(drawerToggler);

        setUpDrawerList();
        pushFragment(new FirstFragment(), true);

        Session.setContext(getApplicationContext());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (drawerToggler.isDrawerIndicatorEnabled()
                && drawerToggler.onOptionsItemSelected(item))
            return true;
        switch (item.getItemId()) {
        case android.R.id.home:
            Toast.makeText(this, "Back from activity", Toast.LENGTH_SHORT)
                    .show();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        drawerToggler.syncState();
    }

    @Override
    public void onBackPressed() {
        popFragment();
    }

    private void setUpDrawerList() {
        ListView listView = (ListView) findViewById(R.id.list_drawer);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1,
                Arrays.asList(new String[] { "First Fragment",
                        "Second Fragment" }));
        listView.setAdapter(adapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                layoutDrawer.closeDrawers();
                drawerToggler.setDrawerIndicatorEnabled(false);
                getSupportActionBar().setDisplayHomeAsUpEnabled(true);
                pushFragment(getFragment(position), true);
            }
        });
    }

    private Fragment getFragment(int pos) {
        switch (pos) {
        case 0:
            return new FirstFragment();
        case 1:
            return new SecondFragment();
        }
        return null;
    }

    public void pushFragment(Fragment fragment, boolean add) {
        FragmentTransaction transation = getSupportFragmentManager()
                .beginTransaction();
        if (add)
            stack.push(fragment);
        transation.replace(R.id.layout_content, fragment);
        transation.commit();
    }

    public void popFragment() {
        if (!stack.isEmpty()) {
            Fragment fragment = stack.elementAt(stack.size() - 2);
            stack.pop();
            pushFragment(fragment, false);
        } else
            super.onBackPressed();
        drawerToggler.setDrawerIndicatorEnabled(stack.size() == 1);
    }

    public void clearBackStack() {
        stack.clear();
    }
}

第一個片段.java

public class FirstFragment extends Fragment {

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setHasOptionsMenu(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_first, container, false);
    }

    @Override
    public void onResume() {
        super.onResume();
        ActionBar actionBar = ((ActionBarActivity)getActivity()).getSupportActionBar();
        actionBar.setTitle("First Fragment");
        actionBar.setDisplayHomeAsUpEnabled(true);
        actionBar.setHomeButtonEnabled(true);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        menu.clear();
        inflater.inflate(R.menu.fragment_menu, menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId()) {
        case android.R.id.home:
            Toast.makeText(getActivity(), "Back from fragment", Toast.LENGTH_SHORT).show();
            getActivity().onBackPressed();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

從上面的代碼中,我無法獲得android.R.id.home的回調,並且每次actionBar.setDisplayHomeAsUpEnabled(true);都無法設置主頁按鈕actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeButtonEnabled(true);

任何幫助將不勝感激。

謝謝

將工具欄添加到您的 xml

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Fragment title"/>

</android.support.v7.widget.Toolbar>

然后在 Fragment 中的 onCreateView 方法中:

Toolbar toolbar = view.findViewById(R.id.toolbar);
toolbar.setNavigationIcon(R.drawable.ic_back_button);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
         getActivity().onBackPressed();
    }
});

您必須在主 Activity 上管理按下后退按鈕的操作,因為您的主 Activity 是片段的容器。

首先,將您的所有片段添加到transaction.addToBackStack(null) ,現在導航后退按鈕調用將在主要活動中進行。 我希望下面的代碼可以幫助你...

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case android.R.id.home:
        onBackPressed();
        }
    return super.onOptionsItemSelected(item);
}

你也可以使用

Fragment fragment =fragmentManager.findFragmentByTag(Constant.TAG); 
if(fragment!=null) {          
      FragmentTransaction transaction = fragmentManager.beginTransaction();
      transaction.remove(fragment).commit();
}

並根據片段名稱更改標題,您可以使用以下代碼:

activity.getSupportActionBar().setTitle("Keyword Report Detail");

我有很多解決方案,但沒有一個能完美運行。 我在我的項目中使用了各種可用的解決方案,如下所示。 請在您初始化工具欄和抽屜布局的類中使用此代碼。

getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
                drawerFragment.mDrawerToggle.setDrawerIndicatorEnabled(false);
                getSupportActionBar().setDisplayHomeAsUpEnabled(true);// show back button
                toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        onBackPressed();
                    }
                });
            } else {
                //show hamburger
                drawerFragment.mDrawerToggle.setDrawerIndicatorEnabled(true);
                getSupportActionBar().setDisplayHomeAsUpEnabled(false);
                drawerFragment.mDrawerToggle.syncState();
                toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        drawerFragment.mDrawerLayout.openDrawer(GravityCompat.START);
                    }
                });
            }
        }
    });

可能是最干凈的解決方案:

abstract class NavigationChildFragment : Fragment() {

    abstract fun onCreateChildView(inflater: LayoutInflater,
                                   container: ViewGroup?,
                                   savedInstanceState: Bundle?): View?

    override fun onCreateView(inflater: LayoutInflater,
                              container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        val activity = activity as? MainActivity
        activity?.supportActionBar?.setDisplayHomeAsUpEnabled(true)
        setHasOptionsMenu(true)
        return onCreateChildView(inflater, container, savedInstanceState)
    }

    override fun onDestroyView() {
        val activity = activity as? MainActivity
        activity?.supportActionBar?.setDisplayHomeAsUpEnabled(false)
        setHasOptionsMenu(false)
        super.onDestroyView()
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        val activity = activity as? MainActivity
        return when (item.itemId) {
            android.R.id.home -> {
                activity?.onBackPressed()
                true
            }
            else              -> super.onOptionsItemSelected(item)
        }
    }
}

只需將此類用作所有應支持導航的 Fragment 的父類。

您可以在片段內部使用工具欄,它很容易處理。 首先將 Toolbar 添加到片段的布局中

<android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/toolbar"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:fitsSystemWindows="true"
    android:minHeight="?attr/actionBarSize"
    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    android:background="?attr/colorPrimaryDark">
</android.support.v7.widget.Toolbar>

在片段的 onCreateView 方法中,您可以像這樣處理工具欄。

 Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar);
 toolbar.setTitle("Title");
 toolbar.setNavigationIcon(R.drawable.ic_arrow_back);

它會將工具欄、標題和后退箭頭導航設置為工具欄。您可以將任何圖標設置為 setNavigationIcon 方法。

如果您需要在單擊工具欄導航圖標時觸發任何事件,您可以使用它。

 toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
           //handle any click event
    });

如果您的活動有導航抽屜,您可能需要在單擊導航返回按鈕時打開它。 你可以像這樣打開那個抽屜。

 toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            DrawerLayout drawer = (DrawerLayout) getActivity().findViewById(R.id.drawer_layout);
            drawer.openDrawer(Gravity.START);
        }
    });

完整代碼在這里

 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    //inflate the layout to the fragement
    view = inflater.inflate(R.layout.layout_user,container,false);

    //initialize the toolbar
    Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar);
    toolbar.setTitle("Title");
    toolbar.setNavigationIcon(R.drawable.ic_arrow_back);
    toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //open navigation drawer when click navigation back button
            DrawerLayout drawer = (DrawerLayout) getActivity().findViewById(R.id.drawer_layout);
            drawer.openDrawer(Gravity.START);
        }
    });
    return view;
}

首先添加導航返回按鈕

   getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    getSupportActionBar().setDisplayShowHomeEnabled(true);

然后,在您的 HostActivity 中添加方法。

 @Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId()==android.R.id.home)
    {
        super.onBackPressed();
        Toast.makeText(this, "OnBAckPressed Works", Toast.LENGTH_SHORT).show();
    }

    return super.onOptionsItemSelected(item);
}

試試這個,絕對有效。

(Kotlin) 在托管片段的活動中:

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
    when (item.itemId) {
        android.R.id.home -> {
            onBackPressed()
            return true
        }
    }
    return super.onOptionsItemSelected(item)
}

我發現當我向項目添加片段時,它們默認顯示操作欄主頁按鈕,刪除/禁用它把它放在 onViewCreated() 中(如果它沒有顯示,請使用 true 啟用它):

val actionBar = this.requireActivity().actionBar
    actionBar?.setDisplayHomeAsUpEnabled(false)

如果您正在使用 androidx 片段並希望在單擊返回主頁按鈕時返回 MainActivity,請使用以下代碼。

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    setHasOptionsMenu(true);
    ....
}


@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == android.R.id.home) {
        requireActivity().onBackPressed();
    }
    return super.onOptionsItemSelected(item);
}

我找到的最簡單的解決方案是簡單地把它放在你的片段中:

androidx.appcompat.widget.Toolbar toolbar = getActivity().findViewById(R.id.toolbar);
    toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            NavController navController = Navigation.findNavController(getActivity(), 
R.id.nav_host_fragment);
            navController.navigate(R.id.action_position_to_destination);
        }
    });

Personnaly 我想轉到另一個頁面,但當然您可以用要執行的操作替換 onClick 方法中的 2 行。

Kotlin 中可以處理標題欄后退動作導航欄后退動作並且可以從所有片段調用的通用方法是:

fun configureToolbarBackPress(
            customToolBar: Toolbar,
            parentVw: View,
            activity: Activity,
            title: String,
            targetResId: Int
        )    {
            customToolBar.setNavigationIcon(R.drawable.ic_arrow_back)
            customToolBar.title = title
            customToolBar.setNavigationOnClickListener {
                parentVw.findNavController().navigate(targetResId)
            }

            (activity as DashboardActivityNew).onBackPressedDispatcher.addCallback(
                object : OnBackPressedCallback(true) {
                    override fun handleOnBackPressed() {
                        parentVw.findNavController().navigate(targetResId)
                    }
                }
            )
        }

現在從任何片段調用這個方法 onViewCreated() 如下:

AppUtils.configureToolbarBackPress(
            customToolbar as Toolbar,
            view,
            requireActivity(),
            getString(R.string.title),
            R.id.mainFragment
        )

在 fragment.xml 中包含工具欄,如下所示:

<include
            android:id="@+id/customToolbar"
            layout="@layout/dashboard_toolbar" /> 

dashboard_toolbar.xml 的布局如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="@dimen/abc_action_bar_default_height_material"
    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    android:background="@color/colorPrimary"/>

OnToolBar 左側有一個導航圖標

Toolbar  toolbar = (Toolbar) findViewById(R.id.tool_bar);
        toolbar.setTitle(getResources().getString(R.string.title_activity_select_event));
        setSupportActionBar(toolbar);

        getSupportActionBar().setDisplayShowHomeEnabled(true);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

通過在左側導航圖標出現並在導航圖標上單擊它調用父活動。

在清單中,我們可以通知系統有關父活動的信息。

  <activity
            android:name=".CategoryCloudSelectActivity"
            android:parentActivityName=".EventSelectionActivity"
            android:screenOrientation="portrait" />

暫無
暫無

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

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