Android Handling back press when using fragments in Android

本文介绍了如何在Android应用中使用Fragment进行页面切换,并通过不同方式处理返回按键来实现页面回退的功能。文中提供了具体的代码实例,包括如何设置监听器以及如何在Fragment内部处理返回键事件。

In MainActivity:

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

In 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;
            }
        });
    }

In your oncreateView() method you need to write this code and in KEYCODE_BACk condition you can write whatever the functionality you want

  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;
        }
    });
 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;

繁琐的方法:

I am using Android Sliding Menu using Navigation Drawer in my application and Fragments are used in the app instead of Activities. When I open the drawer, click on an item a Fragment appears. I move from one fragment to another fragment using the following code:

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();

In this way I can go from one fragment to another but I fail to come to the previous fragment on back button press. I managed to come up with this code to handle back press in MainActivity where Drawer is Initialized:

@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;
}

This works at times but fails most of the time. I would greatly appreciate if a better way to navigate back can be shown.

 

 

I am using Android Sliding Menu using Navigation Drawer in my application and Fragments are used in the app instead of Activities. When I open the drawer, click on an item a Fragment appears. I move from one fragment to another fragment using the following code:

Fragment fragment =null;
fragment =newGalleryFragment(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();

In this way I can go from one fragment to another but I fail to come to the previous fragment on back button press. I managed to come up with this code to handle back press in MainActivity where Drawer is Initialized:

@Overridepublicboolean onKeyDown(int keyCode,KeyEventevent){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();}}elseif(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();}}returnfalse;}

This works at times but fails most of the time. I would greatly appreciate if a better way to navigate back can be shown.

share improve this question
 
   
1 
add this ft.addToBackStack(null);ft.commit(); add the fragments to the backstack and pop them. stackoverflow.com/questions/22550420/… –  Raghunandan  Mar 21 '14 at 7:45 
   
@Raghunandan. The easiest solution I found is yours. –  YuDroid  Nov 29 '14 at 12:21

4 Answers

up vote 46 down vote accepted

I usually set an onKeyListener to the View in onResume. From what I learned you have to take care to set setFocusableInTouchMode() and requestFocus on the View.

This is a sample of what I use for this purpose:

@Overridepublicvoid onResume(){super.onResume();

    getView().setFocusableInTouchMode(true);
    getView().requestFocus();
    getView().setOnKeyListener(newView.OnKeyListener(){@Overridepublicboolean onKey(View v,int keyCode,KeyEventevent){if(event.getAction()==KeyEvent.ACTION_UP && keyCode ==KeyEvent.KEYCODE_BACK){// handle back buttonreturntrue;}returnfalse;}});}
share improve this answer
 
   
where do I place this code? fragment or main activity> –  TharakaNirmana  Mar 21 '14 at 8:16
   
The code goes in the fragment. Hope this helps –  super-qua  Mar 21 '14 at 8:17
   
This worked. I added getActivity().getSupportFragmentManager().popBackStack(); to handle back press. –  TharakaNirmana  Mar 24 '14 at 5:02
1 
@super-qua, superb solution for fragment –  Hiren Patel  Nov 26 '14 at 8:54
5 
This will stop working if you have a child view within the fragment that can gain focus. For example if you have a "list state" and "edit state" in the fragment, you go into the "edit state" that has an EditText within it, select the EditText, the main view will lose focus and the onKey() will stop functioning unless you manually regain focus of the base view. –  wchristiansen  Dec 1 '15 at 21:10

Try these methods. To me, the most useful solution is as follows:

In MainActivity:

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

In GifPageTwoFragment:

@Overridepublicvoid onActivityCreated(Bundle savedInstanceState){super.onActivityCreated(savedInstanceState);
        getView().setFocusableInTouchMode(true);
        getView().requestFocus();
        getView().setOnKeyListener(newView.OnKeyListener(){@Overridepublicboolean onKey(View v,int keyCode,KeyEventevent){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);returntrue;}returnfalse;}});}
share improve this answer
 

In your oncreateView() method you need to write this code and in KEYCODE_BACk condition you can write whatever the functionality you want

View v = inflater.inflate(R.layout.xyz, container,false);//Back pressed Logic for fragment
    v.setFocusableInTouchMode(true);
    v.requestFocus();
    v.setOnKeyListener(newView.OnKeyListener(){@Overridepublicboolean onKey(View v,int keyCode,KeyEventevent){if(event.getAction()==KeyEvent.ACTION_DOWN){if(keyCode ==KeyEvent.KEYCODE_BACK){
                    getActivity().finish();Intent intent =newIntent(getActivity(),MainActivity.class);
                    startActivity(intent);returntrue;}}returnfalse;}});
share improve this answer
 
   
This was perfect for me –  Adi  May 18 '16 at 12:41
        view.setFocusableInTouchMode(true);
        view.requestFocus();
        view.setOnKeyListener(newView.OnKeyListener(){@Overridepublicboolean onKey(View v,int keyCode,KeyEventevent){if(keyCode ==KeyEvent.KEYCODE_BACK){FragmentNameofFragment=newNameofFragment;FragmentTransaction  transaction=getFragmentManager().beginTransaction();
            transaction.replace(R.id.frame_container,NameofFragment);

            transaction.commit();returntrue;}returnfalse;}});return view;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值