在 Android 中使用片段时处理后按

Posted

技术标签:

【中文标题】在 Android 中使用片段时处理后按【英文标题】:Handling back press when using fragments in Android 【发布时间】:2014-04-28 11:28:14 【问题描述】:

我在我的应用程序中使用带有导航抽屉的 android 滑动菜单,并且在应用程序中使用片段而不是活动。 当我打开抽屉时,单击一个出现片段的项目。我使用以下代码从一个片段移动到另一个片段:

Fragment fragment = null;
fragment = new GalleryFragment(selectetdMainMenu.getCategoryID());
                    FragmentTransaction ft = getFragmentManager().beginTransaction();
                    ft.addToBackStack("menuFrag");
                    ft.add(R.id.frame_container, fragment, "menuFrag");
                    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                    ft.commit();

通过这种方式,我可以从一个片段转到另一个片段,但在按下后退按钮时我无法到达前一个片段。我设法想出了这段代码来处理初始化抽屉的 MainActivity 中的后按:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) 
    super.onKeyDown(keyCode, event);
    if (keyCode == KeyEvent.KEYCODE_BACK) 
        Fragment fragment_byTag = fragmentManager.findFragmentByTag("menuFrag");
        Fragment menuFragment_by_tag = fragmentManager.findFragmentByTag("galleryFrag");
        Fragment commentsFrag_by_tag = fragmentManager.findFragmentByTag("commentsFrag");
        Fragment dealDetail = fragmentManager.findFragmentByTag("promoFrag");
            if(commentsFrag_by_tag != null)
                if (commentsFrag_by_tag.isVisible()) 
                    Log.e("comments back  ", " clicked");
                    //menuDetailsFrag.onBackPressed();
                    FragmentManager fragmentManager = getSupportFragmentManager();
                    fragmentManager.beginTransaction().remove(commentsFrag_by_tag).commit();
                    fragmentManager.beginTransaction().show(menuFragment_by_tag).commit();
                
            else if(menuFragment_by_tag.isVisible())
                Log.e("menu back  ", " clicked");
                menuDetailsFrag.onBackPressed();
                FragmentManager fragmentManager = getSupportFragmentManager();
                fragmentManager.beginTransaction().remove(menuFragment_by_tag).commit();
                fragmentManager.beginTransaction().show(fragment_byTag).commit();
            
        



    return false;

这有时有效,但大部分时间都失败了。如果可以显示更好的导航方式,我将不胜感激。

【问题讨论】:

看看这个 .. ***.com/questions/22552653/… add this ft.addToBackStack(null);ft.commit(); 将片段添加到后台堆栈并弹出它们。 ***.com/questions/22550420/… @Raghunandan。我找到的最简单的解决方案是你的。 我知道这篇文章很旧,但请看我的回答:***.com/a/45430033/3999826 【参考方案1】:

我通常将onKeyListener 设置为onResume 中的View。据我所知,您必须注意在View 上设置setFocusableInTouchMode()requestFocus

这是我用于此目的的示例:

@Override
public void onResume() 

    super.onResume();

    getView().setFocusableInTouchMode(true);
    getView().requestFocus();
    getView().setOnKeyListener(new View.OnKeyListener() 
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) 

            if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK)

                // handle back button

                return true;

            

            return false;
        
    );

【讨论】:

我在哪里放置此代码?片段或主要活动> 这行得通。我添加了 getActivity().getSupportFragmentManager().popBackStack();处理后按。 onresume 中有 keyevent 的原因是什么? @super-qua,片段的绝佳解决方案 如果您在片段中有一个可以获得焦点的子视图,这将停止工作。例如,如果您在片段中有“列表状态”和“编辑状态”,则进入其中包含EditText 的“编辑状态”,选择EditText,主视图将失去焦点并且onKey() 将停止运行,除非您手动重新获得基本视图的焦点。【参考方案2】:

试试这些方法。对我来说,最有用的解决方案如下:

在 MainActivity 中:

getSupportFragmentManager().beginTransaction().replace(R.id.gif_contents, gifPageTwoFragment, "gifPageTwoFragment").addToBackStack("gifPageTwoFragment").commit();

在 GifPageTwoFragment 中:

@Override
    public void onActivityCreated(Bundle savedInstanceState) 
        super.onActivityCreated(savedInstanceState);
        getView().setFocusableInTouchMode(true);
        getView().requestFocus();
        getView().setOnKeyListener(new View.OnKeyListener() 
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) 
                if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) 
                    Log.e("gif--","fragment back key is clicked");
                    getActivity().getSupportFragmentManager().popBackStack("gifPageTwoFragment", FragmentManager.POP_BACK_STACK_INCLUSIVE);
                    return true;
                
                return false;
            
        );
    

【讨论】:

【参考方案3】:

在您的 oncreateView() 方法中,您需要编写此代码,在 KEYCODE_BACk 条件下,您可以编写任何您想要的功能

   View v = inflater.inflate(R.layout.xyz, container, false);
    //Back pressed Logic for fragment
    v.setFocusableInTouchMode(true);
    v.requestFocus();
    v.setOnKeyListener(new View.OnKeyListener() 
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) 
            if (event.getAction() == KeyEvent.ACTION_DOWN) 
                if (keyCode == KeyEvent.KEYCODE_BACK) 
                    getActivity().finish();
                    Intent intent = new Intent(getActivity(), MainActivity.class);
                    startActivity(intent);

                    return true;
                
            
            return false;
        
    );

【讨论】:

这对我来说是完美的【参考方案4】:
        view.setFocusableInTouchMode(true);
        view.requestFocus();
        view.setOnKeyListener(new View.OnKeyListener() 
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event)   
        if (keyCode == KeyEvent.KEYCODE_BACK) 


            Fragment NameofFragment = new NameofFragment;

            FragmentTransaction  transaction=getFragmentManager().beginTransaction();
            transaction.replace(R.id.frame_container,NameofFragment);

            transaction.commit();

            return true;
        
        return false;
    
);

return view;

【讨论】:

【参考方案5】:

使用这个(在 kotlin 中)

activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) 
    override fun handleOnBackPressed() 
        // in here you can do logic when backPress is clicked
    
)

我认为这是最优雅的方式

【讨论】:

以上是关于在 Android 中使用片段时处理后按的主要内容,如果未能解决你的问题,请参考以下文章

使用选项卡活动和片段时如何处理后按

Native Android App中的颤振,后按不起作用

使用导航从一个片段导航到另一个片段后,防止后按工作

在片段的后按防止使用导航图调用前一个片段的 onViewCreated

处理仅在单击时更新 UI 数据的活动的后按?

Android studio 动态片段根据日期