programing

Android Fragment 핸들 뒤로 버튼 누르기

yoursource 2023. 9. 4. 22:53
반응형

Android Fragment 핸들 뒤로 버튼 누르기

제 활동에 약간의 파편이 있습니다.

[1], [2], [3], [4], [5], [6]

그리고 Back Button(뒤로 버튼)에서 I를 누르면 현재 활성 fragment가 [2]인 경우 [2]에서 [1]로 되돌아가거나 다른 작업을 수행하지 않습니다.

그것을 하는 가장 좋은 방법은 무엇입니까?

편집: 응용 프로그램이 [3]...[6]에서 [2]로 되돌아가면 안 됩니다.

Fragments할 때 Fragments를 합니다.addToBackStack()의 의일서의 로서.FragmentTransaction:

FragmentTransaction tx = fragmentManager.beginTransation();
tx.replace( R.id.fragment, new MyFragment() ).addToBackStack( "tag" ).commit();

제어가 를 들어 Fragment가 에는 보가예다일경필우한요제가어경우싶상은로뒤키누고를르때될시표세한부예▁an▁if가),경▁set경(▁()우▁control싶▁the우▁you▁you보다▁can은▁detailed▁back▁more▁keyi:▁require고르,▁suppress),OnKeyListener조각의 상위 보기에서:

//You need to add the following line for this solution to work; thanks skayred
fragment.getView().setFocusableInTouchMode(true);
fragment.getView().requestFocus();
fragment.getView().setOnKeyListener( new OnKeyListener()
{
    @Override
    public boolean onKey( View v, int keyCode, KeyEvent event )
    {
        if( keyCode == KeyEvent.KEYCODE_BACK )
        {
            return true;
        }
        return false;
    }
} );

저는 차라리 다음과 같은 것을 하고 싶습니다.

private final static String TAG_FRAGMENT = "TAG_FRAGMENT";

private void showFragment() {
    final Myfragment fragment = new MyFragment();
    final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.replace(R.id.fragment, fragment, TAG_FRAGMENT);
    transaction.addToBackStack(null);
    transaction.commit();
}

@Override
public void onBackPressed() {
    final Myfragment fragment = (Myfragment) getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT);

    if (fragment.allowBackPressed()) { // and then you define a method allowBackPressed with the logic to allow back pressed or not
        super.onBackPressed();
    }
}

fragment 뷰에 대해 onKey 메서드를 재정의하는 경우:

    view.setFocusableInTouchMode(true);
    view.requestFocus();
    view.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                Log.i(tag, "keyCode: " + keyCode);
                if( keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
                    Log.i(tag, "onKey Back listener is working!!!");
                    getFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
                    return true;
                } 
                return false;
            }
        });

한 조각을 다른 조각으로 바꿀 때 addToBackStack 메서드를 사용합니다.

getFragmentManager().beginTransaction().replace(R.id.content_frame, fragment).addToBackStack("my_fragment").commit();

그런 다음 활동에서 다음 코드를 사용하여 조각에서 다른 조각(이전 코드)으로 돌아갑니다.

@Override
public void onBackPressed() {
    if (getParentFragmentManager().getBackStackEntryCount() > 0) {
        getParentFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
}

하드웨어 Back 키 이벤트를 처리하려면 fragment의 onActivityCreated() 메서드에서 다음 코드를 수행해야 합니다.

Action_Down 또는 Action_도 확인해야 합니다.UP 이벤트.확인하지 않을 경우 onKey() Method에서 두 번 호출됩니다.

또한 루트 뷰(getView()에 포커스가 포함되지 않으면 작동하지 않습니다.컨트롤을 클릭한 경우 다시 getView().requestFocus()를 사용하여 루트 뷰에 포커스를 지정해야 합니다. 이 후에는 onKeydown()만 호출됩니다.

getView().setFocusableInTouchMode(true);
getView().requestFocus();

getView().setOnKeyListener(new OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    if (keyCode == KeyEvent.KEYCODE_BACK) {
                        Toast.makeText(getActivity(), "Back Pressed", Toast.LENGTH_SHORT).show();
                    return true;
                    }
                }
                return false;
            }
        });

저를 위해 아주 잘 일하고 있습니다.

인터페이스 만들기:

뒤로 단추 처리기인터페이스

public interface BackButtonHandlerInterface {
    void addBackClickListener (OnBackClickListener onBackClickListener);
    void removeBackClickListener (OnBackClickListener onBackClickListener);
}

OnBackClick 수신기

public interface OnBackClickListener {
     boolean onBackClick();
}

활동 중:

public class MainActivity extends AppCompatActivity implements BackButtonHandlerInterface {

    private ArrayList<WeakReference<OnBackClickListener>> backClickListenersList = new ArrayList<>();

    @Override
    public void addBackClickListener(OnBackClickListener onBackClickListener) {
        backClickListenersList.add(new WeakReference<>(onBackClickListener));
    }

    @Override
    public void removeBackClickListener(OnBackClickListener onBackClickListener) {
        for (Iterator<WeakReference<OnBackClickListener>> iterator = backClickListenersList.iterator();
         iterator.hasNext();){
            WeakReference<OnBackClickListener> weakRef = iterator.next();
            if (weakRef.get() == onBackClickListener){
                iterator.remove();
            }
        }
    }

    @Override
    public void onBackPressed() {
        if(!fragmentsBackKeyIntercept()){
            super.onBackPressed();
        }
    }

    private boolean fragmentsBackKeyIntercept() {
        boolean isIntercept = false;
        for (WeakReference<OnBackClickListener> weakRef : backClickListenersList) {
            OnBackClickListener onBackClickListener = weakRef.get();
            if (onBackClickListener != null) {
                boolean isFragmIntercept = onBackClickListener.onBackClick();
                if (!isIntercept) isIntercept = isFragmIntercept;
            }
        }
        return isIntercept;
    }
}

조각 내:

public class MyFragment extends Fragment implements OnBackClickListener{

    private BackButtonHandlerInterface backButtonHandler;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        backButtonHandler = (BackButtonHandlerInterface) activity;
        backButtonHandler.addBackClickListener(this);
    }

    @Override
    public void onDetach() {
        super.onDetach();
        backButtonHandler.removeBackClickListener(this);
        backButtonHandler = null;
    }

    @Override
    public boolean onBackClick() {
        //This method handle onBackPressed()! return true or false
        return false;
    }

}

갱신하다

사용자 지정 후방 탐색 제공

class MyFragment : Fragment() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // This callback will only be called when MyFragment is at least Started.
        val callback = requireActivity().onBackPressedDispatcher.addCallback(this) {
            // Handle the back button event
        }

        // The callback can be enabled or disabled here or in the lambda
    }

}

이를 위한 가장 이상적인 방법은 다음과 같습니다: 프래그먼트: 뒤로 버튼을 누르고 사용자 지정할 때 호출되는 콜백.

public class MyActivity extends Activity
{
    //...
    //Defined in Activity class, so override
    @Override
    public void onBackPressed()
    {
        super.onBackPressed();
        myFragment.onBackPressed();
    }
}

public class MyFragment extends Fragment
{
    //Your created method
    public static void onBackPressed()
    {
        //Pop Fragments off backstack and do your other checks
    }
}

 @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){

                    if (mDrawerLayout.isDrawerOpen(GravityCompat.START)){
                        mDrawerLayout.closeDrawer(GravityCompat.START);
                    }
                    return true;
                }

                return false;
            }
        });
    }

모든 솔루션을 살펴본 후에 훨씬 더 간단한 솔루션이 있다는 것을 깨달았습니다.

모든 fragment를 호스팅하는 활동의 onBackPressed()에서 백프레스를 방지할 fragment를 찾습니다.발견되면 그냥 돌아가세요.그러면 이 조각에 대해 popBackStack이 발생하지 않습니다.

  @Override
public void onBackPressed() {

        Fragment1 fragment1 = (Fragment1) getFragmentManager().findFragmentByTag(“Fragment1”);
        if (fragment1 != null)
            return;

        if (getFragmentManager().getBackStackEntryCount() > 0){
            getFragmentManager().popBackStack();

        }
}

여러 조각 및/또는 활동에서 백프레스를 처리할 수 있는 작은 라이브러리를 만들었습니다.사용은 Gradle 파일에 종속성을 추가하는 것만큼 간단합니다.

compile 'net.skoumal.fragmentback:fragment-back:0.1.0'

의 단편이 각을구니다합현을 구현하도록 .BackFragment인터페이스:

public abstract class MyFragment extends Fragment implements BackFragment {

    public boolean onBackPressed() {

        // -- your code --

        // return true if you want to consume back-pressed event
        return false;
    }

    public int getBackPriority() {
        return NORMAL_BACK_PRIORITY;
    }
}

백프레스에 대해 단편에 알립니다.

public class MainActivity extends AppCompatActivity {

    @Override
    public void onBackPressed() {
        // first ask your fragments to handle back-pressed event
        if(!BackFragmentHelper.fireOnBackPressedEvent(this)) {
            // lets do the default back action if fragments don't consume it
            super.onBackPressed();
        }
    }
}

자세한 내용 및 기타 사용 사례는 GitHub 페이지를 참조하십시오.

https://github.com/skoumalcz/fragment-back

아니면 당신은 사용할 수 있습니다.getSupportFragmentManager().getBackStackEntryCount()수행할 작업 확인하기

@Override
    public void onBackPressed() {

        logger.d("@@@@@@ back stack entry count : " + getSupportFragmentManager().getBackStackEntryCount());

        if (getSupportFragmentManager().getBackStackEntryCount() != 0) {

            // only show dialog while there's back stack entry
            dialog.show(getSupportFragmentManager(), "ConfirmDialogFragment");

        } else if (getSupportFragmentManager().getBackStackEntryCount() == 0) {

            // or just go back to main activity
            super.onBackPressed();
        }
    }

모든 트랜잭션을 백스택에 추가하는 흐름을 관리하는 경우 사용자가 뒤로 버튼을 누를 때 이전 조각을 표시하기 위해 다음과 같은 작업을 수행할 수 있습니다(홈 버튼도 매핑할 수 있음).

@Override
public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() > 0)
        getFragmentManager().popBackStack();
    else
        super.onBackPressed();
}

정적 프래그먼트를 사용하는 사용자용

만약 당신이 정적인 파편을 가지고 있다면 그것이 더 좋을 것입니다.조각의 인스턴스 개체 만들기

private static MyFragment instance=null;

MyFragment의 onCreate()에서 해당 인스턴스를 초기화

  instance=this;

또한 인스턴스를 가져오는 함수를 만듭니다.

 public static MyFragment getInstance(){
   return instance;
}

또한 기능을 만듭니다.

public boolean allowBackPressed(){
    if(allowBack==true){
        return true;
    }
    return false;
}


 //allowBack is a boolean variable that will be set to true at the action 
 //where you want that your backButton should not close activity. In my case I open 
 //Navigation Drawer then I set it to true. so when I press backbutton my 
 //drawer should be get closed

public void performSomeAction(){
    //.. Your code
    ///Here I have closed my drawer
}

당신의 활동에서 당신은 할 수 있습니다.

@Override
public void onBackPressed() {

    if (MyFragment.getInstance().allowBackPressed()) { 
        MyFragment.getInstance().performSomeAction();
    }
    else{
        super.onBackPressed();
    }
}

작업 코드:

package com.example.keralapolice;

import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentManager.OnBackStackChangedListener;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

public class ChiefFragment extends Fragment {
    View view;

    // public OnBackPressedListener onBackPressedListener;

    @Override
    public View onCreateView(LayoutInflater inflater,
            ViewGroup container, Bundle args) {

        view = inflater.inflate(R.layout.activity_chief, container, false);
        getActivity().getActionBar().hide();
        view.setFocusableInTouchMode(true);
        view.requestFocus();
        view.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                Log.i(getTag(), "keyCode: " + keyCode);
                if (keyCode == KeyEvent.KEYCODE_BACK) {
                    getActivity().getActionBar().show();
                    Log.i(getTag(), "onKey Back listener is working!!!");
                    getFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
                    // String cameback="CameBack";
                    Intent i = new Intent(getActivity(), home.class);
                    // i.putExtra("Comingback", cameback);
                    startActivity(i);
                    return true;
                } else {
                    return false;
                }
            }
        });
        return view;
    }
}

제 생각에 가장 쉬운 방법은 인터페이스를 만들고 Activity에서 fragment가 인터페이스 유형인지 확인하고, 만약 그렇다면 pop을 처리하기 위해 메서드를 호출하는 것입니다.다음은 fragment에 구현할 인터페이스는 다음과 같습니다.

public interface BackPressedFragment {

    // Note for this to work, name AND tag must be set anytime the fragment is added to back stack, e.g.
    // getActivity().getSupportFragmentManager().beginTransaction()
    //                .replace(R.id.fragment_container, MyFragment.newInstance(), "MY_FRAG_TAG")
    //                .addToBackStack("MY_FRAG_TAG")
    //                .commit();
    // This is really an override. Should call popBackStack itself.
    void onPopBackStack();
}

구현 방법은 다음과 같습니다.

public class MyFragment extends Fragment implements BackPressedFragment
    @Override
    public void onPopBackStack() {
        /* Your code goes here, do anything you want. */
        getActivity().getSupportFragmentManager().popBackStack();
}

또한 활동에서 팝업을 처리할 때(BackPressed와 Options 모두에서 발생할 수 있음)항목 선택됨), 다음 방법을 사용하여 백스택을 팝합니다.

public void popBackStack() {
    FragmentManager fm = getSupportFragmentManager();
    // Call current fragment's onPopBackStack if it has one.
    String fragmentTag = fm.getBackStackEntryAt(fm.getBackStackEntryCount() - 1).getName();
    Fragment currentFragment = getSupportFragmentManager().findFragmentByTag(fragmentTag);
    if (currentFragment instanceof BackPressedFragment)
        ((BackPressedFragment)currentFragment).onPopBackStack();
    else
        fm.popBackStack();
}

Sliding Menu와 Fragment와 함께 작업하고 있습니다. 여기서 제 사례를 제시하고 누군가에게 도움이 되기를 바랍니다.

[Back](뒤로) 키를 눌렀을 때의 로직:

  1. 슬라이딩 메뉴가 표시되면 닫을 수 있습니다. 더 이상 할 일이 없습니다.
  2. 또는 두 번째(또는 그 이상) 조각이 표시되면 이전 조각으로 다시 이동하여 더 이상 수행할 작업이 없습니다.
  3. 슬라이딩 메뉴는 표시되지 않으며, 현재 Fragment는 #0이며, 원래 [Back](뒤로) 키를 수행합니다.

    public class Main extends SherlockFragmentActivity
    {
      private SlidingMenu menu=null;
      Constants.VP=new ViewPager(this);
    
      //Some stuff...
    
      @Override
      public void onBackPressed()
      {
        if(menu.isMenuShowing())
        {
          menu.showContent(true); //Close SlidingMenu when menu showing
          return;
        }
        else
        {
          int page=Constants.VP.getCurrentItem();
          if(page>0)
          {
            Constants.VP.setCurrentItem(page-1, true); //Show previous fragment until Fragment#0
            return;
          }
          else
          {super.onBackPressed();} //If SlidingMenu is not showing and current Fragment is #0, do the original [Back] key does. In my case is exit from APP
        }
      }
    }
    

이는 매우 우수하고 신뢰할 수 있는 솔루션입니다. http://vinsol.com/blog/2014/10/01/handling-back-button-press-inside-fragments/

그 남자는 backPress 동작을 처리하는 추상 조각을 만들었고 전략 패턴을 사용하여 활성 조각 사이를 전환하고 있습니다.

여러분 중 몇몇에게는 추상적인 수업에서 약간의 단점이 있을 수 있습니다.

링크의 솔루션은 다음과 같습니다.

// Abstract Fragment handling the back presses

public abstract class BackHandledFragment extends Fragment {
    protected BackHandlerInterface backHandlerInterface;
    public abstract String getTagText();
    public abstract boolean onBackPressed();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(!(getActivity()  instanceof BackHandlerInterface)) {
            throw new ClassCastException("Hosting activity must implement BackHandlerInterface");
        } else {
            backHandlerInterface = (BackHandlerInterface) getActivity();
        }
    }

    @Override
    public void onStart() {
        super.onStart();

        // Mark this fragment as the selected Fragment.
        backHandlerInterface.setSelectedFragment(this);
    }

    public interface BackHandlerInterface {
        public void setSelectedFragment(BackHandledFragment backHandledFragment);
    }
}   

활동에서의 사용:

// BASIC ACTIVITY CODE THAT LETS ITS FRAGMENT UTILIZE onBackPress EVENTS 
// IN AN ADAPTIVE AND ORGANIZED PATTERN USING BackHandledFragment

public class TheActivity extends FragmentActivity implements BackHandlerInterface {
    private BackHandledFragment selectedFragment;

    @Override
    public void onBackPressed() {
        if(selectedFragment == null || !selectedFragment.onBackPressed()) {
            // Selected fragment did not consume the back press event.
            super.onBackPressed();
        }
    }

    @Override
    public void setSelectedFragment(BackHandledFragment selectedFragment) {
        this.selectedFragment = selectedFragment;
    }
}
            rootView.setFocusableInTouchMode(true);
            rootView.requestFocus();
            rootView.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 rootView;

fragment 트랜잭션에 addToBackStack()을 추가한 다음 fragment에 대한 Back Navigation 구현을 위해 아래 코드를 사용합니다.

getSupportFragmentManager().addOnBackStackChangedListener(
    new FragmentManager.OnBackStackChangedListener() {
        public void onBackStackChanged() {
            // Update your UI here.
        }
    });

Fragment Activity를 사용하는 경우.그럼 이렇게 해주세요.

먼저 이것을 당신의 조각 안에 불러들입니다.

public void callParentMethod(){
    getActivity().onBackPressed();
}

그런 다음 호출onBackPressed너의 부모님 안에 있는 방법FragmentActivity학급.

@Override
public void onBackPressed() {
  //super.onBackPressed();
  //create a dialog to ask yes no question whether or not the user wants to exit
  ...
}

에서 사용할 수 있습니다.getActionBar().setDisplayHomeAsUpEnabled():

@Override
public void onBackStackChanged() {
    int backStackEntryCount = getFragmentManager().getBackStackEntryCount();

    if(backStackEntryCount > 0){
        getActionBar().setDisplayHomeAsUpEnabled(true);
    }else{
        getActionBar().setDisplayHomeAsUpEnabled(false);
    }
}

활동에 이 코드 추가

@재지정

public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() == 0) {
        super.onBackPressed();
    } else {
        getFragmentManager().popBackStack();
    }
}

그리고 커밋하기 전에 fragment에 이 행을 추가합니다().

ft.addToBackStack("임의의 이름");

fragment 클래스에서 백 이벤트에 대해 다음 코드를 입력합니다.

 rootView.setFocusableInTouchMode(true);
        rootView.requestFocus();
        rootView.setOnKeyListener( new OnKeyListener()
        {
            @Override
            public boolean onKey( View v, int keyCode, KeyEvent event )
            {
                if( keyCode == KeyEvent.KEYCODE_BACK )
                {
                    FragmentManager fragmentManager = getFragmentManager();
                    fragmentManager.beginTransaction()
                            .replace(R.id.frame_container, new Book_service_provider()).commit();

                    return true;
                }
                return false;
            }
        } );

백스택 확인이 완벽하게 작동합니다.


@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
    if (keyCode == KeyEvent.KEYCODE_BACK)
    {
        if (getFragmentManager().getBackStackEntryCount() == 1)
        {
            // DO something here since there is only one fragment left
            // Popping a dialog asking to quit the application
            return false;
        }
    }
    return super.onKeyDown(keyCode, event);
}

oncreateView() 메서드에서 이 코드를 KEYCODE_B로 작성해야 합니다.원하는 기능을 원하는 대로 쓸 수 있는 확인 조건

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

언급URL : https://stackoverflow.com/questions/7992216/android-fragment-handle-back-button-press

반응형