有没有一种方法可以onBackPressed()在Android Fragment中实现类似于我们在Android Activity中实现的方式?
正如Fragment生命周期所没有的那样onBackPressed().有没有其他替代方法来覆盖onBackPressed()Android 3.0碎片?
我遇到一个奇怪的问题,同时使用Fragments并弹出它们.
我有一个片段活动:
Step1:我在起始命名片段A中的那个Activity的onCreate中附加了一个片段:
这是片段活动的onCreate
@Override
protected void onCreate(Bundle savedBundleState) {
super.onCreate(savedBundleState);
setContentView(R.layout.activity_base_new);
Fragement_Home home = new Fragement_Home();
FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction().add(R.id.frameContent, home).addToBackStack("home").commit();
}
Run Code Online (Sandbox Code Playgroud)
步骤:2之后,我附上了以下代码替换了Fragment:
Fragment_More moreFragment = new Fragment_More();
FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction().replace(R.id.frameContent, moreFragment).addToBackStack("more").commit();
Run Code Online (Sandbox Code Playgroud)
第3步:在那之后我再次以相同的方式在Fragment_More上添加了一个片段:
Fragment_AboutRockstand termsConditions = new Fragment_AboutRockstand();
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.frameContent, termsConditions).addToBackStack("about_rockstand").commit();
Run Code Online (Sandbox Code Playgroud)
这是我的片段活动onBackPressedButton Lisetener:
@Override
public void onBackPressed() {
FragmentManager fm = getSupportFragmentManager();
Fragment f = fm.findFragmentById(R.id.frameContent);
if(fm.getBackStackEntryCount() > 1){
fm.popBackStack();
} else{
finish();
}
}
Run Code Online (Sandbox Code Playgroud)
这是我得到的问题:
当我从第3步按回来时,它按照onBackPressed的描述成功地给了我之前的片段,它会回弹并将我带到前面的片段.但是从Fragment_More开始,当我再次按下时,它会显示空白的FRAGMENT内容.它从未显示我在活动的OnCreate中的第1步中添加的First Fragment.
请评论.我做错了什么?
谢谢
使用时AutoCompleteTextView,会出现下拉建议列表,软件键盘仍然可见.这是有道理的,因为输入随后的字符以缩小列表通常会更有效.
但是,如果用户想要浏览建议列表,则软件键盘仍处于运转状态时变得非常繁琐(当设备处于横向时,这更是一个问题).如果没有键盘占用屏幕空间,导航列表会容易得多.不幸的是,当您按下后退键时,默认行为会首先删除列表(即使在后退键的软件版本中,它显示的图像显示"按此键将隐藏键盘").
这是一个准系统示例,演示了我在说什么:
public class Main2 extends Activity {
private static final String[] items = {
"One",
"Two",
"Three",
"Four",
"Five"
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AutoCompleteTextView actv = new AutoCompleteTextView(this);
actv.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
actv.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, items));
actv.setThreshold(1);
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
ll.addView(actv);
setContentView(ll);
}
}
Run Code Online (Sandbox Code Playgroud)
除了这是不直观的事实(后面的键提示暗示背压将被发送到键盘),它使得导航AutoCompleteTextView建议非常无聊.
什么是最不具侵入性的方式(例如,onBackPressed()在每个活动中捕获后面并相应地路由它肯定不是理想的)使第一次按下后隐藏键盘,第二次删除建议列表?
keyboard android autocompletetextview android-softkeyboard onbackpressed
我在用户按下退出应用程序时显示插页式广告:
mInterstitialAd.setAdListener(new AdListener() {
@Override
public void onAdClosed() {
onBackPressed(); //line 98
}
});
requestNewInterstitial();
private void requestNewInterstitial() {
AdRequest adRequest = new AdRequest.Builder().build();
mInterstitialAd.loadAd(adRequest);
}
@Override
public void onBackPressed() {
if (mInterstitialAd.isLoaded()) {
mInterstitialAd.show();
} else {
super.onBackPressed(); //line 410
}
}
Run Code Online (Sandbox Code Playgroud)
这是我从用户那里收到的崩溃报告:
java.lang.RuntimeException: Unable to pause activity {com.myapp/com.google.android.gms.ads.AdActivity}: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3088)
at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3043)
at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:3021)
at android.app.ActivityThread.access$1000(ActivityThread.java:138)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1253)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:149)
at android.app.ActivityThread.main(ActivityThread.java:5045)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at …Run Code Online (Sandbox Code Playgroud) 由于从 Android 33 开始旧版本Activity.onBackPressed()已被弃用,那么以编程方式调用它的更好方法是什么?
例子:
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
// Handle default back arrow click
android.R.id.home -> {
onBackPressed()
}
...
Run Code Online (Sandbox Code Playgroud)
我们可以创建并添加这样的OnBackPressedCallback内容onBackPressedDispatcher。
onBackPressedDispatcher.addCallback(
this, // Lifecycle owner
backPressedCallback
)
private val backPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
if (viewPager.currentItem != 0)
viewPager.setCurrentItem(0, true)
else
finish()
}
}
Run Code Online (Sandbox Code Playgroud)
然后将旧的替换onBackPressed为
// Handle default back arrow click
android.R.id.home -> {
backPressedCallback.handleOnBackPressed()
}
Run Code Online (Sandbox Code Playgroud)
但我看到了这个公共方法onBackPressedDispatcher,想知道是否可以用它来代替。
onBackPressedDispatcher.onBackPressed() …Run Code Online (Sandbox Code Playgroud) android onbackpressed android-jetpack android-jetpack-navigation android-tiramisu
什么是在按下后处理导航抽屉的选定状态的正确方法?
我有一个带有n个条目的导航抽屉(在列表视图中),就像Android Studio中的SDK示例一样.当我点击导航抽屉条目时,我希望它们被添加到后台堆栈,所以我可以回到它们.
在onNavigationDrawerItemSelected(int pos)我有
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
if (position == 0) {
transaction.replace(R.id.container, new FragmentA());
} else if (position == 1) {
transaction.replace(R.id.container, new FragmentB());
} else {
transaction.replace(R.id.container, new FragmentC());
}
transaction.addToBackStack(null);
transaction.commit();
Run Code Online (Sandbox Code Playgroud)
当我点击抽屉中的第二个条目时,B被选中并替换A.如果我之后单击后退按钮,片段A将再次显示,但仍然在导航抽屉中选择了B.
如何在按下后更新抽屉的选择状态?
不知怎的,我需要调用mDrawerListView.setItemChecked(position,true); 或NavigationDrawerFragment.selectItem(int position).但到了哪个位置?我怎么记得呢?
拦截onBackPressed?
@Override
public void onBackPressed() {}
Run Code Online (Sandbox Code Playgroud)
但我怎么知道哪个片段再次活跃?它对应于哪个位置.
有一些简单的解决方案我是盲目的看到的吗?似乎与导航抽屉结合使用并更新选择状态是标准模式.
navigation android android-fragments navigation-drawer onbackpressed
对于共享元素转换,我遵循这个 github项目.它有2个屏幕 - 一个带有recyclerview,有多个卡片,第二个是细节屏幕.正如预期的那样,它展示了imageview&textview从recyclerview项目到详细屏幕和背面反向过渡的共享元素转换.
但是,如果用户在详细信息屏幕上更改方向,然后按下后退按钮,则反向过渡动画不起作用.看着这个 2:49之间的视频的帧2:57,似乎连方向更改后成为可能.有什么想法吗?
编辑:
请查看此视频以便更好地理解.
android material-design onbackpressed shared-element-transition android-recyclerview
在我的活动中,操作栏仅显示左箭头和活动标题.
当我按下向左箭头时,活动返回到上一个活动,但在onKeyUp,OnkeyDown和OnBackPressed方法中没有注册任何事件.
但是当我按下手机上的Back键(在底部)时,活动将返回到前一个,并且onKeyUp,OnKeyDown和OnBackPressed上的所有方法都会注册一个事件(在logcat中).
如何捕获左箭头(我认为它被称为UP按钮)?
我需要捕获密钥的原因是在onPause方法中知道活动是由用户而不是系统销毁的(例如,如果用户切换到另一个活动).
通过进一步研究他的问题,我发现UP按钮给出了一个由onOptionsItemSelected方法捕获的事件,因为菜单上没有其他按钮,我知道它就是这个按钮.
我想在活动的(Java)片段(Kotlin)之一中处理用户的后按操作。
在活动的 onCreate 方法中我调用
OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(true) {
(...) handling back press when there's other BackPressedDispatcherCallbacks registered (...)
}
getOnBackPressedDispatcher().addCallback(this, onBackPressedCallback);
Run Code Online (Sandbox Code Playgroud)
然后在我想要处理后按的片段的 onCreateView() 中,我调用
activity?.onBackPressedDispatcher?.addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
(...) handling back press here, not in activity (...)
}})
Run Code Online (Sandbox Code Playgroud)
一切都按预期工作,直到我将应用程序置于后台然后返回前台,导致 Activity 和 Fragment 的 OnStop -> OnStart 被调用。
在这种情况下,应用程序会忽略 Fragment 回调,并且会调用 Activity 的回调。
我发现的是
onBackPressedDispatcher 以与添加回调相反的顺序调用回调。仅当最近添加的回调未启用时,才会调用之前添加的回调(仅调用最后启用的回调)
将观察者添加到 Activity 和 Fragment 生命周期并记录结果打印:
FRAG:ON_START ACT:ON_START FRAG:ON_RESUME ACT:ON_RESUME
OnStart 和 OnResume 上的 Activity 在 Fragments 等效项之后调用,这有效地使 Activity …
android ×10
onbackpressed ×10
back ×1
back-stack ×1
button ×1
java ×1
keyboard ×1
kotlin ×1
navigation ×1
onkeydown ×1
onkeyup ×1