在我的布局底部,我有一个包含三个片段的BottomNavigationView。如果我单击后退按钮,片段正在切换,但不是底部图标。我该如何解决?
addToBackStack() 有效。也许你有一些建议来美化代码。
在活动或片段中使用片段标签是一种好习惯吗?
public class MainActivity extends AppCompatActivity {
private FragmentManager mFragmentManager;
private BottomNavigationView mBottomNavigationView;
private static final String HOME_FRAGMENT = "homeFragment";
private static final String SEARCH_FRAGMENT = "searchFragment";
private static final String SHARE_FRAGMENT = "shareFragment";
private boolean isFirstFragment;
private long mBackPressedTime;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
setBottomNavigationView();
}
private void init() {
mBottomNavigationView = findViewById(R.id.bottomNavigationView);
mFragmentManager = getSupportFragmentManager();
mBackPressedTime = 0;
}
private void setBottomNavigationView() {
setFragment(HomeFragment.newInstance(), HOME_FRAGMENT);
isFirstFragment = true;
mBottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.ic_home:
setFragment(HomeFragment.newInstance(), HOME_FRAGMENT);
return true;
case R.id.ic_search:
setFragment(SearchFragment.newInstance(), SEARCH_FRAGMENT);
return true;
case R.id.ic_circle:
setFragment(ShareFragment.newInstance(), SHARE_FRAGMENT);
return true;
default:
return false;
}
}
});
}
private void setFragment(Fragment fragment, String tag) {
FragmentTransaction transaction = mFragmentManager.beginTransaction();
transaction.replace(R.id.container, fragment, tag);
if (isFirstFragment) {
transaction.addToBackStack(tag);
}
transaction.commit();
}
@Override
public void onBackPressed() {
final long currentTimeMillis = System.currentTimeMillis();
if (mFragmentManager.getBackStackEntryCount() > 0) {
mFragmentManager.popBackStack();
} else if (currentTimeMillis - mBackPressedTime > 2000) {
mBackPressedTime = currentTimeMillis;
Toast.makeText(this, getString(R.string.reach_homescreen), Toast.LENGTH_SHORT).show();
} else {
super.onBackPressed();
}
}
}
Run Code Online (Sandbox Code Playgroud)
@Hans Baum 而不是将您的第一个片段添加到后台堆栈尝试此代码,
@Override
public void onBackPressed() {
if(mBottomNavigationView.getSelectedItemId () != R.id.ic_home)
{
mBottomNavigationView.setSelectedItemId(R.id.ic_home);
}
else
{
super.onBackPressed();
}
}
Run Code Online (Sandbox Code Playgroud)
如果您在 Home Fragment 中,此代码将退出您的活动,否则如果您在任何其他 Fragment 中,它将转到 Home Fragment。所以不需要 addToBackStack() 。所以你的 serFragment() 方法应该是,
private void setFragment(Fragment fragment, String tag) {
FragmentTransaction transaction = mFragmentManager.beginTransaction();
transaction.replace(R.id.container, fragment, tag);
transaction.commit();
}
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你。请注意,在您的代码中,您从未将 false 分配给 isFirstFragment,因此我假设所有片段都添加到非常消耗内存的后台堆栈中。
更新:由于您的要求不同。因为您想要像标签一样的Instagra m,我希望此实现对您有所帮助。
Deque<Integer> mStack = new ArrayDeque<>();
boolean isBackPressed = false;
private void setBottomNavigationView() {
mBottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.ic_home:
if(!isBackPressed) {
pushFragmentIntoStack(R.id.ic_home);
}
isBackPressed = false
setFragment(HomeFragment.newInstance(), HOME_FRAGMENT);
return true;
case R.id.ic_search:
if(!isBackPressed) {
pushFragmentIntoStack(R.id.ic_search);
}
isBackPressed = false
setFragment(SearchFragment.newInstance(), SEARCH_FRAGMENT);
return true;
case R.id.ic_circle:
if(!isBackPressed) {
pushFragmentIntoStack(R.id.ic_circle);
}
isBackPressed = false
setFragment(ShareFragment.newInstance(), SHARE_FRAGMENT);
return true;
default:
return false;
}
}
});
mBottomNavigationView.setOnNavigationItemReselectedListener(new
BottomNavigationView.OnNavigationItemReselectedListener() {
@Override
public void onNavigationItemReselected(@NonNull MenuItem item) {
}
});
mBottomNavigationView.setSelectedItemId(R.id.ic_home);
pushFragmentIntoStack(R.id.ic_home);
}
private void pushFragmentIntoStack(int id)
{
if(mStack.size() < 3)
{
mStack.push(id);
}
else
{
mStack.removeLast();
mStack.push(id);
}
}
private void setFragment(Fragment fragment, String tag) {
FragmentTransaction transaction = mFragmentManager.beginTransaction();
transaction.replace(R.id.container, fragment, tag);
transaction.commit();
}
@Override
public void onBackPressed() {
if(mStack.size() > 1)
{
isBackPressed = true;
mStack.pop();
mBottomNavigationView.setSelectedItemId(mStack.peek());
}
else
{
super.onBackPressed();
}
}
Run Code Online (Sandbox Code Playgroud)
我使用 deque 来存储选项卡被点击的顺序,因为有 3 个选项卡 deque 大小是 3 。按下后它会弹出堆栈并转到该选项卡。如果堆栈中没有项目,它将退出活动。
重要说明: 在这种情况下不要将片段添加到 backstack,因为当我切换选项卡时,backstack 计数将不断增加,甚至可能导致 MemoryOutOfBound 异常。
对于问题 2: 来到您的 Fragment 标签问题,将标签保存在 Fragment 中很好。由于片段可以在任何活动中重用,而不是在每个使用它的活动中添加标签,如果我们将它添加到片段本身中会很好。
| 归档时间: |
|
| 查看次数: |
3369 次 |
| 最近记录: |