效果:
//RecyclerViewAdapter
implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.50'
//流式布局
implementation 'com.google.android.flexbox:flexbox:3.0.0'
标签fragment:
package com.example.testcsdnproject;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class ChildFragment extends Fragment {
private View view;
private TextView textView;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
// return super.onCreateView(inflater, container, savedInstanceState);
view =inflater.inflate(R.layout.fragment_child,null);
textView = view.findViewById(R.id.tv_fragment);
initView();
return view;
}
public static ChildFragment newInstance(String tag) {
Bundle args = new Bundle();
args.putString("tag",tag);
ChildFragment fragment = new ChildFragment();
fragment.setArguments(args);
return fragment;
}
private void initView(){
String fragmentTag = getArguments().getString("tag","标签");
textView.setText(fragmentTag);
}
}
fragment_child.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_fragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="子fragment"
android:textSize="16sp"
android:textColor="@color/white"
/>
</RelativeLayout>
Activity:
package com.example.testcsdnproject;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager.widget.ViewPager;
import android.os.Bundle;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.listener.OnItemClickListener;
import com.example.testcsdnproject.adapter.MyFragmentPagerAdapter;
import com.example.testcsdnproject.adapter.StringTabAdapter;
import com.google.android.flexbox.FlexDirection;
import com.google.android.flexbox.FlexboxLayoutManager;
import com.google.android.material.tabs.TabLayout;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class FragmentActivity extends AppCompatActivity {
ViewPager viewpage_metaverse;
TabLayout mTabs;
MyFragmentPagerAdapter mMyFragmentPagerAdapter;
private List<Fragment> fragmentList = new ArrayList<>();
private String[] titles ;
RelativeLayout rl_all_tab;
RecyclerView rv_more_tab; //展开更多tab标签列表
RelativeLayout rl_triangle_up,rl_triangle_down;
TextView tv_all_tab;
private StringTabAdapter stringTabAdapter;
private List<String> tabData = new ArrayList<>(); //测试标签tab数据
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment);
viewpage_metaverse = findViewById(R.id.viewpage_metaverse);
mTabs = findViewById(R.id.tabs);
rl_all_tab = findViewById(R.id.rl_all_tab);
rv_more_tab = findViewById(R.id.rv_more_tab);
tv_all_tab = findViewById(R.id.tv_all_tab);
rl_triangle_up = findViewById(R.id.rl_triangle_up);
rl_triangle_down = findViewById(R.id.rl_triangle_down);
tabData.clear();
for (int i = 0;i<20;i++){
tabData.add("标签"+i);
}
stringTabAdapter = new StringTabAdapter(tabData);
rv_more_tab.setAdapter(stringTabAdapter);
FlexboxLayoutManager layoutManager=new FlexboxLayoutManager(this); //流式布局,按长度自动排列item数量
layoutManager.setFlexDirection(FlexDirection.ROW);
rv_more_tab.setLayoutManager(layoutManager);
initViewPage();
rv_more_tab.addOnItemTouchListener(new OnItemClickListener() {
@Override
public void onSimpleItemClick(BaseQuickAdapter adapter, View view, int position) {
if (viewpage_metaverse!=null){
viewpage_metaverse.setCurrentItem(position+1);
rl_all_tab.setVisibility(View.GONE);
}
}
});
rl_all_tab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
rl_all_tab.setVisibility(View.GONE);
}
});
rl_triangle_up.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
rl_all_tab.setVisibility(View.GONE);
}
});
rl_triangle_down.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
rl_all_tab.setVisibility(View.VISIBLE);
}
});
tv_all_tab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
viewpage_metaverse.setCurrentItem(0);
rl_all_tab.setVisibility(View.GONE);
}
});
}
private void initViewPage(){
// if (homeLabelBeans!=null){
int size = tabData.size()+1;
titles = new String[size];
viewpage_metaverse.setOffscreenPageLimit(0); //设置预先加载的页面个数,设置成0的话即是懒加载
fragmentList.clear();
for (int i = 0;i< titles.length; i++){
if (i == 0){
titles[0] = "全部";
fragmentList.add(ChildFragment.newInstance(titles[0]));
}else {
titles[i] =tabData.get(i-1);
fragmentList.add(ChildFragment.newInstance(titles[i]));
}
}
for (String title : titles){
mTabs.addTab(mTabs.newTab().setText(title));
}
/*mMyFragmentPagerAdapter = new MyFragmentPagerAdapter(getChildFragmentManager(), Arrays.asList(titles),
fragmentList);*/
mMyFragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager(), Arrays.asList(titles),
fragmentList);
viewpage_metaverse.setAdapter(mMyFragmentPagerAdapter);
mTabs.setupWithViewPager(viewpage_metaverse);
mTabs.setTabsFromPagerAdapter(mMyFragmentPagerAdapter);
mTabs.setTabMode(TabLayout.MODE_SCROLLABLE);
// }
}
}
activity_fragment.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:clipChildren="false"
android:background="#1A1A1A">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/ll_title"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:background="#252525"
>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#252525"
android:theme="@style/Widget.Design.TabLayout"
app:tabIndicatorHeight="0dp"
app:tabRippleColor="#00000000"
app:tabSelectedTextColor="#FFFFFFFF"
app:tabTextAppearance="@style/TabText"
app:tabTextColor="#FF999999"/>
<RelativeLayout
android:id="@+id/rl_triangle_down"
android:layout_width="40dp"
android:layout_height="match_parent">
<com.example.testcsdnproject.view.TriangleView
android:id="@+id/triangle_down"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
app:trv_color="#FFBBBBBB"
app:trv_direction="bottom" />
</RelativeLayout>
</LinearLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpage_metaverse"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
/>
</LinearLayout>
<!--展开的全部标签-->
<RelativeLayout
android:id="@+id/rl_all_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="50dp"
android:background="#252525"
android:visibility="gone"
>
<TextView
android:id="@+id/tv_all_tab"
android:layout_width="40dp"
android:layout_height="40dp"
android:text="全部"
android:textColor="#FFFFFFFF"
android:textSize="14sp"
android:gravity="center"
/>
<RelativeLayout
android:id="@+id/rl_triangle_up"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentRight="true">
<com.example.testcsdnproject.view.TriangleView
android:id="@+id/triangle_up"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
app:trv_color="#FFBBBBBB"
app:trv_direction="top"
/>
</RelativeLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_more_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_all_tab"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
/>
</RelativeLayout>
</RelativeLayout>
MyFragmentPagerAdapter:
package com.example.testcsdnproject.adapter;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import java.util.List;
public class MyFragmentPagerAdapter extends FragmentPagerAdapter {
private List<String> tab_title_list;//存放标签页标题
private List<Fragment> fragment_list;//存放ViewPager下的Fragment
public MyFragmentPagerAdapter(FragmentManager fm, List<String> tab_title_list, List<Fragment> fragment_list) {
super(fm);
this.tab_title_list = tab_title_list;
this.fragment_list = fragment_list;
}
@Override
public Fragment getItem(int position) {
return fragment_list.get(position);
}
@Override
public int getCount() {
return fragment_list.size();
}
@Override
public CharSequence getPageTitle(int position) {
return tab_title_list.get(position>tab_title_list.size()-1?tab_title_list.size()-1:position);
}
// 动态设置我们标题的方法
public void setPageTitle(int position, String title)
{
if(position >= 0 && position < tab_title_list.size())
{
tab_title_list.set(position, title);
notifyDataSetChanged();
}
}
}
StringTabAdapter:
package com.example.testcsdnproject.adapter;
import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.example.testcsdnproject.R;
import java.util.List;
/**
* 灰底白字圆角的tab标签适配器
*/
public class StringTabAdapter extends BaseQuickAdapter<String, BaseViewHolder> {
public StringTabAdapter(@Nullable List<String> data) {
super(R.layout.item_string_tab,data);
}
@Override
protected void convert(BaseViewHolder helper, String item) {
helper.setText(R.id.rtv_tab,item);
}
}
item_string_tab.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_margin="5dp">
<TextView
android:id="@+id/rtv_tab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标签"
android:textSize="14sp"
android:textColor="#FFFDFDFD"
android:singleLine="true"
android:background="#FF333333"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:paddingLeft="9dp"
android:paddingRight="9dp"
/>
</LinearLayout>
自定义View 三角形TriangleView 通过direction设置三角形方向:
package com.example.testcsdnproject.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import com.example.testcsdnproject.DensityUtil;
import com.example.testcsdnproject.R;
/**
* 自定义View 三角形
* 通过direction设置三角形方向
*/
public class TriangleView extends View {
private static final int TOP = 0;
private static final int BOTTOM = 1;
private static final int RIGHT = 2;
private static final int LEFT = 3;
private static final int DEFUALT_WIDTH = 10;
private static final int DEFUALT_HEIGHT = 6;
private static final int DEFUALT_COLOR = R.color.color80000000;
private Paint mPaint;
private int mColor;
private int mWidth;
private int mHeight;
private int mDirection;
private Path mPath;
public TriangleView(final Context context) {
this(context, null);
}
public TriangleView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public TriangleView(final Context context, final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.TriangleView, 0, 0);
mColor = typedArray.getColor(R.styleable.TriangleView_trv_color, ContextCompat.getColor(getContext(), DEFUALT_COLOR));
mDirection = typedArray.getInt(R.styleable.TriangleView_trv_direction, mDirection);
typedArray.recycle();
mPaint.setColor(mColor);
}
private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
mPath = new Path();
mDirection = TOP;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = MeasureSpec.getSize(widthMeasureSpec);
mHeight = MeasureSpec.getSize(heightMeasureSpec);
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (mWidth == 0 || widthMode != MeasureSpec.EXACTLY) {
mWidth = (int) DensityUtil.dp2px(getContext(),DEFUALT_WIDTH);
}
if (mHeight == 0 || heightMode != MeasureSpec.EXACTLY) {
mHeight = (int) DensityUtil.dp2px(getContext(),DEFUALT_HEIGHT);
}
setMeasuredDimension(mWidth, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
switch (mDirection) {
case TOP:
mPath.moveTo(0, mHeight);
mPath.lineTo(mWidth, mHeight);
mPath.lineTo(mWidth / 2, 0);
break;
case BOTTOM:
mPath.moveTo(0, 0);
mPath.lineTo(mWidth / 2, mHeight);
mPath.lineTo(mWidth, 0);
break;
case RIGHT:
mPath.moveTo(0, 0);
mPath.lineTo(0, mHeight);
mPath.lineTo(mWidth, mHeight / 2);
break;
case LEFT:
mPath.moveTo(0, mHeight / 2);
mPath.lineTo(mWidth, mHeight);
mPath.lineTo(mWidth, 0);
break;
default:
break;
}
mPath.close();
canvas.drawPath(mPath, mPaint);
}
}
styles.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TriangleView">
<attr name="trv_color" format="color" />
<attr name="trv_direction">
<enum name="top" value="0" />
<enum name="bottom" value="1" />
<enum name="right" value="2" />
<enum name="left" value="3" />
</attr>
</declare-styleable>
<style name="TabText" parent="TextAppearance.AppCompat">
<item name="android:textStyle">bold</item>
<item name="android:textSize">14sp</item>
</style>
</resources>
DensityUtil:
package com.example.testcsdnproject;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.graphics.Point;
import android.os.Build;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;
/**
* Created by :colin
* time :2018/1/10.
* description:屏幕相关
*/
public class DensityUtil {
private static int[] deviceWidthHeight = new int[2];
public static int[] getDeviceInfo(Context context) {
if ((deviceWidthHeight[0] == 0) && (deviceWidthHeight[1] == 0)) {
DisplayMetrics metrics = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay()
.getMetrics(metrics);
deviceWidthHeight[0] = metrics.widthPixels;
deviceWidthHeight[1] = metrics.heightPixels;
}
return deviceWidthHeight;
}
public static int getWidth(Context context){
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
int width = wm.getDefaultDisplay().getWidth();
return width;
}
public static int getHeight(Context context){
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
int width = wm.getDefaultDisplay().getHeight();
return width;
}
/**
*
* @param context 上下文
* @param dpValue dp数值
* @return dp to px
*/
public static int dp2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 获取屏幕尺寸
*/
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
public static Point getScreenSize(Context context){
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2){
return new Point(display.getWidth(), display.getHeight());
}else{
Point point = new Point();
display.getSize(point);
return point;
}
}
/**
*
* @param context 上下文
* @param pxValue px的数值
* @return px to dp
*/
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
/**
* 获取状态栏高度
*
* @param context context
* @return 状态栏高度
*/
public static int getStatusBarHeight(Context context) {
// 获得状态栏高度
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
return context.getResources().getDimensionPixelSize(resourceId);
}
}