广告
返回顶部
首页 > 资讯 > 移动开发 >Android自定义TabLayout效果
  • 631
分享到

Android自定义TabLayout效果

tablayoutAndroid 2022-06-06 11:06:42 631人浏览 安东尼
摘要

周末就要到了,今天项目中遇到这样一个Tab,选中tab的背景是个圆角矩形,方向指向器没有了,这样普通的TabLayout不能满足我的要求,可能会想到动态的去设置选中Tab的背景

周末就要到了,今天项目中遇到这样一个Tab,选中tab的背景是个圆角矩形,方向指向器没有了,这样普通的TabLayout不能满足我的要求,可能会想到动态的去设置选中Tab的背景不就可以了,但是那样的话太生硬了,没有动画效果,其实想想也还比较简单,今天就简单的说一说这个YzzTab。效果如下图:

这里是四个Tab,一版只显示3个,这里假设有num个Tab,当滑动到第3个时,这里就需要考虑如何让TabLayout和指示器一起移动呢?


@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
 if (positionOffset>1){
  return;
 }
 int leftCop = (int) (positionOffset*(getMeasuredWidth()/mMaxLineNum)+position*getMeasuredWidth()/mMaxLineNum);
 if (leftCop!=leftForTabLayout){
  //这里要做判断是否滑动,当选择的位置大于TabLayout中显示的最大数-1时,会向左右滑动,指示器也会
  //跟这滑动,相对静止,否则指示器滑动,Tab布局不移动
  if (position>=mMaxLineNum-1) {
   scrollContent += leftCop - leftForTabLayout;
   scrollTo(scrollContent, 0);
   //这里要重新layout
   update();
  }
  leftForTabLayout = leftCop;
  invalidate();
 }
}

首先,在ViewPage的监听中,positionOffset有时候可能大于1,这点需要注意的,当两次left的坐标相等 时,我们就不进行绘制了,接下来就是
如何确定left的值了,对于这点我也想了很久,最后终于得出结论:

int leftCop = (int) (positionOffset*(getMeasuredWidth()/mMaxLineNum)+position*getMeasuredWidth()/mMaxLineNum);

因为当positionOffset的值在向右滑动80%左右的时候getCurrentItem()的值会发生变化,这点可以试验一下,所以getCurrentItem()方法不能用了,只能用参数position.Layout滑动的实际代码注释很详细了,我就不再阐述了,可以试试。在布局滑动了以后,必须要layout,不然View的属性不会变,点击没法应,但是也可以不更新,动态的告诉用户点击的真是Tab,这样也可以。


 private void update() {
 for (int i = 0; i <mChildCount ; i++) {
  View v = getChildAt(i);
  v.setLeft(v.getLeft()+scrollContent);
 }
 //必须调用,不然不会重新layout
 requestLayout();
}

接下来就是绘制了,ViewGroup是默认不调用onDraw(canvas canvas)方法的,原因很简单,ViewGroup是个容器,主要作用是起承载作用,绘画就交给子View了,但是还是有办法让其调用该方法的,如下:

 setWillNotDraw(false);

这就告诉该容器,需要绘制;

接下来就是绘制指向器和选中背景了,一个圆角矩形和一条线,比较简单,我就不再详细说明了。


@Override
protected void onDraw(Canvas canvas) {
 //left = getMeasuredWidth() / mChildCount * mSelectPosition;
 super.onDraw(canvas);
 mPaint.setColor(Color.GREEN);
 int top = getMeasuredHeight() / 4;
 int right = leftForTabLayout + getMeasuredWidth() / mMaxLineNum;
 int bottom = getMeasuredHeight() - getMeasuredHeight() / 4;
 RectF rectF = new RectF(leftForTabLayout, top, right, bottom);
 mPaint.setAntiAlias(true);
 mPaint.setStyle(Paint.Style.FILL);
 canvas.drawRoundRect(rectF, 10, 10, mPaint);
 mPaint.setColor(Color.RED);
 mPaint.setStrokeWidth(5);
 canvas.drawLine(leftForTabLayout,getMeasuredHeight()-5,right,getMeasuredHeight()-5,mPaint);
}

接下来介绍建与ViewPager建立关联的方法


 
public void setUpWithViewPager(ViewPager viewPager) {
 mViewPager = viewPager;
 mChildCount = viewPager.getAdapter().getCount();
 mSelectPosition = viewPager.getCurrentItem();
 viewPager.setOnPageChangeListener(this);
}

初始化的方法



private void init() {
 setWillNotDraw(false);
 mPaint = new Paint();
 for (int i = 0; i < mChildCount; i++) {
  final TextView tv = new TextView(getContext());
  int w = getMeasuredWidth()/mMaxLineNum;
  LinearLayout.LayoutParams lp = new LayoutParams(w, ViewGroup.LayoutParams.MATCH_PARENT);
  tv.setText("tab" + i);
  tv.setGravity(Gravity.CENTER);
  tv.setLayoutParams(lp);
  final int finalI = i;
  tv.setOnClickListener(new OnClickListener() {
   @Override
   public void onClick(View v) {
    if (monTabSelecterListener != null){
     monTabSelecterListener.selecter(finalI,tv);
    }
   }
  });
  addView(tv);
 }
}

这里只是很简单的加了几个TextView进去,也可以弄个方法,通过用户动态添加自己想要的View,都可以实现的。至于监听的话就很简单了.上面已经写到了。

YzzTab的代码


package a6he.Android.yzz.com.mytablayout;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.Switch;
import android.widget.TextView;

public class YzzTab extends LinearLayout implements ViewPager.OnPageChangeListener {
private ViewPager mViewPager;
private Paint mPaint;
//tab的数量
private int mChildCount;
//tab选中的位置
private int mSelectPosition;
//绘制指向器的左顶点
private int leftForTabLayout = 0;
private int leftForInvidator = 0;
private int mMaxLineNum = 3;
private int scrollContent = 0;
private onTabSelecterListener monTabSelecterListener;
public YzzTab(Context context) {
 super(context);
}
public YzzTab(Context context, AttributeSet attrs) {
 super(context, attrs);
}
public YzzTab(Context context, AttributeSet attrs, int defStyleAttr) {
 super(context, attrs, defStyleAttr);
}
@Override
protected void onFinishInflate() {
 super.onFinishInflate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 init();
}

public void setUpWithViewPager(ViewPager viewPager) {
 mViewPager = viewPager;
 mChildCount = viewPager.getAdapter().getCount();
 mSelectPosition = viewPager.getCurrentItem();
 viewPager.setOnPageChangeListener(this);
}

private void init() {
 setWillNotDraw(false);
 mPaint = new Paint();
 for (int i = 0; i < mChildCount; i++) {
  final TextView tv = new TextView(getContext());
  int w = getMeasuredWidth()/mMaxLineNum;
  LinearLayout.LayoutParams lp = new LayoutParams(w, ViewGroup.LayoutParams.MATCH_PARENT);
  tv.setText("tab" + i);
  tv.setGravity(Gravity.CENTER);
  tv.setLayoutParams(lp);
  final int finalI = i;
  tv.setOnClickListener(new OnClickListener() {
   @Override
   public void onClick(View v) {
    if (monTabSelecterListener != null){
     monTabSelecterListener.selecter(finalI,tv);
    }
   }
  });
  addView(tv);
 }
}
@Override
protected void onDraw(Canvas canvas) {
 //left = getMeasuredWidth() / mChildCount * mSelectPosition;
 super.onDraw(canvas);
 mPaint.setColor(Color.GREEN);
 int top = getMeasuredHeight() / 4;
 int right = leftForTabLayout + getMeasuredWidth() / mMaxLineNum;
 int bottom = getMeasuredHeight() - getMeasuredHeight() / 4;
 RectF rectF = new RectF(leftForTabLayout, top, right, bottom);
 mPaint.setAntiAlias(true);
 mPaint.setStyle(Paint.Style.FILL);
 canvas.drawRoundRect(rectF, 10, 10, mPaint);
 mPaint.setColor(Color.RED);
 mPaint.setStrokeWidth(5);
 canvas.drawLine(leftForTabLayout,getMeasuredHeight()-5,right,getMeasuredHeight()-5,mPaint);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
 if (positionOffset>1){
  return;
 }
 int leftCop = (int) (positionOffset*(getMeasuredWidth()/mMaxLineNum)+position*getMeasuredWidth()/mMaxLineNum);
 if (leftCop!=leftForTabLayout){
  //这里要做判断是否滑动,当选择的位置大于TabLayout中显示的最大数-1时,会向左右滑动,指示器也会
  //跟这滑动,相对静止,否则指示器滑动,Tab布局不移动
  if (position>=mMaxLineNum-1) {
   scrollContent += leftCop - leftForTabLayout;
   scrollTo(scrollContent, 0);
   //这里要重新layout
   update();
  }
  leftForTabLayout = leftCop;
  invalidate();
 }
}
private void update() {
 for (int i = 0; i <mChildCount ; i++) {
  View v = getChildAt(i);
  v.setLeft(v.getLeft()+scrollContent);
 }
 requestLayout();
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
 switch (state){
 }
}
public void setmMaxLineNum(int mMaxLineNum) {
 this.mMaxLineNum = mMaxLineNum;
}
public void setonTabSelecterListener(onTabSelecterListener monTabSelecterListener) {
 this.monTabSelecterListener = monTabSelecterListener;
}
interface onTabSelecterListener{
 void selecter(int position,View view);
 }
}

好啦,就介绍这么多,还有待完善,继续封装,完成更强大的功能。

您可能感兴趣的文章:Android TabLayout(选项卡布局)简单用法实例分析android TabLayout使用方法详解Android 中TabLayout自定义选择背景滑块的实例代码Android中TabLayout结合ViewPager实现页面切换效果Android design包自定义tablayout的底部导航栏的实现方法Android TabLayout实现京东详情效果Android中TabLayout+ViewPager 简单实现app底部Tab导航栏AndroidUI组件SlidingTabLayout实现ViewPager页滑动效果Android中TabLayout结合ViewPager实现页面切换TabLayout使用方法详解


--结束END--

本文标题: Android自定义TabLayout效果

本文链接: https://www.lsjlt.com/news/28290.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android自定义TabLayout效果
    周末就要到了,今天项目中遇到这样一个Tab,选中tab的背景是个圆角矩形,方向指向器没有了,这样普通的TabLayout不能满足我的要求,可能会想到动态的去设置选中Tab的背景...
    99+
    2022-06-06
    tablayout Android
  • Android完全自定义下划线的TabLayout
    一 介绍: 导航功能几乎是所有的APP都具备的基础功能之一,Android系统提供了TabLayout+ViewPager的组合来实现该功能。再...
    99+
    2022-06-06
    自定义 tablayout 下划线 Android
  • Android自定义日历效果
    要实现Android自定义日历效果,可以按照以下步骤进行:1. 创建一个自定义的CalendarView控件,继承自ViewGrou...
    99+
    2023-08-15
    Android
  • Android TabLayout 自定义样式及使用详解
    目录基本使用XML静态设置TabItem联动ViewPager2动态设置TabItem1. Activity布局代码2. 创建三个Fragment给ViewPager2设置3. Fr...
    99+
    2022-11-13
  • Android自定义加载框效果
    本文实例为大家分享了Android自定义加载框效果的具体代码,供大家参考,具体内容如下 效果图 菊花图标(mipmap-xxhdpi) 加载框圆角背景drawable <...
    99+
    2022-11-12
  • Android自定义轮播图效果
    本文实例为大家分享了Android自定义轮播图效果的具体代码,供大家参考,具体内容如下 概述 1、写一个布局,其中有ViewPager,TextView,LinearLayout. ...
    99+
    2022-11-12
  • Android自定义弹框Dialog效果
    本文实例为大家分享了Android自定义弹框Dialog效果的具体代码,供大家参考,具体内容如下 1.dialog_delete.xml <xml version=...
    99+
    2022-11-13
  • Android Switch自定义实现IOS效果
    先看下效果图 自定义View public class Seniorswitch extends Switch { priva...
    99+
    2022-06-06
    switch IOS Android
  • Android自定义仿微信PopupWindow效果
    给大家分享一个高仿微信的PopupWindow、就是微信的扫一扫那个功能窗口、下面有应用运行效果图、更加直观的展示了Demo的效果、源代码是通过两种方法实现的、大家可以下载源代...
    99+
    2022-06-06
    popupwindow Android
  • Android如何自定义按钮效果
    安卓原生的按钮是多么丑,效果是多么单调,大家也是有目共睹的。 要做一个APP少不了使用按钮,一个好看的按钮少不了好看的效果和外表,这次主要跟大家讲讲如何用drawable的x...
    99+
    2022-06-06
    自定义 按钮 Android
  • Android自定义Material进度条效果
    首先看下效果图 布局文件: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/andr...
    99+
    2022-06-06
    material Android
  • Android自定义悬浮按钮效果
    本文实例为大家分享了Android自定义悬浮按钮效果的具体代码,供大家参考,具体内容如下 以下:内容没有参考,写的也是一个比较简单的例子,主要就是应用切换前后台时会显示/隐藏悬浮窗。...
    99+
    2022-11-12
  • Android studio自定义对话框效果
    本文实例为大家分享了Android studio自定义对话框效果的具体代码,供大家参考,具体内容如下 实现步骤: 第一步:自定义.xml布局文件 <?xml ver...
    99+
    2022-11-12
  • Android自定义弹出框dialog效果
    项目要用到弹出框,还要和苹果的样式一样(Android真是没地位),所以就自己定义了一个,不是很像(主要是没图),但是也还可以。废话不多说了,直接上代码先看布局文件<?xml version="1.0" encoding="u...
    99+
    2023-05-31
    android 弹出框 dialog
  • Android自定义弹窗提示效果
    本文实例为大家分享了Android 自定义弹窗提示的具体代码,供大家参考,具体内容如下 Java文件: private void showSetDeBugDialog() { ...
    99+
    2022-11-12
  • Android怎么自定义日历效果
    要自定义Android日历效果,可以使用Android中的CalendarView或者自定义View来实现。以下是一种简单的自定义日...
    99+
    2023-08-16
    Android
  • android自定义进度条移动效果
    本文实例为大家分享了android实现进度条移动效果的具体代码,供大家参考,具体内容如下 自定义进度条,效果如下: CustomViewActivity.java public...
    99+
    2022-11-12
  • Android自定义圆形进度条效果
    本文实例为大家分享了Android自定义圆形进度条效果的具体代码,供大家参考,具体内容如下 1 控件 RoundProgress package listview.tianhet...
    99+
    2022-11-12
  • Android自定义StickinessView粘性滑动效果
    design包的出现,Android界面发生了巨大变化,各种滑动配合的效果,下面我就粘性滑动中的一种进行自定义,效果图如下: 大家看到效果了,这里我是继承了LinerL...
    99+
    2022-06-06
    动效 Android
  • android自定义View滑动删除效果
    View滑动删除效果图 实现功能 1、可以向左滑动,右侧出现删除 2、向左滑动如果删除出现一大半,松手打开删除,反之关闭删除 3、应用场景    ...
    99+
    2022-06-06
    view Android
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作