• android: 结合BottomNavigationView、ViewPager和Fragment 实现左右滑动的效果


    主界面:MainActivity

    package com.yongdaimi.android.androidapitest;
    
    import android.os.Bundle;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import com.yongdaimi.android.androidapitest.fragment.HomePageFragment;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            initFragment();
        }
    
        private void initFragment() {
            HomePageFragment homePageFragment = HomePageFragment.newInstance();
            getSupportFragmentManager()
                    .beginTransaction()
                    .add(R.id.fl_main_container, homePageFragment, homePageFragment.getClass().getSimpleName())
                    .commit();
        }
    
    }

    主界面布局:activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/fl_main_container"
        />

    主界面入口的Fragment: HomePageFragment.java

    package com.yongdaimi.android.androidapitest.fragment;
    
    import android.os.Bundle;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.ViewGroup;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.fragment.app.Fragment;
    import androidx.viewpager.widget.PagerAdapter;
    import androidx.viewpager.widget.ViewPager;
    
    import com.google.android.material.bottomnavigation.BottomNavigationView;
    import com.google.android.material.bottomnavigation.LabelVisibilityMode;
    import com.yongdaimi.android.androidapitest.R;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * A simple {@link Fragment} subclass.
     * Activities that contain this fragment must implement the
     * HomePageFragment.OnFragmentInteractionListener interface
     * to handle interaction events.
     * Use the {@link HomePageFragment#newInstance} factory method to
     * create an instance of this fragment.
     */
    public class HomePageFragment extends Fragment {
    
    
        public static final String TAG = "xp.chen";
    
        private View mContentView;
        private ViewPager vp_pager;
        private BottomNavigationView nv_bottom_menu;
    
        private List<BaseViewController> mPageList;
    
    
        public static HomePageFragment newInstance() {
            return new HomePageFragment();
        }
    
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            // Inflate the layout for this fragment
            mContentView = inflater.inflate(R.layout.fragment_home_page, container, false);
            return mContentView;
        }
    
    
        @Override
        public void onActivityCreated(@Nullable Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            initView();
            initPages();
            setListener();
        }
    
    
        private void initPages() {
            mPageList = new ArrayList<>();
            HomeViewController homeViewController = new HomeViewController(getActivity());
            mPageList.add(homeViewController);
    
            ContactViewController contactViewController = new ContactViewController(getActivity());
            mPageList.add(contactViewController);
    
            SearchViewController searchViewController = new SearchViewController(getActivity());
            mPageList.add(searchViewController);
    
            SettingsViewController settingsViewController = new SettingsViewController(getActivity());
            mPageList.add(settingsViewController);
            vp_pager.setAdapter(mPagerAdapter);
        }
    
    
        private void initView() {
            vp_pager = mContentView.findViewById(R.id.vp_pager);
    
            nv_bottom_menu = mContentView.findViewById(R.id.nv_bottom_menu);
            nv_bottom_menu.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);
            nv_bottom_menu.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
        }
    
    
        private void setListener() {
            vp_pager.addOnPageChangeListener(mOnPageChangeListener);
        }
    
    
        private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener = new BottomNavigationView.OnNavigationItemSelectedListener() {
    
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
                vp_pager.setCurrentItem(menuItem.getOrder());
                return true;
            }
        };
    
    
        private PagerAdapter mPagerAdapter = new PagerAdapter() {
    
            @Override
            public int getCount() {
                return mPageList.size();
            }
    
            @Override
            public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
                return view == object;
            }
    
            @NonNull
            @Override
            public Object instantiateItem(@NonNull ViewGroup container, int position) {
    
                BaseViewController baseViewController = mPageList.get(position);
                ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
                container.addView(baseViewController, layoutParams);
                return baseViewController;
            }
    
            @Override
            public void destroyItem(ViewGroup container, int position, Object object) {
                container.removeView((View) object);
            }
    
            @Override
            public int getItemPosition(Object object) {
                return super.getItemPosition(object);
            }
    
            @Override
            public void notifyDataSetChanged() {
                super.notifyDataSetChanged();
            }
    
        };
    
    
        private ViewPager.OnPageChangeListener mOnPageChangeListener = new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    
            }
    
            @Override
            public void onPageSelected(int position) {
                Log.i(TAG, "onPageSelected: " + position);
                nv_bottom_menu.getMenu().getItem(position).setChecked(true);
            }
    
            @Override
            public void onPageScrollStateChanged(int state) {
    
            }
        };
    
    }

    主界面入口Fragment的布局:fragment_home_page.xml

    <?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"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        >
    
        <androidx.viewpager.widget.ViewPager
            android:id="@+id/vp_pager"
            android:layout_width="match_parent"
            android:layout_height="0dip"
            android:layout_weight="1"
            />
    
    
        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/nv_bottom_menu"
            android:layout_width="match_parent"
            android:layout_height="50dip"
            android:layout_gravity="bottom"
            android:background="?android:attr/windowBackground"
            app:menu="@menu/menu_navigation"
            app:elevation="4dip"
            />
    
    </LinearLayout>

    BottomNavigationView的menu文件:menu_navigation.xml

    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android">
    
        <item
            android:id="@+id/item_tab1"
            android:icon="@drawable/ic_menu_home"
            android:title="Home"
            android:checked="true"
            android:orderInCategory="0"
            />
        <item
            android:id="@+id/item_tab2"
            android:icon="@drawable/ic_menu_contact"
            android:title="Contact"
            android:orderInCategory="1"
            />
        <item
            android:id="@+id/item_tab3"
            android:icon="@drawable/ic_menu_search"
            android:title="Search"
            android:orderInCategory="2"
            />
        <item
            android:id="@+id/item_tab4"
            android:icon="@drawable/ic_menu_settings"
            android:title="Settings"
            android:orderInCategory="3"
            />
    
    </menu>

    这里有几个地方需要特别说明一下:

    1.  HomePageFragment.java 文件中的 nv_bottom_menu.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED); 用来设置BottomNavigationView在切换时的状态,如果不设置,在点击BottomNavigationView上的item在切换时文字可能会发生隐藏。
    2. 上面menu文件中的 orderInCategory 属性用于设置菜单项的排列顺序,必须设置为大于或者等于0的整数值。数值小的排列在前,如果值相等,则按照XML中的顺序展现。 title 属性用于指定navigation Item的标题, icon 属性用于指定navigation item的图标。
    3. fragment_home_page文件中的 app:elevation="4dip" 属性用于设置BottomNavigationView菜单顶部的模糊程度,如果不设置的话,BottomNavigationView的菜单顶部会很模糊。

    最后是几个用于切换的Layout:

    package com.yongdaimi.android.androidapitest.fragment;
    
    import android.content.Context;
    import android.widget.FrameLayout;
    
    import androidx.annotation.NonNull;
    
    public abstract class BaseViewController extends FrameLayout {
        
        public BaseViewController(@NonNull Context context) {
            super(context);
        }
    
    }
    BaseViewController.java
    package com.yongdaimi.android.androidapitest.fragment;
    
    import android.content.Context;
    import android.view.LayoutInflater;
    
    import androidx.annotation.NonNull;
    
    import com.yongdaimi.android.androidapitest.R;
    
    public class HomeViewController extends BaseViewController {
    
        public HomeViewController(@NonNull Context context) {
            super(context);
            LayoutInflater.from(context).inflate(R.layout.layout_home, this);
        }
    
    }
    HomeViewController.java
    package com.yongdaimi.android.androidapitest.fragment;
    
    import android.content.Context;
    import android.view.LayoutInflater;
    
    import androidx.annotation.NonNull;
    
    import com.yongdaimi.android.androidapitest.R;
    
    public class ContactViewController extends BaseViewController {
    
        public ContactViewController(@NonNull Context context) {
            super(context);
            LayoutInflater.from(context).inflate(R.layout.layout_contact, this);
        }
    
    }
    ContactViewController.java
    package com.yongdaimi.android.androidapitest.fragment;
    
    import android.content.Context;
    import android.view.LayoutInflater;
    
    import androidx.annotation.NonNull;
    
    import com.yongdaimi.android.androidapitest.R;
    
    public class SearchViewController extends BaseViewController {
    
        public SearchViewController(@NonNull Context context) {
            super(context);
            LayoutInflater.from(context).inflate(R.layout.layout_search, this);
        }
    
    }
    SearchViewController.java
    package com.yongdaimi.android.androidapitest.fragment;
    
    import android.content.Context;
    import android.view.LayoutInflater;
    
    import androidx.annotation.NonNull;
    
    import com.yongdaimi.android.androidapitest.R;
    
    public class SettingsViewController extends BaseViewController {
    
        public SettingsViewController(@NonNull Context context) {
            super(context);
            LayoutInflater.from(context).inflate(R.layout.layout_settings, this);
        }
    
    }
    SettingsViewController.java

    基本上都是一样的,它们的布局文件也很简单,就是一个布局里加一个TextView。

    最终效果: 

    我这里的PageAdapter中并没有直接使用Fragment, 因为ViewPager在加载Fragment时,会同时初始化几个Fragment,这在实际开发中很不友好,目前正在想办法解决,这也是我什么只使用一个Fragment多个Layout的主要原因。如果希望ViewPager中添加的也是Fragment,可参考:

    Android布局实现-BottomNavigationView+ViewPager+Fragment+整合

  • 相关阅读:
    JS数组常用方法参考---5、sort方法
    JS数组常用方法---1、课程介绍
    JS数组常用方法参考---4、unshift方法
    JS数组常用方法参考---3、队列对应的方法
    ES6课程---12、面向对象
    legend3---30、不同类型的网站打包方案
    数据库Sharding的基本思想和切分策略
    用sharding技术来扩展你的数据库(一)sharding 介绍
    什么是Scale Up和Scale Out?
    淘宝网采用什么技术架构来实现网站高负载的
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/11929394.html
Copyright © 2020-2023  润新知