自定义 TabLayout 按钮

Customizing TabLayout Buttons

目前我的TabLayout如下所示:

它的代码是一个普通的 TabLayout:

<android.support.design.widget.TabLayout
   android:id="@+id/tabs"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   app:tabMode="fixed"
   app:tabGravity="fill"/>

我想实现以下风格:

如何实现? 中间按钮的作用是调用一个activity,TabLayout会放在屏幕底部。

注意:我实际上有 4 个选项卡,而不仅仅是 2

这是我之前的代码

<android.support.constraint.ConstraintLayout 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:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        tools:context="com.sampleproject.MainActivity"
        tools:showIn="@layout/activity_main">

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            android:orientation="vertical">

               <!--SOME CODE HERE-->

            <android.support.v7.widget.CardView
                android:id="@+id/bottom"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/top"
                android:orientation="horizontal"
                app:cardBackgroundColor="@color/colorWhite"
                app:cardCornerRadius="0dp"
                app:cardElevation="20dp"
                app:cardUseCompatPadding="false"
                tools:layout_editor_absoluteY="0dp"
                tools:layout_editor_absoluteX="8dp">

                <LinearLayout
                    android:id="@+id/bottom_container"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="@color/colorWhite"
                    android:gravity="center_horizontal"
                    android:minHeight="48dp"
                    android:orientation="horizontal">

                    <ImageButton
                        style="@style/Base.Widget.AppCompat.ActionButton"
                        android:layout_width="0dp"
                        android:layout_height="?attr/actionBarSize"
                        android:layout_weight="1"
                        android:adjustViewBounds="true"
                        android:src="@drawable/ic_toolbar_messages" />

                    <!--START OF FAKE BUTTON, this button is here to create space between the two ImageButton -->
                    <ImageButton
                        style="@style/Base.Widget.AppCompat.ActionButton"
                        android:layout_width="0dp"
                        android:layout_height="?attr/actionBarSize"
                        android:layout_weight="1"
                        android:adjustViewBounds="true"
                        android:src="@null" />
                    <!--END OF FAKE BUTTON-->

                    <ImageButton
                        style="@style/Base.Widget.AppCompat.ActionButton"
                        android:layout_width="0dp"
                        android:layout_height="?attr/actionBarSize"
                        android:layout_weight="1"
                        android:adjustViewBounds="true"
                        android:src="@drawable/ic_drawer_contact" />   


                </LinearLayout>
            </android.support.v7.widget.CardView>

        </LinearLayout>
    </android.support.constraint.ConstraintLayout>

我正在使用 FloatingActionButton 并将其放在底部|中心

<android.support.design.widget.FloatingActionButton
        android:id="@+id/fabNewConversation"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|center"
        android:layout_margin="@dimen/fab_margin"
        app:srcCompat="@drawable/ic_add" />

我刚刚决定使用 TabLayout,但我不知道如何应用我的样式。

谢谢!

更新

好像BottomNavigationView是我想要的,但是没能达到我的要求。我也不想为此使用外部库。所以我所做的只是 remove the TabLayoutput the ViewPager at the top of the parentmy custom TabLayout style in the bottom。我的要求之一是 ViewPagerdisable the swipe,因此我使用自定义 class 禁用了滑动并触发了 ImageButton 的页面 onClick。感谢您的回答和建议。我稍后会把我的代码。

更新:这是我的代码

首先我为Custom ViewPager创建了一个class NonSwipeableViewPager,这将禁用它的滑动功能。(我搜索了这个,我实际上不是这个[=25的作者=] class)

public class NonSwipeableViewPager extends ViewPager {

    public NonSwipeableViewPager(Context context) {
        super(context);
        setMyScroller();
    }

    public NonSwipeableViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        setMyScroller();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        // Never allow swiping to switch between pages
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // Never allow swiping to switch between pages
        return false;
    }

    //down one is added for smooth scrolling

    private void setMyScroller() {
        try {
            Class<?> viewpager = ViewPager.class;
            Field scroller = viewpager.getDeclaredField("mScroller");
            scroller.setAccessible(true);
            scroller.set(this, new MyScroller(getContext()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public class MyScroller extends Scroller {
        public MyScroller(Context context) {
            super(context, new DecelerateInterpolator());
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy, int duration) {
            super.startScroll(startX, startY, dx, dy, 350 /*1 secs*/);
        }
    }

    //Disable Left and Right arrow swipe for keyboard in some devices
    @Override public boolean executeKeyEvent(KeyEvent event) { return false; }

}

第二,初始化content_main.xml布局。记住!这是 content_main.xml,我 @include 来自 activity_main.xml,其中 ToolBarFloatingActionButton 视图已初始化。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.sample.MainActivity"
    tools:showIn="@layout/activity_main">

    <!--I use LinearLayout to be the container_parent-->
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:orientation="vertical">

        <!--TOP VIEW-->
        <RelativeLayout
            android:id="@+id/top"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">

            <!--Initialize the Custom ViewPager here, Make sure you created the class for this-->
            <com.sample.NonSwipeableViewPager
                android:id="@+id/viewpager"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
            <!--END OF CUSTOM VIEWPAGER -->

        </RelativeLayout>
        <!--END OF TOP VIEW-->

        <!--BOTTOM VIEW-->
        <android.support.v7.widget.CardView
            android:id="@+id/bottom"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/top"
            android:orientation="horizontal"
            app:cardBackgroundColor="@color/colorWhite"
            app:cardCornerRadius="0dp"
            app:cardElevation="20dp"
            app:cardUseCompatPadding="false"
            tools:layout_editor_absoluteY="0dp"
            tools:layout_editor_absoluteX="8dp">

            <LinearLayout
                android:id="@+id/bottom_container"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/colorWhite"
                android:gravity="center_horizontal"
                android:minHeight="48dp"
                android:orientation="horizontal">

                <ImageButton
                    android:id="@+id/btn_one"
                    style="@style/Base.Widget.AppCompat.ActionButton"
                    android:layout_width="0dp"
                    android:layout_height="?attr/actionBarSize"
                    android:layout_weight="1"
                    android:adjustViewBounds="true"
                    android:src="@drawable/ic_one" />

                <ImageButton
                    android:id="@+id/btn_two"
                    style="@style/Base.Widget.AppCompat.ActionButton"
                    android:layout_width="0dp"
                    android:layout_height="?attr/actionBarSize"
                    android:layout_weight="1"
                    android:adjustViewBounds="true"
                    android:src="@drawable/ic_two" />

                <!--START OF FAKE BUTTON FOR SPACER-->
                <ImageButton
                    android:id="@+id/fake_btn_spacer"
                    style="@style/Base.Widget.AppCompat.ActionButton"
                    android:layout_width="0dp"
                    android:layout_height="?attr/actionBarSize"
                    android:layout_weight="1"
                    android:adjustViewBounds="true"
                    android:src="@null"
                    android:clickable="false" />
                <!--END OF START OF FAKE BUTTON FOR SPACER-->

                <ImageButton
                    android:id="@+id/btn_three"
                    style="@style/Base.Widget.AppCompat.ActionButton"
                    android:layout_width="0dp"
                    android:layout_height="?attr/actionBarSize"
                    android:layout_weight="1"
                    android:adjustViewBounds="true"
                    android:src="@drawable/ic_three" />

                <ImageButton
                    android:id="@+id/btn_four"
                    style="@style/Base.Widget.AppCompat.ActionButton"
                    android:layout_width="0dp"
                    android:layout_height="?attr/actionBarSize"
                    android:layout_weight="1"
                    android:adjustViewBounds="true"
                    android:src="@drawable/ic_four" />

            </LinearLayout>

        </android.support.v7.widget.CardView>
        <!--END OF BOTTOM VIEW-->

    </LinearLayout>

</android.support.constraint.ConstraintLayout>

三、activity_main.xml布局

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.sample.MainActivity">

    <!--SOME CODE FOR MY AppBarLayout-->
    <!--SOME CODE FOR MY ToolBar-->

    <!--INCLUDE content_main.xml here-->
    <include layout="@layout/content_main" />

    <!--START OF FloatingActionButton and set it to bottom|center-->
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|center"
        android:layout_margin="@dimen/fab_margin"
        app:srcCompat="@drawable/ic_add" />

</android.support.design.widget.CoordinatorLayout>

最后,MainActivity.class

public class MainActivity extends AppCompatActivity {

    private NonSwipeableViewPager viewPager; //Declare Custom ViewPager Class
    ImageButton btn_one, btn_two, btn_three, btn_four; //Declare ImageButton

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        /**SOME CODE HERE**/

       //Initialize ImageButton
       btn_messages = (ImageButton) findViewById(R.id.btn_one);
       btn_people = (ImageButton) findViewById(R.id.btn_two);
       btn_video_call = (ImageButton) findViewById(R.id.btn_three);
       btn_voice_call = (ImageButton) findViewById(R.id.btn_four);

       //Initialize FloatingActionButton which in the Center at the Bottom of the Parent
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //Handle some functions here...
            }
        });

        //Initialize ViewPager
        viewPager = (NonSwipeableViewPager) findViewById(R.id.viewpager);
        setupViewPager(viewPager); //Call setupViewPager to setup the ViewPager

        //Initialize OnClickListener in every ImageButton
        btn_one.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                viewPager.setCurrentItem(0); //Trigger Page 1 of ViewPager
            }
        });

        btn_two.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                viewPager.setCurrentItem(1); //Trigger Page 2 of ViewPager
            }
        });

        btn_three.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                viewPager.setCurrentItem(2); //Trigger Page 3 of ViewPager
            }
        });

        btn_four.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                viewPager.setCurrentItem(3); //Trigger Page 4 of ViewPager
            }
        });

    }

    //This function setup the ViewPager
    private void setupViewPager(ViewPager viewPager) {
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFragment(new Fragment_Zero(), "ZERO");
        adapter.addFragment(new Fragment_One(), "ONE");
        adapter.addFragment(new Fragment_Two(), "TWO");
        adapter.addFragment(new Fragment_Three(), "THREE");
        viewPager.setAdapter(adapter);
    }

    //Inner Class for ViewPagerAdapter
    class ViewPagerAdapter extends FragmentPagerAdapter {
        private final List<Fragment> mFragmentList = new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();

        public ViewPagerAdapter(FragmentManager manager) {
            super(manager);
        }

        @Override
        public Fragment getItem(int position) {
            return mFragmentList.get(position);
        }

        @Override
        public int getCount() {
            return mFragmentList.size();
        }

        public void addFragment(Fragment fragment, String title) {
            mFragmentList.add(fragment);
            mFragmentTitleList.add(title);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return null;
            // return mFragmentTitleList.get(position);
        }
    }
    //END
}

输出:

我建议您使用底部导航视图来实现这一点。您可以找到文档 here

但是原生的BottomNavigationView在设计上有很多限制。所以你可以使用一些自定义库,比如:

https://github.com/peng8350/JPTabBar

https://github.com/aurelhubert/ahbottomnavigation

您可以使用像

这样的自定义方式

使用 ConstraintLayout 并为其添加 LeftRightBottom 约束。

<android.support.constraint.ConstraintLayout
---
---
>

<android.support.design.widget.FloatingActionButton
...
...
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent”"
app:layout_constraintRight_toRightOf="parent"  />
</Constraint Layout>

将您的其他视图放入其中。

  • Gradle 依赖关系:

    编译 'com.android.support.constraint:constraint-layout:1.0.2'

了解更多about ConstraintLayout

此布局可以通过底部导航视图实现。

在导航视图的中心使用浮动按钮。

https://medium.com/@hitherejoe/exploring-the-android-design-support-library-bottom-navigation-drawer-548de699e8e0

https://segunfamisa.com/posts/bottom-navigation-view-android

https://developer.android.com/reference/android/support/design/widget/BottomNavigationView.html