Как изменить фрагмент с помощью операции "Нижняя навигация"?
Я создал новый проект с "Bottom Navigation Activity":
![enter image description here]()
Это сгенерированный код:
package com.aaron.waller.mrpolitik;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView mTextMessage;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
mTextMessage.setText(R.string.title_home);
case R.id.navigation_dashboard:
mTextMessage.setText(R.string.title_dashboard);
case R.id.navigation_notifications:
mTextMessage.setText(R.string.title_notifications);
}
return true;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextMessage = (TextView) findViewById(R.id.message);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}
}
Как я могу перейти на новые фрагменты с нижней панели? Например, у меня есть 3 фрагмента: Fragment1 Fragment2 и Fragment3, и я хочу изменить их с помощью 3 кнопок на нижней панели. Также я хочу, чтобы я мог переключать фрагменты, проводя пальцем влево и вправо, как я могу это сделать?
Ответы
Ответ 1
Таким образом, я бы сначала добавил три метода, похожих на этот (каждый для одного фрагмента. Замените имя макета и объект фрагмента на соответствующий фрагмент, на который переключается):
public void switchToFragment1() {
FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction().replace(R.id.your_fragment_layout_name, new Fragment1()).commit();
}
Таким образом, ваш оператор switch будет выглядеть так:
switch (item.getItemId()) {
case R.id.navigation_home:
mTextMessage.setText(R.string.title_home);
switchToFragment1();
break;
case R.id.navigation_dashboard:
mTextMessage.setText(R.string.title_dashboard);
switchToFragment2();
break;
case R.id.navigation_notifications:
mTextMessage.setText(R.string.title_notifications);
switchToFragment3();
break;
}
Что касается переключения фрагментов, проводя в стороны, я думаю, вам понадобится ViewPager.
Ответ 2
Это довольно "просто".
- Создайте свои фрагменты. Скажем, мы хотим 3 фрагмента;
FragmentA
, FragmentB
и FragmentC
с FragmentA
, являющимся первым фрагментом, который мы хотим в BottomNavigationView.
-
В своей деятельности перейдите к методу onNavigationItemSelected
и измените содержимое на это:
private BottomNavigationView.OnNavigationItemSelectedListener
mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener(){
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.frag_a:
currentFragment = new FragmentA();
ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content, currentFragment);
ft.commit();
return true;
case R.id.frag_b:
currentFragment = new FragmentB();
ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content, currentFragment);
ft.commit();
return true;
case R.id.frag_c:
currentFragment = new FragmentC();
ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content, currentFragment);
ft.commit();
return true;
}
return false;
}
};
-
В вашем методе onCreate()
сделайте следующее:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client_profile);
ft = getSupportFragmentManager().beginTransaction();
currentFragment = new FragmentA();
ft.replace(R.id.content, currentFragment);
ft.commit();
BottomNavigationView navigation = (BottomNavigationView)
findViewById(R.id.navigation); navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}
Если вы не добавили FragmentA
в onCreate()
, при первом запуске это действие будет пустым.
Если вам интересно, что означает R.id.content
, это идентификатор Framelayout в вашем макете активности. Сначала он содержит TextView
, удаляет TextView так, чтобы он выглядел следующим образом:
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
Наконец, ft
и currentFragment
определяются следующим образом:
Fragment currentFragment = null;
FragmentTransaction ft;
Не уверен в элегантности, но это работает.
Ответ 3
Лучший способ - использовать ViewPager
с FragmentPagerAdapter
. Так как он обманывает фрагменты внутри него. Используйте setOnNavigationItemSelectedListener
с помощью BottomNavigationView
, чтобы прослушивать клики пользователей. И используйте viewPager.setCurrentItem(..)
для перемещения между страницами.
Создание нового фрагмента каждый раз, когда пользователь нажимает на элемент в нижнем навигационном представлении, не является хорошим решением (особенно когда пользователь нажимает на элемент экрана, на котором он сейчас находится, решение выше создаст новый фрагмент даже для этого случая)
Ответ 4
//fully tested
public class DashBoardActivity extends AppCompatActivity {
Fragment fragment = null;
FragmentTransaction fragmentTransaction;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
return true;
case R.id.navigation_dashboard:
fragment = new FragmentDashBoard();
switchFragment(fragment);
return true;
case R.id.navigation_notifications:
fragment = new FragmentNotification();
switchFragment(fragment);
return true;
}
return false;
}
};
private void switchFragment(Fragment fragment) {
fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content, fragment);
fragmentTransaction.commit();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
navigation.setSelectedItemId(R.id.navigation_dashboard);
}
}
Ответ 5
Есть еще один способ избежать воссоздания фрагмента - fm.beginTransaction().hide(active).show(aimFragment)
Мой пример следующий (просто скопируйте из моего недавнего проекта):
public class MainActivity extends AppCompatActivity {
@BindView(R.id.main_bottom_navigation) BottomNavigationView mBottomNavigationView;
final Fragment mTaskListFragment = new TaskListFragment();
final Fragment mUserGroupFragment = new UserGroupFragment();
final Fragment mUserMeFragment = new UserMeFragment();
final FragmentManager fm = getSupportFragmentManager();
Fragment active = mTaskListFragment;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mBottomNavigationView
.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
fm.beginTransaction().add(R.id.main_fragment_container, mUserMeFragment, "3")
.hide(mUserMeFragment).commit();
fm.beginTransaction().add(R.id.main_fragment_container, mUserGroupFragment, "2")
.hide(mUserGroupFragment).commit();
fm.beginTransaction().add(R.id.main_fragment_container, mTaskListFragment, "1").commit();
}
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= item -> {
// TODO: 这种切换方式比较快,但横竖屏切换会出问题,已经
switch (item.getItemId()) {
case R.id.nav_list:
fm.beginTransaction().hide(active).show(mTaskListFragment).commit();
active = mTaskListFragment;
break;
case R.id.nav_group:
fm.beginTransaction().hide(active).show(mUserGroupFragment).commit();
active = mUserGroupFragment;
break;
case R.id.nav_me:
fm.beginTransaction().hide(active).show(mUserMeFragment).commit();
active = mUserMeFragment;
break;
}
return true;
};
}
Это кажется эффективным и будет хорошо работать, пока вы не поверните телефон. И я исправил это, запретив вращаться в этом AndroidManifest.xml
(в AndroidManifest.xml
):
<activity android:name=".MainActivity"
android:screenOrientation="portrait"
android:launchMode="singleTop">
Может быть, сохранить active
может исправить это лучше, но я не пробовал. (Извините за мой плохой английский)
Ответ 6
Простой способ с компонентом навигации:
bottom_navigation_view?.setupWithNavController(navController)
Ответ 7
вы можете использовать этот
fragmentManager = getFragmentManager();
transaction = fragmentManager.beginTransaction();
FragmentA a = new FragmentA();
transaction.replace(R.id.frame, a);
transaction.commit();