用后退按钮上的另一个替换片段
Replace Fragment with another on back button
我试图覆盖后退按钮,因为当我按下时它会关闭我的应用程序,我有不同的片段:
- 片段 A:索引(当我按下后退按钮时,它会关闭应用程序)
- Fragment B(当我按下后退按钮时,它将返回到 Fragment A)
- Fragment C(当我按下后退按钮时,它将返回到 Fragment A)
我有我的 Main Activity:它管理我的 Fragments(因为有一个导航抽屉)。
我找到了很多关于这个的帖子,但我无法实现它们:
以片段 B 为例:
@Override
public void onBackPressed(){
FragmentManager fm = getSupportFragmentManager();
Fragment f = fm.findFragmentById(R.id.fragmentb); // get the fragment that is currently loaded in placeholder
Object tag = f.getTag();
// do handling with help of tag here
// call super method
super.onBackPressed();
}
它说不能解析onBackPressed()和getSupportFragmentManager(),我想我没有正确使用该方法,所以怎么办?
Activity:
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements FragmentDrawer.FragmentDrawerListener {
private static String TAG = MainActivity.class.getSimpleName();
private Toolbar mToolbar;
private FragmentDrawer drawerFragment;
//Initialisation de l activite avec les donnees necessaires
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
drawerFragment = (FragmentDrawer)getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
drawerFragment.setUp(R.id.fragment_navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout), mToolbar);
drawerFragment.setDrawerListener(this);
// Affichage de la navigation
displayView(0);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//Ajout des items
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onDrawerItemSelected(View view, int position) {
displayView(position);
}
private void displayView(int position) {
Fragment fragment = null;
String title = getString(R.string.app_name);
switch (position) {
case 0:
fragment = new Accueil();
title = getString(R.string.title_accueil);
break;
case 1:
fragment = new NosOffres();
title = getString(R.string.title_nosoffres);
break;
case 2:
fragment = new DemandeGratuite();
title = getString(R.string.title_demandegratuite);
break;
case 3:
fragment = new ContactezNous();
title = getString(R.string.title_contact);
break;
case 4:
fragment = new Actualites();
title = getString(R.string.title_actu);
break;
case 5:
fragment = new MentionsLegales();
title = getString(R.string.title_mentions);
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container_body, fragment);
fragmentTransaction.commit();
// libelle du toolbar
TextView titlet;
titlet = (TextView) findViewById(R.id.main_toolbar_title);
titlet.setText(title);
titlet.setTypeface(Typeface.createFromAsset(getAssets(), "fonts/GothamBook.ttf"));
}
}
}
@jujyfruits
我试过了但是没用:
@Override
public void onBackPressed(){
Fragment myFragment = getSupportFragmentManager().findFragmentById(R.id.demande_gratuite);
if (myFragment != null && myFragment.isVisible()) {
AlertDialog alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Reset...");
alertDialog.setMessage("test");
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
alertDialog.show();
}
super.onBackPressed();
}
}
@AutonomousApps
public class MainActivity extends AppCompatActivity implements FragmentDrawer.FragmentDrawerListener {
private static String TAG = MainActivity.class.getSimpleName();
private Toolbar mToolbar;
private FragmentDrawer drawerFragment;
//Initialisation de l activite avec les donnees necessaires
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
drawerFragment = (FragmentDrawer)getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
drawerFragment.setUp(R.id.fragment_navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout), mToolbar);
drawerFragment.setDrawerListener(this);
// Affichage de la navigation
displayView(0);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//Ajout des items
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onDrawerItemSelected(View view, int position) {
displayView(position);
}
private void displayView(int position) {
Fragment fragment = null;
String title = getString(R.string.app_name);
switch (position) {
case 0:
fragment = new Accueil();
title = getString(R.string.title_accueil);
break;
case 1:
fragment = new NosOffres();
title = getString(R.string.title_nosoffres);
break;
case 2:
fragment = new DemandeGratuite();
title = getString(R.string.title_demandegratuite);
break;
case 3:
fragment = new ContactezNous();
title = getString(R.string.title_contact);
break;
case 4:
fragment = new Actualites();
title = getString(R.string.title_actu);
break;
case 5:
fragment = new MentionsLegales();
title = getString(R.string.title_mentions);
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container_body, fragment);
fragmentTransaction.addToBackStack("name");
fragmentTransaction.commit();
// libelle du toolbar
TextView titlet;
titlet = (TextView) findViewById(R.id.main_toolbar_title);
titlet.setText(title);
titlet.setTypeface(Typeface.createFromAsset(getAssets(), "fonts/GothamBook.ttf"));
}
}
@Override
public void onBackPressed(){
FragmentManager mgr = getSupportFragmentManager();
if (mgr.getBackStackEntryCount() == 0) {
super.onBackPressed();
}else{
mgr.popBackStack();
}
}
这是我在片段之间导航时使用的:
MainActivity.java:
@Override
public void onBackPressed() {
// note: you can also use 'getSupportFragmentManager()'
FragmentManager mgr = getFragmentManager();
if (mgr.getBackStackEntryCount() == 0) {
// No backstack to pop, so calling super
super.onBackPressed();
} else {
mgr.popBackStack();
}
}
编辑第二个: 请注意,如果您还没有处理它,您只想调用 super.onBackPressed()
(例如,弹出片段管理器的后栈)。
为此,您必须将新片段添加到 FragmentManager
的后台堆栈 (addToBackStack()
)。例如(也在MainActivity.java):
private void displayView(int position) {
Fragment fragment = ...; // YOUR CODE HERE
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container_body, fragment);
// ADD THIS LINE
fragmentTransaction.addToBackStack("name"); // name can be null
fragmentTransaction.commit();
// libelle du toolbar
TextView titlet;
titlet = (TextView) findViewById(R.id.main_toolbar_title);
titlet.setText(title);
titlet.setTypeface(Typeface.createFromAsset(getAssets(), "fonts/GothamBook.ttf"));
}
}
编辑第三个 (7/28): 在您的 onCreate(Bundle)
方法中,您通过调用 displayView(int)
方法来执行您的第一个片段事务。 displayView(int)
总是 将其片段事务添加到后台堆栈。这不是你想要的。 第一个片段交易应该使用fragmentTransaction.**add**(int, Fragment)
并且应该不调用addToBackStack(String)
。 之后的每个事务第一个应该调用 fragmentTransaction.**replace**(int, Fragment)
并且 应该 调用 addToBackStack(String)
。这样做的原因是你第一个交易基本上是"adding"一个片段(你的UI)到一个空容器(它不是"replacing"另一个分段)。当这个事务在后台时,这意味着空容器状态在后台是也。因此,当您弹出最后一笔交易时,它会显示空白 UI.
编辑第一个: 当您调用 addToBackStack(String name)
on a FragmentTransaction
object (which you obtain by calling getFragmentManager().beginTransaction()
), then you are adding a FragmentTransaction
to your FragmentManager
s 'backstack'. What my code does is check the size of the backstack by calling getFragmentManager.getBackStackEntryCount()
. If that number is greater than zero, then we know we have FragmentTransaction
s on the backstack. In such a case, you can call getFragmentManager.popBackStack()
时,这会将最后一个事务从后台堆栈中弹出——换句话说,将您的应用程序返回到最后一个片段那是在展出。
如果 backstack entry county 等于 0,那么这意味着你在你的片段 A,你应该改为调用 super.onBackPressed()
,这将导致应用程序退出。
onBackPressed()
和 getSupportFragmentManager()
是 Activity class 中的方法,而不是 Fragment,因此您必须在 Activity 而不是分段。
如果你只想为一个片段实现一种特定的行为,你可以检查当前可见的片段是什么,然后实现你的行为。像这样:
@Override
public void onBackPressed(){
MyFragment myFragment = (MyFragment)getFragmentManager().findFragmentByTag("YOUR_FRAGMENT");
if (myFragment != null && myFragment.isVisible()) {
// the code for whatever behaviour you want goes here
}
else
super.onBackPressed();
}
另一种可能更简单的方法是在添加片段时激活的 Activity 中使用一些标志,然后从 onBackPressed()
.
中读取
编辑对 BENJY 编辑的回应
请注意,您并没有完全使用我发布的代码。您使用的 findFragmentById()
并不适用于所有情况,我无法判断它是否适合您的代码。
您应该使用适用于任何类型的片段事务的 findFragmentByTag
。
只需在您进行交易时向您的片段添加一个标签,如下所示:
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment(), "FRAGMENT_TAG")
.commit();
然后,当您尝试取回 onBackPressed()
中的片段时,您会发现它正在寻找该标签:
PlaceholderFragment myFragment = (PlaceholderFragment) getSupportFragmentManager()
.findFragmentByTag("FRAGMENT_TAG");
进行此更改必须有效。
我知道这个回答太迟了,但是无论谁来这里,都可能得到帮助,我通过下面实现了这个。
如果您想更改在点击设备后退按钮时保持 activity 的片段,上面提到的所有代码都可以在删除下面的行时使用。
super.onBackPressed()
我试图覆盖后退按钮,因为当我按下时它会关闭我的应用程序,我有不同的片段:
- 片段 A:索引(当我按下后退按钮时,它会关闭应用程序)
- Fragment B(当我按下后退按钮时,它将返回到 Fragment A)
- Fragment C(当我按下后退按钮时,它将返回到 Fragment A)
我有我的 Main Activity:它管理我的 Fragments(因为有一个导航抽屉)。
我找到了很多关于这个的帖子,但我无法实现它们:
以片段 B 为例:
@Override
public void onBackPressed(){
FragmentManager fm = getSupportFragmentManager();
Fragment f = fm.findFragmentById(R.id.fragmentb); // get the fragment that is currently loaded in placeholder
Object tag = f.getTag();
// do handling with help of tag here
// call super method
super.onBackPressed();
}
它说不能解析onBackPressed()和getSupportFragmentManager(),我想我没有正确使用该方法,所以怎么办?
Activity:
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements FragmentDrawer.FragmentDrawerListener {
private static String TAG = MainActivity.class.getSimpleName();
private Toolbar mToolbar;
private FragmentDrawer drawerFragment;
//Initialisation de l activite avec les donnees necessaires
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
drawerFragment = (FragmentDrawer)getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
drawerFragment.setUp(R.id.fragment_navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout), mToolbar);
drawerFragment.setDrawerListener(this);
// Affichage de la navigation
displayView(0);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//Ajout des items
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onDrawerItemSelected(View view, int position) {
displayView(position);
}
private void displayView(int position) {
Fragment fragment = null;
String title = getString(R.string.app_name);
switch (position) {
case 0:
fragment = new Accueil();
title = getString(R.string.title_accueil);
break;
case 1:
fragment = new NosOffres();
title = getString(R.string.title_nosoffres);
break;
case 2:
fragment = new DemandeGratuite();
title = getString(R.string.title_demandegratuite);
break;
case 3:
fragment = new ContactezNous();
title = getString(R.string.title_contact);
break;
case 4:
fragment = new Actualites();
title = getString(R.string.title_actu);
break;
case 5:
fragment = new MentionsLegales();
title = getString(R.string.title_mentions);
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container_body, fragment);
fragmentTransaction.commit();
// libelle du toolbar
TextView titlet;
titlet = (TextView) findViewById(R.id.main_toolbar_title);
titlet.setText(title);
titlet.setTypeface(Typeface.createFromAsset(getAssets(), "fonts/GothamBook.ttf"));
}
}
}
@jujyfruits
我试过了但是没用:
@Override
public void onBackPressed(){
Fragment myFragment = getSupportFragmentManager().findFragmentById(R.id.demande_gratuite);
if (myFragment != null && myFragment.isVisible()) {
AlertDialog alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Reset...");
alertDialog.setMessage("test");
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
alertDialog.show();
}
super.onBackPressed();
}
}
@AutonomousApps
public class MainActivity extends AppCompatActivity implements FragmentDrawer.FragmentDrawerListener {
private static String TAG = MainActivity.class.getSimpleName();
private Toolbar mToolbar;
private FragmentDrawer drawerFragment;
//Initialisation de l activite avec les donnees necessaires
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
drawerFragment = (FragmentDrawer)getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
drawerFragment.setUp(R.id.fragment_navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout), mToolbar);
drawerFragment.setDrawerListener(this);
// Affichage de la navigation
displayView(0);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//Ajout des items
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onDrawerItemSelected(View view, int position) {
displayView(position);
}
private void displayView(int position) {
Fragment fragment = null;
String title = getString(R.string.app_name);
switch (position) {
case 0:
fragment = new Accueil();
title = getString(R.string.title_accueil);
break;
case 1:
fragment = new NosOffres();
title = getString(R.string.title_nosoffres);
break;
case 2:
fragment = new DemandeGratuite();
title = getString(R.string.title_demandegratuite);
break;
case 3:
fragment = new ContactezNous();
title = getString(R.string.title_contact);
break;
case 4:
fragment = new Actualites();
title = getString(R.string.title_actu);
break;
case 5:
fragment = new MentionsLegales();
title = getString(R.string.title_mentions);
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container_body, fragment);
fragmentTransaction.addToBackStack("name");
fragmentTransaction.commit();
// libelle du toolbar
TextView titlet;
titlet = (TextView) findViewById(R.id.main_toolbar_title);
titlet.setText(title);
titlet.setTypeface(Typeface.createFromAsset(getAssets(), "fonts/GothamBook.ttf"));
}
}
@Override
public void onBackPressed(){
FragmentManager mgr = getSupportFragmentManager();
if (mgr.getBackStackEntryCount() == 0) {
super.onBackPressed();
}else{
mgr.popBackStack();
}
}
这是我在片段之间导航时使用的:
MainActivity.java:
@Override
public void onBackPressed() {
// note: you can also use 'getSupportFragmentManager()'
FragmentManager mgr = getFragmentManager();
if (mgr.getBackStackEntryCount() == 0) {
// No backstack to pop, so calling super
super.onBackPressed();
} else {
mgr.popBackStack();
}
}
编辑第二个: 请注意,如果您还没有处理它,您只想调用 super.onBackPressed()
(例如,弹出片段管理器的后栈)。
为此,您必须将新片段添加到 FragmentManager
的后台堆栈 (addToBackStack()
)。例如(也在MainActivity.java):
private void displayView(int position) {
Fragment fragment = ...; // YOUR CODE HERE
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container_body, fragment);
// ADD THIS LINE
fragmentTransaction.addToBackStack("name"); // name can be null
fragmentTransaction.commit();
// libelle du toolbar
TextView titlet;
titlet = (TextView) findViewById(R.id.main_toolbar_title);
titlet.setText(title);
titlet.setTypeface(Typeface.createFromAsset(getAssets(), "fonts/GothamBook.ttf"));
}
}
编辑第三个 (7/28): 在您的 onCreate(Bundle)
方法中,您通过调用 displayView(int)
方法来执行您的第一个片段事务。 displayView(int)
总是 将其片段事务添加到后台堆栈。这不是你想要的。 第一个片段交易应该使用fragmentTransaction.**add**(int, Fragment)
并且应该不调用addToBackStack(String)
。 之后的每个事务第一个应该调用 fragmentTransaction.**replace**(int, Fragment)
并且 应该 调用 addToBackStack(String)
。这样做的原因是你第一个交易基本上是"adding"一个片段(你的UI)到一个空容器(它不是"replacing"另一个分段)。当这个事务在后台时,这意味着空容器状态在后台是也。因此,当您弹出最后一笔交易时,它会显示空白 UI.
编辑第一个: 当您调用 addToBackStack(String name)
on a FragmentTransaction
object (which you obtain by calling getFragmentManager().beginTransaction()
), then you are adding a FragmentTransaction
to your FragmentManager
s 'backstack'. What my code does is check the size of the backstack by calling getFragmentManager.getBackStackEntryCount()
. If that number is greater than zero, then we know we have FragmentTransaction
s on the backstack. In such a case, you can call getFragmentManager.popBackStack()
时,这会将最后一个事务从后台堆栈中弹出——换句话说,将您的应用程序返回到最后一个片段那是在展出。
如果 backstack entry county 等于 0,那么这意味着你在你的片段 A,你应该改为调用 super.onBackPressed()
,这将导致应用程序退出。
onBackPressed()
和 getSupportFragmentManager()
是 Activity class 中的方法,而不是 Fragment,因此您必须在 Activity 而不是分段。
如果你只想为一个片段实现一种特定的行为,你可以检查当前可见的片段是什么,然后实现你的行为。像这样:
@Override
public void onBackPressed(){
MyFragment myFragment = (MyFragment)getFragmentManager().findFragmentByTag("YOUR_FRAGMENT");
if (myFragment != null && myFragment.isVisible()) {
// the code for whatever behaviour you want goes here
}
else
super.onBackPressed();
}
另一种可能更简单的方法是在添加片段时激活的 Activity 中使用一些标志,然后从 onBackPressed()
.
编辑对 BENJY 编辑的回应
请注意,您并没有完全使用我发布的代码。您使用的 findFragmentById()
并不适用于所有情况,我无法判断它是否适合您的代码。
您应该使用适用于任何类型的片段事务的 findFragmentByTag
。
只需在您进行交易时向您的片段添加一个标签,如下所示:
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment(), "FRAGMENT_TAG")
.commit();
然后,当您尝试取回 onBackPressed()
中的片段时,您会发现它正在寻找该标签:
PlaceholderFragment myFragment = (PlaceholderFragment) getSupportFragmentManager()
.findFragmentByTag("FRAGMENT_TAG");
进行此更改必须有效。
我知道这个回答太迟了,但是无论谁来这里,都可能得到帮助,我通过下面实现了这个。
如果您想更改在点击设备后退按钮时保持 activity 的片段,上面提到的所有代码都可以在删除下面的行时使用。
super.onBackPressed()