是否有一种方法,我们可以实现onBackPressed()在Android片段类似的方式,我们实现在Android活动?
因为Fragment的生命周期没有onBackPressed()。在android3.0片段中是否有其他替代方法来覆盖onBackPressed() ?
是否有一种方法,我们可以实现onBackPressed()在Android片段类似的方式,我们实现在Android活动?
因为Fragment的生命周期没有onBackPressed()。在android3.0片段中是否有其他替代方法来覆盖onBackPressed() ?
当前回答
在mainActivity实现回调接口中
protected mainActivity.OnBackPressedListener onBackPressedListener;
public interface OnBackPressedListener {
void doBack();
}
public void setOnBackPressedListener(mainActivity.OnBackPressedListener onBackPressedListener) {
this.onBackPressedListener = onBackPressedListener;
}
@Override
public void onBackPressed() {
if (onBackPressedListener != null) {
onBackPressedListener.doBack();
} else {
super.onBackPressed();
}
}
在片段实现接口OnBackPressedListener,我们写在mainActivity
implements mainActivity.OnBackPressedListener
mainActivity是我的基本活动,在你的片段onCreateView方法中编写以下代码
((mainActivity) getActivity()).setOnBackPressedListener(this);
并实现OnBackPressedListener接口方法doBack
@Override
public void doBack() {
//call base fragment
}
现在使用doBack()方法调用你想要调用的fragment
其他回答
在kotlin的情况下使用这个onAttach回调
override fun onAttach(context: Context) {
super.onAttach(context)
val callback: OnBackPressedCallback = object :
OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
// your onbackpressed code
}
}
requireActivity().onBackPressedDispatcher.addCallback(this, callback)
}
如果你想要那种功能,你需要在你的活动中覆盖它,然后给你所有的片段添加一个YourBackPressed接口,当你按下后退按钮时,你就会在相关的片段上调用这个接口。
编辑:我想补充我之前的答案。
如果我今天要这样做,我将使用广播,或者如果我希望其他面板同步更新到主/主内容面板,则可能使用有序广播。
支持库中的LocalBroadcastManager可以帮助解决这个问题,你只需要在onBackPressed中发送广播,并在你的片段中订阅。我认为Messaging是一种更加解耦的实现,可伸缩性更好,所以它是我现在的官方实现建议。只要使用Intent的动作作为你信息的过滤器。发送你新创建的ACTION_BACK_PRESSED,从你的活动发送它,并在相关片段中监听它。
你应该添加接口到你的项目如下;
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();
}
}
根据@ hammer的回答,这里是伪代码,它应该如何工作。 假设你的主活动名为BaseActivity,它有子片段(就像SlidingMenu库的例子一样)。 以下是步骤:
首先,我们需要创建接口和类,实现它的接口具有泛型方法
Create class interface OnBackPressedListener public interface OnBackPressedListener { public void doBack(); } Create class which implements skills of 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); } } Since now, we will work on our code BaseActivity and its fragments Create private listener on top of your class BaseActivity protected OnBackPressedListener onBackPressedListener; create method to set listener in BaseActivity public void setOnBackPressedListener(OnBackPressedListener onBackPressedListener) { this.onBackPressedListener = onBackPressedListener; } in override onBackPressed implement something like that @Override public void onBackPressed() { if (onBackPressedListener != null) onBackPressedListener.doBack(); else super.onBackPressed(); in your fragment in onCreateView you should add our listener @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; }
瞧,现在当你在片段中单击返回时,你应该捕获你的自定义on back方法。
既然这个问题和一些答案已经超过5年了,让我分享一下我的解决方案。这是@oyenigun的回答的后续和现代化
更新: 在本文的底部,我添加了一个使用抽象Fragment扩展的替代实现,它根本不涉及Activity,这对于任何具有更复杂的片段层次结构(涉及需要不同返回行为的嵌套片段)的人来说都是有用的。
我需要实现这一点,因为我使用的一些片段具有较小的视图,我希望通过返回按钮来消除这些视图,例如弹出的小信息视图,等等,但这对于需要覆盖片段内返回按钮行为的任何人都是有益的。
首先,定义一个接口
public interface Backable {
boolean onBackPressed();
}
This interface, which I call Backable (I'm a stickler for naming conventions), has a single method onBackPressed() that must return a boolean value. We need to enforce a boolean value because we will need to know if the back button press has "absorbed" the back event. Returning true means that it has, and no further action is needed, otherwise, false says that the default back action still must take place. This interface should be it's own file (preferably in a separate package named interfaces). Remember, separating your classes into packages is good practice.
其次,找到顶部的片段
我创建了一个方法,返回后面堆栈中的最后一个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。稍后我们将检查空值…
第三,在一个片段中实现
在需要覆盖后退按钮行为的片段中实现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();
}
我们在back堆栈中获取当前片段,然后进行空检查并确定它是否实现了Backable接口。如果是,确定事件是否被吸收。如果是这样,我们就完成了onBackPressed()并可以返回。否则,将其视为普通的背压并调用super方法。
第二种选择是不参与活动
有时,您根本不希望Activity处理它,而需要直接在片段中处理它。但是谁说Fragments不能带有背压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的片段都会使用视图自动捕获回点击。OnKeyListener接口。只需在实现的onKey()方法中调用抽象的onBackButtonPressed()方法,使用标准逻辑来识别后退按钮的按下。如果你需要注册按键点击而不是返回按钮,只要确保在你的片段中覆盖onKey()时调用super方法,否则你将覆盖抽象中的行为。
使用简单,只需扩展和实现:
public class FragmentChannels extends BackableFragment {
...
@Override
public void onBackButtonPressed() {
if (doTheThingRequiringBackButtonOverride) {
// do the thing
} else {
getActivity().onBackPressed();
}
}
...
}
由于超类中的onBackButtonPressed()方法是抽象的,一旦扩展,就必须实现onBackButtonPressed()。它返回void,因为它只需要在fragment类中执行一个动作,而不需要将压力的吸收传递回Activity。如果你对后退按钮所做的事情不需要处理,请确保你调用Activity onBackPressed()方法,否则,后退按钮将被禁用…你不会想要这样的!
警告 如您所见,这将关键侦听器设置为片段的根视图,我们需要集中它。如果在扩展该类的片段(或具有相同内容的其他内部片段或视图)中涉及到编辑文本(或任何其他焦点窃取视图),则需要单独处理。有一篇很好的文章介绍了如何扩展EditText以使其失去对背压的关注。
我希望有人觉得这有用。快乐的编码。