Android 在按下后退按钮的片段中,活动为空白
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20340303/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In Fragment on back button pressed Activity is blank
提问by Filip Luchianenco
I have an Activity and many fragments inflated in same FrameLayout
我有一个 Activity 和许多碎片在同一个膨胀 FrameLayout
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
example: mainActivity > any fragment (press back button) > activity is blank.
示例:mainActivity > 任何片段(按后退按钮)> 活动为空白。
In onCreate:
在 onCreate 中:
layout = (FrameLayout)findViewById(R.id.content_frame);
layout.setVisibility(View.GONE);
When I start a fragment:
当我开始一个片段时:
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, profileFragment);
ft.addToBackStack(null);
ft.commit();
layout.setVisibility(View.VISIBLE);
I suppose I need to make the frameLayout's visibility GONE
again on back pressed, but how do I do this?
我想我需要GONE
在按下后再次使 frameLayout 的可见性,但我该怎么做?
I tried onBackPressed
and set layout.setVisibility(View.GONE);
but I cannot go back through fragments, as I go directly to main page.
我尝试onBackPressed
并设置layout.setVisibility(View.GONE);
但我无法返回片段,因为我直接进入主页。
回答by Sampath Kumar
If you have more than one fragment been used in the activity or even if you have only one fragment then the first fragment should not have addToBackStack defined. Since this allows back navigation and prior to this fragment the empty activity layout will be displayed.
如果您在活动中使用了多个片段,或者即使您只有一个片段,则第一个片段不应定义 addToBackStack。由于这允许返回导航并且在此片段之前将显示空的活动布局。
// fragmentTransaction.addToBackStack() // dont include this for your first fragment.
But for the other fragment you need to have this defined otherwise the back will not navigate to earlier screen (fragment) instead the application might shutdown.
但是对于另一个片段,您需要定义它,否则背面将不会导航到较早的屏幕(片段),而应用程序可能会关闭。
回答by Goodlife
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
}
else {
int fragments = getSupportFragmentManager().getBackStackEntryCount();
if (fragments == 1) {
finish();
} else if (getFragmentManager().getBackStackEntryCount() > 1) {
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
}
To add a fragment
添加片段
getSupportFragmentManager().beginTransaction()
.replace(R.id.layout_main, dashboardFragment, getString(R.string.title_dashboard))
.addToBackStack(getString(R.string.title_dashboard))
.commit();
回答by irscomp
Sorry for the late response.
回复晚了非常抱歉。
You don't have to add ft.addToBackStack(null);while adding first fragment.
您不必添加 ft.addToBackStack(null); 在添加第一个片段时。
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, profileFragment);
// ft.addToBackStack(null); --remove this line.
ft.commit();
// ... rest of code
回答by Edgar Sousa
If you want to track by the fragments you should override the onBackPressed
method, like this
如果您想通过片段进行跟踪,则应覆盖该onBackPressed
方法,如下所示
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() == 1) {
finish();
} else {
super.onBackPressed();
}
}
回答by JRomero
You can override onBackPressed
and check to see if there is anything on the backstack.
您可以覆盖onBackPressed
并检查 backstack 上是否有任何内容。
@Override
public void onBackPressed() {
int fragments = getFragmentManager().getBackStackEntryCount();
if (fragments == 1) {
// make layout invisible since last fragment will be removed
}
super.onBackPressed();
}
回答by Sileria
Just don't add the first fragment to back stack
只是不要将第一个片段添加到后堆栈
Here is the Kotlin code that worked for me.
这是对我有用的 Kotlin 代码。
val ft = supportFragmentManager.beginTransaction().replace(container, frag)
if (!supportFragmentManager.fragments.isEmpty()) ft.addToBackStack(null)
ft.commit()
回答by gMale
On a recent personal project, I solved this by not calling addToBackStack
if the stack is empty.
在最近的一个个人项目中,我通过addToBackStack
在堆栈为空时不调用来解决这个问题。
// don't add the first fragment to the backstack
// otherwise, pressing back on that fragment will result in a blank screen
if (fragmentManager.getFragments() != null) {
transaction.addToBackStack(tag);
}
Here's my full implementation:
这是我的完整实现:
String tag = String.valueOf(mCurrentSectionId);
FragmentManager fragmentManager = mActivity.getSupportFragmentManager();
Fragment fragment = fragmentManager.findFragmentByTag(tag);
if (fragment != null) {
// if the fragment exists then no need to create it, just pop back to it so
// that repeatedly toggling between fragments doesn't create a giant stack
fragmentManager.popBackStackImmediate(tag, 0);
} else {
// at this point, popping back to that fragment didn't happen
// So create a new one and then show it
fragment = createFragmentForSection(mCurrentSectionId);
FragmentTransaction transaction = fragmentManager.beginTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.replace(R.id.main_content, fragment, tag);
// don't add the first fragment to the backstack
// otherwise, pressing back on that fragment will result in a blank screen
if (fragmentManager.getFragments() != null) {
transaction.addToBackStack(tag);
}
transaction.commit();
}
回答by Filip Luchianenco
I still could not fix the issue through getBackStackEntryCount()
and I solved my issue by making the main page a fragment too, so in the end I have an activity with a FrameLayout
only; and all other fragments including the main page I inflate into that layout. This solved my issue.
我仍然无法解决问题getBackStackEntryCount()
,我也通过将主页设为片段来解决我的问题,所以最后我只有一个活动FrameLayout
;以及所有其他片段,包括我膨胀到该布局中的主页。这解决了我的问题。
回答by Jemshit Iskenderov
irscomp's solution works if you want to end activity when back button is pressed on first fragment. But if you want to track all fragments, and go back from one to another in back order, you add all fragments to stack with:
如果您想在第一个片段上按下后退按钮时结束活动,则 irscomp 的解决方案有效。但是,如果您想跟踪所有片段,并按照倒序从一个返回到另一个,则将所有片段添加到堆栈中:
ft.addToBackStack(null);
and then, add this to the end of onCreate() to avoid blank screen in last back pressed; you can use getSupportFragmentManager() or getFragmentManager() depending on your API:
然后,将此添加到 onCreate() 的末尾以避免最后一次按下时出现空白屏幕;您可以根据您的 API 使用 getSupportFragmentManager() 或 getFragmentManager() :
FragmentManager fm = getSupportFragmentManager();
fm.addOnBackStackChangedListener(new OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
if(getSupportFragmentManager().getBackStackEntryCount() == 0) finish();
}
});
Final words: I don't suggest you to use this solution, because if you go from fragment1 to fragment 2 and vice versa 10 times, when you press back button 10 times it will do it in back order which users will not want it.
最后的话:我不建议你使用这个解决方案,因为如果你从 fragment1 到 fragment 2,反之亦然 10 次,当你按后退按钮 10 次时,它会按用户不想要的顺序进行。
回答by Mehdi Dehghani
Almost same as Goodlife's answer, but in Xamarin.Android
way:
与Goodlife的回答几乎相同,但Xamarin.Android
方式不同:
Load fragment (I wrote helper method for that, but it's not necessary):
加载片段(我为此编写了辅助方法,但这不是必需的):
public void LoadFragment(Activity activity, Fragment fragment, string fragmentTitle = "")
{
var fragmentManager = activity.FragmentManager;
var fragmentTransaction = fragmentManager.BeginTransaction();
fragmentTransaction.Replace(Resource.Id.mainContainer, fragment);
fragmentTransaction.AddToBackStack(fragmentTitle);
fragmentTransaction.Commit();
}
Back button (in MainActivity
):
后退按钮(中MainActivity
):
public override void OnBackPressed()
{
if (isNavDrawerOpen()) drawerLayout.CloseDrawers();
else
{
var backStackEntryCount = FragmentManager.BackStackEntryCount;
if (backStackEntryCount == 1) Finish();
else if (backStackEntryCount > 1) FragmentManager.PopBackStack();
else base.OnBackPressed();
}
}
And isNavDrawerOpen
method:
和isNavDrawerOpen
方法:
bool isNavDrawerOpen()
{
return drawerLayout != null && drawerLayout.IsDrawerOpen(Android.Support.V4.View.GravityCompat.Start);
}