use*_*007 16 android navigationbar android-fragments bottomnavigationview
我点击导航栏中的项目底部导航栏我正在替换片段.我有3个片段A,B,C所以点击b项B片段加载,在B我调用3-4个API.所以,现在如果我转到C然后再次来到B,就会创建一个新的B Fragment实例,并再次调用这些API,如何保存片段实例状态,而不是在更改片段时再次调用API.这是我的代码.
mBottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
int id = item.getItemId();
Fragment currentLoaded = fgMan.findFragmentById(R.id.container_body);
switch (id) {
case R.id.nearby_fragment:
if (!(currentLoaded instanceof SpotFeedMapFragment)) {
removeScroll();
mNearByFragment = fgMan.findFragmentByTag(NEARBY_FRAGMENT_TAG) != null ? fgMan.findFragmentByTag(NEARBY_FRAGMENT_TAG) : mNearByFragment;
fgMan.beginTransaction().setCustomAnimations(R.anim.abc_fade_in, R.anim.abc_fade_out);
fgMan.beginTransaction().replace(R.id.container_body, mNearByFragment, NEARBY_FRAGMENT_TAG).commit();
fgMan.executePendingTransactions();
getSupportActionBar().setTitle(getString(R.string.nearby_fragment));
}
break;
case R.id.route_fragment:
if (!(currentLoaded instanceof BusLocationsFragment)) {
if (!inParent) {
mRl.removeView(fixLayout);
p.addRule(RelativeLayout.BELOW, toolbar.getId());
scrollView.setLayoutParams(p);
scrollView.addView(fixLayout);
mRl.addView(scrollView);
inParent = true;
}
//mFragment = new BusLocationsFragment();
mBusLocFragment = fgMan.findFragmentByTag(BUS_LOC_FRAGMENT_TAG) != null ? fgMan.findFragmentByTag(BUS_LOC_FRAGMENT_TAG) : mBusLocFragment;
fgMan.beginTransaction().setCustomAnimations(R.anim.abc_fade_in, R.anim.abc_fade_out);
fgMan.beginTransaction().replace(R.id.container_body, mBusLocFragment, BUS_LOC_FRAGMENT_TAG).commit();
fgMan.executePendingTransactions();
getSupportActionBar().setTitle(getString(R.string.app_name));
}
break;
case R.id.newsfeed_activity:
if (!(currentLoaded instanceof NewsFeedActivity)) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
removeScroll();
}
mNewsFeedFragment = fgMan.findFragmentByTag(NEWSFEED_FRAGMENT_TAG) != null ? fgMan.findFragmentByTag(NEWSFEED_FRAGMENT_TAG) : mNewsFeedFragment;
fgMan.beginTransaction().setCustomAnimations(R.anim.abc_fade_in, R.anim.abc_fade_out);
fgMan.beginTransaction().replace(R.id.container_body, mNewsFeedFragment, NEWSFEED_FRAGMENT_TAG).commit();
fgMan.executePendingTransactions();
getSupportActionBar().setTitle(getString(R.string.news));
}
break;
}
return true;
}
});
Run Code Online (Sandbox Code Playgroud)
我已经初始化以上片段的成员变量onCreate的MainActivity
Har*_*tra 12
您应该使用FragmentPagerAdapter来启动片段,因此当您想要在它们之间切换时,片段的状态将被保存.
CutomViewPager viewPager = (CustomViewPager) findViewById(R.id.viewpager1);
ViewPagerAdapter adapter = new ViewPagerAdapter (MainActivity.this.getSupportFragmentManager());
adapter.addFragment(new SpotFeedMapFragment(), "title");
adapter.addFragment(new BusLocationsFragment(), "title");
adapter.addFragment(new NewsFeedActivity(), "title");
viewPager.setAdapter(adapter);
Run Code Online (Sandbox Code Playgroud)
然后在选择的底部导航中,您可以通过简单命令设置片段
viewPager.setCurrentItem(n);
Run Code Online (Sandbox Code Playgroud)
我的viewpager类如下:
public class CustomViewPager extends ViewPager {
private boolean isPagingEnabled;
public CustomViewPager(Context context) {
super(context);
this.isPagingEnabled = true;
}
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.isPagingEnabled = true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return this.isPagingEnabled && super.onTouchEvent(event);
}
//for samsung phones to prevent tab switching keys to show on keyboard
@Override
public boolean executeKeyEvent(KeyEvent event) {
return isPagingEnabled && super.executeKeyEvent(event);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
return this.isPagingEnabled && super.onInterceptTouchEvent(event);
}
public void setPagingEnabled(boolean enabled) {
this.isPagingEnabled = enabled;
}
}
Run Code Online (Sandbox Code Playgroud)
在xml而不是fragemnt你需要的空布局:
<com.package.util.CustomViewPager
android:id="@+id/viewpager1"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Run Code Online (Sandbox Code Playgroud)
自定义FragmentPagerAdapter的代码:
private class ViewPagerAdapter extends FragmentPagerAdapter {
private final SparseArray<WeakReference<Fragment>> instantiatedFragments = new SparseArray<>();
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
final Fragment fragment = (Fragment) super.instantiateItem(container, position);
instantiatedFragments.put(position, new WeakReference<>(fragment));
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
instantiatedFragments.remove(position);
super.destroyItem(container, position, object);
}
@Nullable
Fragment getFragment(final int position) {
final WeakReference<Fragment> wr = instantiatedFragments.get(position);
if (wr != null) {
return wr.get();
} else {
return null;
}
}
@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
Run Code Online (Sandbox Code Playgroud)
我使用过,bottom navigation bar并且通过自定义viewpager来做到这一点,并且我禁用了滑动导航。每次用户单击底部项目时,在viewpager中设置相关片段。Viewpager控制片段的状态,因此不需要控制状态。
自定义ViewPager
public class BottomNavigationViewPager extends ViewPager {
private boolean enabled;
public BottomNavigationViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.enabled = false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onTouchEvent(event);
}
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}
/**
* Enable or disable the swipe navigation
* @param enabled
*/
public void setPagingEnabled(boolean enabled) {
this.enabled = enabled;
}
}
Run Code Online (Sandbox Code Playgroud)
如果仍然要控制片段状态,则可以在此链接中看到我的答案。 如何在android中保存片段状态?
要恢复/保留一个片段的状态,你应该使用ViewPager2,因为它的更新版本ViewPager。
您将得到的代码在我的GitHub库与三个菜单项的底部导航栏有更多的功能。我还在这里提供了一个简单的描述,其中包含底部导航栏中的两个菜单项。
分步指南(以恢复/保留 EditText 的状态为例):
第1步:
在build.gradle(应用程序模块)文件中添加依赖项:
dependencies {
def nav_version = "2.3.0"
implementation "androidx.navigation:navigation-fragment:$nav_version"
implementation "androidx.navigation:navigation-ui:$nav_version"
implementation 'androidx.viewpager2:viewpager2:1.0.0'
}
Run Code Online (Sandbox Code Playgroud)
第2步:
将menu_bottom_navigation.xml添加到res/menu :(您也可以向菜单项添加图标)
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_first"
android:checked="true"
android:title="First"
app:showAsAction="always" />
<item
android:id="@+id/menu_second"
android:checked="false"
android:title="Second"
app:showAsAction="always" />
</menu>
Run Code Online (Sandbox Code Playgroud)
第 3 步:
将activity_main.xml添加到res/layout :(将菜单添加到BottomNavigationView并放置ViewPager2)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activityRoot"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom"
android:orientation="vertical"
android:animateLayoutChanges="true"
tools:context=".MainActivity">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/bottom_navigation"
android:layout_alignParentTop="true"
android:layout_weight="1"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_gravity="bottom"
android:fitsSystemWindows="true"
app:itemIconSize="20dp"
android:background="#A8DD44"
app:menu="@menu/menu_bottom_navigation" />
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)
第四步:
将fragment_first.xml添加到res/layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_margin="20dp"
tools:context="com.example.rough.Fragment.FirstFragment">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="First Fragment"
android:layout_centerInParent="true"
android:textSize="30sp" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Write something & it will stay"
android:ems="13"/>
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)
第 5 步:
将fragment_second.xml添加到res/layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp"
android:orientation="vertical"
tools:context="com.example.rough.Fragment.SecondFragment">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Second Fragment"
android:layout_centerInParent="true"
android:textSize="30sp" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Write something & it will stay"
android:ems="13"/>
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)
第 6 步:
ViewPagerAdapter.java :
public class ViewPagerAdapter extends FragmentStateAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
public ViewPagerAdapter(@NonNull FragmentManager fragmentManager, Lifecycle b ) {
super(fragmentManager,b);
}
public void addFragment(Fragment fragment) {
mFragmentList.add(fragment);
}
@NonNull
@Override
public Fragment createFragment(int position) {
return mFragmentList.get(position);
}
@Override
public int getItemCount() {
return mFragmentList.size();
}
}
Run Code Online (Sandbox Code Playgroud)
第 7 步:
FirstFragment.java:
public class FirstFragment extends Fragment {
public FirstFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_first, container, false);
}
}
Run Code Online (Sandbox Code Playgroud)
第 8 步:
SecondFragment.java:
public class SecondFragment extends Fragment {
public SecondFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_second, container, false);
}
}
Run Code Online (Sandbox Code Playgroud)
第 9 步:
主活动.java :
public class MainActivity extends AppCompatActivity {
BottomNavigationView bottomNavigationView;
private ViewPager2 viewPager2;
FirstFragment firstFragment;
SecondFragment secondFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager2 = findViewById(R.id.viewpager2);
bottomNavigationView = findViewById(R.id.bottom_navigation);
bottomNavigationView.setOnNavigationItemSelectedListener(
new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_first:
viewPager2.setCurrentItem(0,false);
break;
case R.id.menu_second:
viewPager2.setCurrentItem(1,false);
break;
}
return false;
}
});
viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
switch (position) {
case 0:
bottomNavigationView.getMenu().findItem(R.id.menu_first).setChecked(true);
break;
case 1:
bottomNavigationView.getMenu().findItem(R.id.menu_second).setChecked(true);
break;
}
}
});
setupViewPager(viewPager2);
}
private void setupViewPager(ViewPager2 viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager(), getLifecycle());
firstFragment =new FirstFragment();
secondFragment =new SecondFragment();
adapter.addFragment(firstFragment);
adapter.addFragment(secondFragment);
viewPager.setAdapter(adapter);
}
}
Run Code Online (Sandbox Code Playgroud)