安卓前端研习——TabLayout轻松实现页中页

  界面设计时常要实现页中页的轮播图或者标签页的效果,TabLayout可以帮助我们轻松实现,具体效果如下:

布局文件设置

  首先我们要导入tablayout的依赖,在build中加入如下代码:

compile 'com.android.support:design:23.3.0'

  接着我们要创建一个新的布局文件,就使用一个简单的上面tablayout下面是viewpager的结构,代码如下:

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/quest_tabLayout"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginTop="28dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_percent="0.0625"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/search_filed_quest"
        app:layout_constraintWidth_percent="1" />
    <androidx.viewpager.widget.ViewPager
        android:id="@+id/quest_container"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_percent="0.7360"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/quest_tabLayout"
        app:layout_constraintWidth_percent="1" />

因为运用到了约束布局,所以定位是使用百分比来定位的,其他布局也可通过其他代码实现。

Java逻辑实现

  首先我们要为每一个tablayout页分配一个fragment,利用arraylist将他们组织在一起。示例仅使用两页所以只有两个fragment,具体代码如下:

    public void OnSetList(){
        fragments = new ArrayList<>();
        fragments.add(new NewQuestFragment());
        fragments.add(new SolvedQuestFragment());
    }

  接着是为viewpager配置adapter,具体代码如下:

    public void OnSetListener(){
        quest_container.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
            @NonNull
            @Override
            public Fragment getItem(int position) {
                return fragments.get(position);
            }

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

            @Nullable
            @Override
            public CharSequence getPageTitle(int position) {
                return titles[position];
            }
        });
    }

其中,函数public Fragment getItem(int position)返回的是fragment的下标用于获取每一个fragment页。函数public int getCount()返回的是fragment页的个数,所以直接调用ArrayList的size获取其大小。函数public CharSequence getPageTitle(int position) 是为tablayout的每一个标签命名,具体的名字写在了一个titles数组中,具体代码如下:

private String[] titles = {"最新", "已解决"};

函数会为每一个tab标签调用数组中的字符串命名。

  因为tablayout与viewpager良好的兼容性,所以同步两者的操作不需要使用像viewpager与BottomNavigationView一样复杂,只需要一行代码便可以完成两者操作的同步。代码如下:

    public void OnSetTabStyle(){
        tabLayout.setupWithViewPager(quest_container);
        tabLayout.getTabAt(0).select();
    }

其中tabLayout.getTabAt(0).select();是设置tablayout显示的默认页(下标0即为第一页)

  全部完成后,代码如下:

package com.example.quanta;

import android.os.Bundle;
import android.view.View;
import android.widget.ImageButton;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;

import com.google.android.material.tabs.TabLayout;

import java.util.ArrayList;

public class QuizPageActivity extends AppCompatActivity implements View.OnClickListener{
    private TabLayout tabLayout;
    private ViewPager quest_container;
    private ArrayList<Fragment> fragments;
    private String[] titles = {"最新", "已解决"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.quest_layout);
        OnInitController();
        OnSetList();
        OnSetListener();
        OnSetTabStyle();
    }

    public void OnInitController(){
        ImageButton back_btn = findViewById(R.id.quest_back_btn);
        back_btn.setOnClickListener(this);
        tabLayout = findViewById(R.id.quest_tabLayout);
        quest_container = findViewById(R.id.quest_container);
    }

    public void OnSetList(){
        fragments = new ArrayList<>();
        fragments.add(new NewQuestFragment());
        fragments.add(new SolvedQuestFragment());
    }

    public void OnSetListener(){
        quest_container.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
            @NonNull
            @Override
            public Fragment getItem(int position) {
                return fragments.get(position);
            }

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

            @Nullable
            @Override
            public CharSequence getPageTitle(int position) {
                return titles[position];
            }
        });
    }

    public void OnSetTabStyle(){
        tabLayout.setupWithViewPager(quest_container);
        tabLayout.getTabAt(0).select();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.quest_back_btn:
                this.finish();
                break;
        }
    }
}

设置好看的界面

  除了默认的tablayout样式之外,我们还可以自定义实现各种更加好看的效果。

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/quest_tabLayout"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginTop="28dp"
        app:tabRippleColor="@android:color/transparent"
        app:tabIndicatorColor="#6040FF"
        app:tabTextColor="#616161"
        app:tabSelectedTextColor="#6040FF"
        app:tabMode="fixed"
        app:tabIndicatorFullWidth="false"
        app:tabIndicatorHeight="5dp"
        app:tabIndicator="@drawable/indicator"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_percent="0.0625"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/search_filed_quest"
        app:layout_constraintWidth_percent="1" />

这段代码是在原来的基础上增加了自定义圆角指示下划线的效果。

  • app:tabRippleColor="@android:color/transparent"将按键反馈调为透明,默认情况下是灰色的水波反馈
  • app:tabIndicatorColor="#6040FF"设置了指示下划线的颜色
  • app:tabTextColor="#616161"设置了默认情况下标签文本的颜色
  • app:tabSelectedTextColor="#6040FF"设置了在选中情况下标签文本的颜色
  • app:tabMode="fixed"设置了标签显示的效果,fixed是在标签数较少的情况下使用的,他会将标签平分屏幕的大小,如果有过多的标签数可以选择使用scrolled,即可以滑动的标签选择栏。
  • app:tabIndicatorFullWidth="false"默认情况下下划线会填满整个按钮,将选项设为false下划线就只会与标签中内容的长度相等
  • app:tabIndicatorHeight="5dp"设置了下划线的高度,也就是厚度
  • app:tabIndicator="@drawable/indicator"这是主要设置了圆角下划线的部分

我们需要在drawable文件夹下新建一个indicator.xml文件,并输入一下代码:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <corners android:radius="5dp"/>
        </shape>
    </item>
</layer-list>

因为圆角的半径设置为了5dp,所以前面讲下划线的厚度也设置为了5dp使效果更加美观。


初めて会ったの日から 僕の心の全てを奪った