onBackPressed()
Android 활동에서 구현하는 방식과 비슷한 방식으로 Android Fragment에서 구현할 수 있는 방법이 있습니까?
조각 수명주기에는 없습니다 onBackPressed()
. onBackPressed()
안드로이드 3.0 프래그먼트 를 오버라이드 할 수있는 다른 방법이 있습니까?
onBackPressed()
Android 활동에서 구현하는 방식과 비슷한 방식으로 Android Fragment에서 구현할 수 있는 방법이 있습니까?
조각 수명주기에는 없습니다 onBackPressed()
. onBackPressed()
안드로이드 3.0 프래그먼트 를 오버라이드 할 수있는 다른 방법이 있습니까?
답변:
이 방법으로 onBackPressed
Activity에서 재정의 를 해결했습니다 . 모든이 FragmentTransaction
있습니다 addToBackStack
커밋하기 전에 :
@Override
public void onBackPressed() {
int count = getSupportFragmentManager().getBackStackEntryCount();
if (count == 0) {
super.onBackPressed();
//additional code
} else {
getSupportFragmentManager().popBackStack();
}
}
내 생각에 가장 좋은 해결책은 다음과 같습니다.
간단한 인터페이스를 만듭니다.
public interface IOnBackPressed {
/**
* If you return true the back press will not be taken into account, otherwise the activity will act naturally
* @return true if your processing has priority if not false
*/
boolean onBackPressed();
}
그리고 당신의 활동에서
public class MyActivity extends Activity {
@Override public void onBackPressed() {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.main_container);
if (!(fragment instanceof IOnBackPressed) || !((IOnBackPressed) fragment).onBackPressed()) {
super.onBackPressed();
}
} ...
}
마지막으로 조각에서 :
public class MyFragment extends Fragment implements IOnBackPressed{
@Override
public boolean onBackPressed() {
if (myCondition) {
//action not popBackStack
return true;
} else {
return false;
}
}
}
interface IOnBackPressed {
fun onBackPressed(): Boolean
}
class MyActivity : AppCompatActivity() {
override fun onBackPressed() {
val fragment =
this.supportFragmentManager.findFragmentById(R.id.main_container)
(fragment as? IOnBackPressed)?.onBackPressed()?.not()?.let {
super.onBackPressed()
}
}
}
class MyFragment : Fragment(), IOnBackPressed {
override fun onBackPressed(): Boolean {
return if (myCondition) {
//action not popBackStack
true
} else {
false
}
}
}
R.id.main_container
? 이것이 FragmentPager의 ID입니까?
.?
)를 혼합하고 널이 아닌 값 ( !!
)을 적용 하면 NPE가 발생할 수 있습니다. 캐스트가 항상 안전하지는 않습니다. 차라리 글을 if ((fragment as? IOnBackPressed)?.onBackPressed()?.not() == true) { ... }
쓰거나 좀 더 kotliney 하고 싶습니다(fragment as? IOnBackPressed)?.onBackPressed()?.not()?.let { ... }
.onBackPressed()?.takeIf { !it }?.let{...}
않습니까? .not()
그냥 역을 반환합니다.
val fragment = this.supportFragmentManager.findFragmentById(R.id.flContainer) as? NavHostFragment val currentFragment = fragment?.childFragmentManager?.fragments?.get(0) as? IOnBackPressed currentFragment?.onBackPressed()?.takeIf { !it }?.let{ super.onBackPressed() }
이것은 Kotlin과 NavigationController를 사용하는 사람들을위한 것입니다
@HaMMeRed에 따르면 여기에 의사 코드가 어떻게 작동 해야하는지에 대한 대답이 있습니다. BaseActivity
SlidingMenu lib 예제와 같이 하위 조각이있는 기본 활동이 호출되었다고 가정 해 봅시다. 단계는 다음과 같습니다.
먼저 일반적인 메소드를 갖도록 인터페이스를 구현하는 인터페이스와 클래스를 만들어야합니다.
수업 인터페이스 만들기 OnBackPressedListener
public interface OnBackPressedListener {
public void doBack();
}
의 기술을 구현하는 수업 만들기 OnBackPressedListener
public class BaseBackPressedListener implements OnBackPressedListener {
private final FragmentActivity activity;
public BaseBackPressedListener(FragmentActivity activity) {
this.activity = activity;
}
@Override
public void doBack() {
activity.getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}
이제부터 코드 BaseActivity
와 그 조각 에 대해 작업하겠습니다.
수업 위에 비공개 청취자 만들기 BaseActivity
protected OnBackPressedListener onBackPressedListener;
리스너를 설정하는 메소드 작성 BaseActivity
public void setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
this.onBackPressedListener = onBackPressedListener;
}
재정의에서 onBackPressed
그런 것을 구현하십시오.
@Override
public void onBackPressed() {
if (onBackPressedListener != null)
onBackPressedListener.doBack();
else
super.onBackPressed();
당신의 조각에 onCreateView
당신의 청취자를 추가해야합니다
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
activity = getActivity();
((BaseActivity)activity).setOnBackPressedListener(new BaseBackPressedListener(activity));
View view = ... ;
//stuff with view
return view;
}
Voila, 이제 조각으로 다시 클릭하면 사용자 정의 on back 메소드를 잡아야합니다.
onBackPressed()
경우 뒤로 버튼을 눌렀을 때 어떤 프래그먼트가 표시되고 있는지를 어떻게 확인 합니까?
((BaseActivity)activity).setOnBackPressedListener(new OnBackpressedListener(){ public void doBack() { //...your stuff here }});
이것은 나를 위해 일했다 : https://stackoverflow.com/a/27145007/3934111
@Override
public void onResume() {
super.onResume();
if(getView() == null){
return;
}
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's click listener
return true;
}
return false;
}
});
}
그런 종류의 기능을 원한다면 활동에서 기능을 재정의 한 다음 YourBackPressed
모든 조각에 인터페이스를 추가 해야합니다.이 단추를 누를 때마다 관련 조각을 호출합니다.
편집 : 이전 답변을 추가하고 싶습니다.
오늘이 작업을 수행하려면 다른 패널이 마스터 / 메인 콘텐츠 패널과 동시에 업데이트 될 것으로 예상되는 경우 브로드 캐스트 또는 주문 된 브로드 캐스트를 사용합니다.
LocalBroadcastManager
지원 라이브러리에서이 기능을 사용하면 브로드 캐스트를 전송하고 onBackPressed
관심있는 조각을 구독하면됩니다. 메시징은 더 분리 된 구현이며 더 확장 성이 좋으므로 지금 공식 구현 권장 사항이 될 것입니다. 그냥 사용하는 Intent
메시지의 필터로의 조치를. 새로 만든 ACTION_BACK_PRESSED
을 보내고 활동에서 보내고 관련 조각에서 듣습니다.
LocalBroadcastManager
주문 된 방송 을 할 수 없습니다
그 중 어느 것도 구현하기 쉽지 않으며 최적의 방식으로 작동하지 않습니다.
프래그먼트에는 작업을 수행 할 메소드 호출 onDetach가 있습니다.
@Override
public void onDetach() {
super.onDetach();
PUT YOUR CODE HERE
}
이 작업을 수행합니다.
androidx.appcompat:appcompat:1.1.0
이상을 사용하는 경우 OnBackPressedCallback
다음과 같이 조각에을 추가 할 수 있습니다
requireActivity()
.onBackPressedDispatcher
.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
Log.d(TAG, "Fragment back pressed invoked")
// Do custom work here
// if you want onBackPressed() to be called as normal afterwards
if (isEnabled) {
isEnabled = false
requireActivity().onBackPressed()
}
}
}
)
참조 https://developer.android.com/guide/navigation/navigation-custom-back를
androidx-core-ktx
수 있습니다.requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { /* code to be executed when back is pressed */ }
LifecycleOwner
PARAM이 예에서와 같이 추가해야합니다. 그것없이, handleBackPressed()
뒤로 버튼을 누르면 이후에 시작된 조각이 호출 됩니다.
addToBackStack
아래처럼 조각 사이를 전환하는 동안 추가 하십시오.
fragmentManager.beginTransaction().replace(R.id.content_frame,fragment).addToBackStack("tag").commit();
쓰면 addToBackStack(null)
자체적으로 처리하지만 태그를 제공하면 수동으로 처리해야합니다.
이 질문과 일부 답변이 5 년이 넘었으므로 솔루션을 공유하겠습니다. 이것은 @oyenigun의 답변에 대한 후속 및 현대화입니다.
최신 정보: 이 기사의 맨 아래에는 Activity가 전혀 포함되지 않는 추상 Fragment 확장을 사용하여 대체 구현을 추가했습니다.이 기능은 다른 백 동작이 필요한 중첩 된 조각과 관련된 더 복잡한 조각 계층 구조를 가진 사람에게 유용합니다.
내가 사용하는 일부 프래그먼트가 작은 정보 뷰와 같이 뒤로 버튼으로 닫고 싶은 더 작은 뷰를 가지고 있기 때문에 이것을 구현해야했지만, 이는 동작을 재정의 해야하는 모든 사람에게 좋습니다 조각 내부의 뒤로 버튼.
먼저 인터페이스를 정의하십시오
public interface Backable {
boolean onBackPressed();
}
내가 부르는이 인터페이스 Backable
(명명 규칙의 stickler) onBackPressed()
는 boolean
값을 반환 해야하는 단일 메소드 를 가지고 있습니다. 뒤로 버튼 누름이 뒤로 이벤트를 "흡수"했는지 알아야하기 때문에 부울 값을 적용해야합니다. 리턴 true
은 추가 조치가 필요하지 않음을 의미하며, 그렇지 않으면 false
기본 뒤로 조치가 여전히 수행되어야한다고 말합니다. 이 인터페이스는 자체 파일 (바람직하게는 별도의 패키지 interfaces
) 이어야합니다 . 클래스를 패키지로 분리하는 것이 좋습니다.
둘째, 최고의 조각을 찾으십시오
Fragment
백 스택에서 마지막 객체 를 반환하는 메서드를 만들었습니다 . 태그를 사용합니다 ... ID를 사용하는 경우 필요한 사항을 변경하십시오. 탐색 상태 등을 처리하는 유틸리티 클래스 에이 정적 메소드가 있지만 물론 가장 적합한 위치에 배치하십시오. 교화를 위해이라는 클래스에 내 것을 넣었습니다 NavUtils
.
public static Fragment getCurrentFragment(Activity activity) {
FragmentManager fragmentManager = activity.getFragmentManager();
if (fragmentManager.getBackStackEntryCount() > 0) {
String lastFragmentName = fragmentManager.getBackStackEntryAt(
fragmentManager.getBackStackEntryCount() - 1).getName();
return fragmentManager.findFragmentByTag(lastFragmentName);
}
return null;
}
백 스택 수가 0보다 큰지 확인하십시오. 그렇지 않으면 ArrayOutOfBoundsException
런타임에 가 발생할 수 있습니다. 0보다 크지 않으면 null을 반환합니다. 나중에 null 값을 확인합니다 ...
셋째, 조각으로 구현
구현 Backable
뒤로 단추 동작을 대체해야하는 조각이있는 인터페이스를 . 구현 방법을 추가하십시오.
public class SomeFragment extends Fragment implements
FragmentManager.OnBackStackChangedListener, Backable {
...
@Override
public boolean onBackPressed() {
// Logic here...
if (backButtonShouldNotGoBack) {
whateverMethodYouNeed();
return true;
}
return false;
}
}
에서 onBackPressed()
재정의, 당신이 필요로하는 어떤 논리했습니다. 뒤로 버튼으로 백 스택 이 나오지 않게 하려면 (기본 동작) true를 백 이벤트가 흡수되었음을 하십시오. 그렇지 않으면 false를 반환하십시오.
마지막으로, 활동에서 ...
onBackPressed()
메소드를 대체 하고이 로직을 추가하십시오.
@Override
public void onBackPressed() {
// Get the current fragment using the method from the second step above...
Fragment currentFragment = NavUtils.getCurrentFragment(this);
// Determine whether or not this fragment implements Backable
// Do a null check just to be safe
if (currentFragment != null && currentFragment instanceof Backable) {
if (((Backable) currentFragment).onBackPressed()) {
// If the onBackPressed override in your fragment
// did absorb the back event (returned true), return
return;
} else {
// Otherwise, call the super method for the default behavior
super.onBackPressed();
}
}
// Any other logic needed...
// call super method to be sure the back button does its thing...
super.onBackPressed();
}
백 스택에서 현재 조각을 얻은 다음 null 검사를 수행하여 Backable
인터페이스를 구현하는지 확인합니다 . 그렇다면 이벤트가 흡수되었는지 판별하십시오. 그렇다면 우리는 끝났습니다onBackPressed()
돌아올 수 있습니다. 그렇지 않은 경우에는 일반 백 프레스로 처리하고 super 메소드를 호출하십시오.
활동을 포함하지 않는 두 번째 옵션
때때로, 당신은 Activity가 이것을 처리하기를 원하지 않으며, 조각 내에서 직접 처리해야합니다. 그러나 누가 당신이 할 수 없다고 백 프레스 API로 프래그먼트를 가질 합니까? 조각을 새 클래스로 확장하십시오.
Fragment를 확장하고 View.OnKeyListner
인터페이스를 구현하는 추상 클래스를 작성하십시오 .
import android.app.Fragment;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
public abstract class BackableFragment extends Fragment implements View.OnKeyListener {
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.setFocusableInTouchMode(true);
view.requestFocus();
view.setOnKeyListener(this);
}
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
onBackButtonPressed();
return true;
}
}
return false;
}
public abstract void onBackButtonPressed();
}
보시다시피, 확장되는 조각 BackableFragment
은 View.OnKeyListener
인터페이스를 사용하여 클릭을 자동으로 캡처합니다 . 표준 논리를 사용하여 onBackButtonPressed()
구현 된 onKey()
메소드 내 에서 추상 메소드를 호출하여 뒤로 버튼 누름을 식별하십시오. 뒤로 버튼 이외의 키 클릭을 등록 해야하는 경우 조각에서 super
재정의 할 때 메소드 를 호출해야합니다 onKey()
. 그렇지 않으면 추상화의 동작을 재정의 합니다.
사용하기 쉽고 확장하고 구현하십시오.
public class FragmentChannels extends BackableFragment {
...
@Override
public void onBackButtonPressed() {
if (doTheThingRequiringBackButtonOverride) {
// do the thing
} else {
getActivity().onBackPressed();
}
}
...
}
onBackButtonPressed()
수퍼 클래스 의 메소드는 추상적이므로 일단 확장하면 구현해야합니다 onBackButtonPressed()
. void
프래그먼트 클래스 내에서 작업을 수행하기 만하면되므로 반환 되며 흡수를 다시 액티비티로 전달할 필요가 없습니다. 뒤로 버튼으로 수행하는 작업에 처리가 필요하지 않은 경우 Activity 메서드를 호출 해야 합니다 onBackPressed()
. 그렇지 않으면 뒤로 버튼이 비활성화되고 원하지 않습니다!
주의 사항 보시다시피, 이것은 키 리스너를 프래그먼트의 루트 뷰로 설정하므로 집중해야합니다. 이 클래스를 확장하는 프래그먼트에 포함 된 편집 텍스트 (또는 다른 포커스 스틸 링보기)가 있거나 다른 내부 프래그먼트 또는보기가있는 경우이를 별도로 처리해야합니다. EditText 확장에 대한 좋은 기사가 있습니다.백 프레스에 초점을 잃기 를 .
누군가가 이것을 유용하게 사용하기를 바랍니다. 행복한 코딩.
super.onBackPressed();
두 번 전화 합니까?
currentFragment
됩니다. 프래그먼트가 널이 아니고 프래그먼트가 Backable
인터페이스를 구현하면 조치가 수행되지 않습니다. 프래그먼트가 null이 아니고 구현하지 않으면 Backable
super 메소드를 호출합니다. 프래그먼트가 null이면 마지막 슈퍼 호출로 건너 뜁니다.
currentFragment
가 null이 아니고 Backable의 인스턴스 인 경우 분리 된 경우 ( back
버튼 을 누르고 조각을 닫음)의 첫 번째 발생을 super.onBackPressed();
호출 한 다음 두 번째 발생을 호출합니다.
해결책은 간단합니다.
1) 모든 조각이 확장되는 기본 조각 클래스가있는 경우이 코드를 해당 클래스에 추가하십시오. 그렇지 않으면 기본 조각 클래스를 작성하십시오
/*
* called when on back pressed to the current fragment that is returned
*/
public void onBackPressed()
{
// add code in super class when override
}
2) 활동 클래스에서 다음과 같이 onBackPressed를 대체하십시오.
private BaseFragment _currentFragment;
@Override
public void onBackPressed()
{
super.onBackPressed();
_currentFragment.onBackPressed();
}
3) Fragment 클래스에서 원하는 코드를 추가하십시오.
@Override
public void onBackPressed()
{
setUpTitle();
}
onBackPressed()
조각이 활동에서 분리됩니다.
@Sterling Diaz의 답변에 따르면 나는 그가 옳다고 생각합니다. 그러나 어떤 상황은 잘못 될 것입니다. (예 : 화면 회전)
isRemoving()
목표 달성 여부 를 감지 할 수 있다고 생각합니다 .
onDetach()
또는에 쓸 수 있습니다 onDestroyView()
. 일입니다.
@Override
public void onDetach() {
super.onDetach();
if(isRemoving()){
// onBackPressed()
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
if(isRemoving()){
// onBackPressed()
}
}
글쎄, 나는 이것을 이렇게했고, 그것은 나를 위해 일한다.
간단한 인터페이스
FragmentOnBackClickInterface.java
public interface FragmentOnBackClickInterface {
void onClick();
}
구현 예
MyFragment.java
public class MyFragment extends Fragment implements FragmentOnBackClickInterface {
// other stuff
public void onClick() {
// what you want to call onBackPressed?
}
그런 다음 활동에서 onBackPressed를 재정의하십시오.
@Override
public void onBackPressed() {
int count = getSupportFragmentManager().getBackStackEntryCount();
List<Fragment> frags = getSupportFragmentManager().getFragments();
Fragment lastFrag = getLastNotNull(frags);
//nothing else in back stack || nothing in back stack is instance of our interface
if (count == 0 || !(lastFrag instanceof FragmentOnBackClickInterface)) {
super.onBackPressed();
} else {
((FragmentOnBackClickInterface) lastFrag).onClick();
}
}
private Fragment getLastNotNull(List<Fragment> list){
for (int i= list.size()-1;i>=0;i--){
Fragment frag = list.get(i);
if (frag != null){
return frag;
}
}
return null;
}
아래와 같이 프로젝트에 인터페이스를 추가해야합니다.
public interface OnBackPressed {
void onBackPressed();
}
그런 다음 조각에이 인터페이스를 구현해야합니다.
public class SampleFragment extends Fragment implements OnBackPressed {
@Override
public void onBackPressed() {
//on Back Pressed
}
}
그리고 당신은 당신의 활동 onBackPressed 이벤트 아래 에서이 onBackPressed 이벤트를 트리거 할 수 있습니다;
public class MainActivity extends AppCompatActivity {
@Override
public void onBackPressed() {
Fragment currentFragment = getSupportFragmentManager().getFragments().get(getSupportFragmentManager().getBackStackEntryCount() - 1);
if (currentFragment instanceof OnBackPressed) {
((OnBackPressed) currentFragment).onBackPressed();
}
super.onBackPressed();
}
}
getActivity().onBackPressed();
. "java.lang.StackOverflowError : stack size 8MB"예외를 호출하므로 호출하지 마십시오 .
이것은 트릭을 수행하는 작은 코드 일뿐입니다.
getActivity().onBackPressed();
그것이 누군가를 돕기를 바랍니다 :)
EventBus를 사용하는 경우 훨씬 간단한 솔루션 일 것입니다.
조각에서 :
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
EventBus.getDefault().register(this);
}
@Override
public void onDetach() {
super.onDetach();
EventBus.getDefault().unregister(this);
}
// This method will be called when a MessageEvent is posted
public void onEvent(BackPressedMessage type){
getSupportFragmentManager().popBackStack();
}
활동 클래스에서 다음을 정의 할 수 있습니다.
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
// This method will be called when a MessageEvent is posted
public void onEvent(BackPressedMessage type){
super.onBackPressed();
}
@Override
public void onBackPressed() {
EventBus.getDefault().post(new BackPressedMessage(true));
}
BackPressedMessage.java는 POJO 객체 일뿐입니다.
이것은 매우 깨끗하며 인터페이스 / 구현 번거 로움이 없습니다.
이것은 내 솔루션입니다.
에 MyActivity.java :
public interface OnBackClickListener {
boolean onBackClick();
}
private OnBackClickListener onBackClickListener;
public void setOnBackClickListener(OnBackClickListener onBackClickListener) {
this.onBackClickListener = onBackClickListener;
}
@Override
public void onBackPressed() {
if (onBackClickListener != null && onBackClickListener.onBackClick()) {
return;
}
super.onBackPressed();
}
그리고 단편에서 :
((MyActivity) getActivity()).setOnBackClickListener(new MyActivity.OnBackClickListener() {
@Override
public boolean onBackClick() {
if (condition) {
return false;
}
// some codes
return true;
}
});
Navigation 구성 요소 를 사용하면 다음 과 같이 할 수 있습니다 .
자바
public class MyFragment extends Fragment {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// This callback will only be called when MyFragment is at least Started.
OnBackPressedCallback callback = new OnBackPressedCallback(true /* enabled by default */) {
@Override
public void handleOnBackPressed() {
// Handle the back button event
}
});
requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
// The callback can be enabled or disabled here or in handleOnBackPressed()
}
...
}
코 틀린
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
}
...
}
@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
replaceFragmentToBackStack(getActivity(), WelcomeFragment.newInstance(bundle), tags);
return true;
}
return false;
}
});
}
public class MyActivity extends Activity {
protected OnBackPressedListener onBackPressedListener;
public interface OnBackPressedListener {
void doBack();
}
public void setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
this.onBackPressedListener = onBackPressedListener;
}
@Override
public void onBackPressed() {
if (onBackPressedListener != null)
onBackPressedListener.doBack();
else
super.onBackPressed();
}
@Override
protected void onDestroy() {
onBackPressedListener = null;
super.onDestroy();
}
}
조각에 다음을 추가하고 mainactivity의 인터페이스를 구현하는 것을 잊지 마십시오.
public class MyFragment extends Framgent implements MyActivity.OnBackPressedListener {
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
((MyActivity) getActivity()).setOnBackPressedListener(this);
}
@Override
public void doBack() {
//BackPressed in activity will call this;
}
}
내 솔루션에서 (Kotlin);
나는에 매개 변수로 onBackAlternative 기능을 사용하고 BaseActivity .
BaseActivity
abstract class BaseActivity {
var onBackPressAlternative: (() -> Unit)? = null
override fun onBackPressed() {
if (onBackPressAlternative != null) {
onBackPressAlternative!!()
} else {
super.onBackPressed()
}
}
}
BaseFragment 에 onBackPressAlternative 를 설정하는 기능이 있습니다.
BaseFragment
abstract class BaseFragment {
override fun onStart() {
super.onStart()
...
setOnBackPressed(null) // Add this
}
//Method must be declared as open, for overriding in child class
open fun setOnBackPressed(onBackAlternative: (() -> Unit)?) {
(activity as BaseActivity<*, *>).onBackPressAlternative = onBackAlternative
}
}
그런 다음 onBackPressAlternative를 조각에 사용할 준비가되었습니다.
하위 조각
override fun setOnBackPressed(onBackAlternative: (() -> Unit)?) {
(activity as BaseActivity<*, *>).onBackPressAlternative = {
// TODO Your own custom onback function
}
}
뒤로 버튼을 눌렀을 때 활동이 완료되도록 ft.addToBackStack () 메소드를 구현하지 마십시오.
proAddAccount = new ProfileAddAccount();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, proAddAccount);
//fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
다음 단계를 따르십시오.
조각을 추가하는 동안 항상
fragmentTransaction.add(R.id.fragment_container, detail_fragment, "Fragment_tag").addToBackStack(null).commit();
그런 다음 주요 활동에서 재정의 onBackPressed()
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
} else {
finish();
}
앱에서 뒤로 버튼을 처리하려면
Fragment f = getActivity().getSupportFragmentManager().findFragmentByTag("Fragment_tag");
if (f instanceof FragmentName) {
if (f != null)
getActivity().getSupportFragmentManager().beginTransaction().remove(f).commit()
}
그게 다야!
활동 수명주기에서 FragmentActivity 또는 AppCompatActivity를 사용하면 항상 Android 뒤로 버튼이 FragmentManager 트랜잭션을 처리합니다.
백 스택을 처리하기 위해 백 스택 수 또는 태그를 처리 할 필요는 없지만 조각을 추가하거나 교체하는 동안 초점을 유지해야합니다. 뒤로 버튼 케이스를 처리하기 위해 다음 스 니펫을 찾으십시오.
public void replaceFragment(Fragment fragment) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (!(fragment instanceof HomeFragment)) {
transaction.addToBackStack(null);
}
transaction.replace(R.id.activity_menu_fragment_container, fragment).commit();
}
여기에서는 내 응용 프로그램의 홈 페이지이므로 홈 조각에 대한 스택을 다시 추가하지 않습니다. addFBackStack을 HomeFragment에 추가하면 응용 프로그램이 acitivity의 모든 frament를 제거하기 위해 대기 한 다음 빈 화면이 표시되므로 다음과 같은 조건을 유지합니다.
if (!(fragment instanceof HomeFragment)) {
transaction.addToBackStack(null);
}
이제 acitvity에서 이전에 추가 된 조각을 볼 수 있으며 HomeFragment에 도달하면 앱이 종료됩니다. 다음 스 니펫을 볼 수도 있습니다.
@Override
public void onBackPressed() {
if (mDrawerLayout.isDrawerOpen(Gravity.LEFT)) {
closeDrawer();
} else {
super.onBackPressed();
}
}
조각 : 메소드를 배치하는 BaseFragment를 작성하십시오.
public boolean onBackPressed();
활동:
@Override
public void onBackPressed() {
List<Fragment> fragments = getSupportFragmentManager().getFragments();
if (fragments != null) {
for (Fragment fragment : fragments) {
if (!fragment.isVisible()) continue;
if (fragment instanceof BaseFragment && ((BaseFragment) fragment).onBackPressed()) {
return;
}
}
}
super.onBackPressed();
}
액티비티는 첨부되고 보이는 조각을 실행하고 각 조각에서 onBackPressed () 를 호출하고 그중 하나가 'true'를 반환하면 중단됩니다 (처리되었으므로 더 이상의 작업이 없음).
에 따르면 AndroidX 릴리스 노트 , androidx.activity 1.0.0-alpha01
출시 및 출시되고 ComponentActivity
, 기존의 새로운 기본 클래스 FragmentActivity
와 AppCompatActivity
. 이 릴리스에는 새로운 기능이 있습니다.
이제 활동의 메소드를 재정의하지 않고도 OnBackPressedCallback
비아 addOnBackPressedCallback
를 등록하여 onBackPressed()
콜백 을 수신 할 수 있습니다.
역행을 처리하기 위해 활동에 단편을 등록 할 수 있습니다.
interface BackPressRegistrar {
fun registerHandler(handler: BackPressHandler)
fun unregisterHandler(handler: BackPressHandler)
}
interface BackPressHandler {
fun onBackPressed(): Boolean
}
용법:
private val backPressHandler = object : BackPressHandler {
override fun onBackPressed(): Boolean {
showClosingWarning()
return false
}
}
override fun onResume() {
super.onResume()
(activity as? BackPressRegistrar)?.registerHandler(backPressHandler)
}
override fun onStop() {
(activity as? BackPressRegistrar)?.unregisterHandler(backPressHandler)
super.onStop()
}
class MainActivity : AppCompatActivity(), BackPressRegistrar {
private var registeredHandler: BackPressHandler? = null
override fun registerHandler(handler: BackPressHandler) { registeredHandler = handler }
override fun unregisterHandler(handler: BackPressHandler) { registeredHandler = null }
override fun onBackPressed() {
if (registeredHandler?.onBackPressed() != false) super.onBackPressed()
}
}
조각 내에서 콜백을 사용하면 onBackPressed를 처리하여 커스텀 백 네비게이션을 제공하는 것이 더 쉬워졌습니다.
class MyFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
if (true == conditionForCustomAction) {
myCustomActionHere()
} else NavHostFragment.findNavController(this@MyFragment).navigateUp();
}
}
requireActivity().onBackPressedDispatcher.addCallback(
this, onBackPressedCallback
)
...
}
어떤 조건에 따라 기본 뒤로 동작을 원하면 다음을 사용할 수 있습니다.
NavHostFragment.findNavController(this@MyFragment).navigateUp();
프래그먼트의 onCreate 메소드 안에 다음을 추가하십시오.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OnBackPressedCallback callback = new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
//Handle the back pressed
}
};
requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
}
최고의 솔루션
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
public class BaseActivity extends AppCompatActivity {
@Override
public void onBackPressed() {
FragmentManager fm = getSupportFragmentManager();
for (Fragment frag : fm.getFragments()) {
if (frag == null) {
super.onBackPressed();
finish();
return;
}
if (frag.isVisible()) {
FragmentManager childFm = frag.getChildFragmentManager();
if (childFm.getFragments() == null) {
super.onBackPressed();
finish();
return;
}
if (childFm.getBackStackEntryCount() > 0) {
childFm.popBackStack();
return;
}
else {
fm.popBackStack();
if (fm.getFragments().size() <= 1) {
finish();
}
return;
}
}
}
}
}