Android模块化编程——炫酷小巧多功能Button

前段时间客户需求,要加几个按钮,包括清理缓存,关于,设置,定位等。可是界面已经做好了,再重新布局界面,很麻烦。所以做了这么个小Button。在此分享,供大家学习。下面是几张截图,动画效果没工具保存,是依次展开的。文末附有源码下载链接。

首先上自定义布局文件:ComposerLayout.java

package com.example.button;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

@SuppressLint("ViewConstructor")
public class ComposerLayout extends RelativeLayout {

	public static byte RIGHTBOTTOM = 1, CENTERBOTTOM = 2, LEFTBOTTOM = 3,
			LEFTCENTER = 4, LEFTTOP = 5, CENTERTOP = 6, RIGHTTOP = 7,
			RIGHTCENTER = 8;
	private boolean hasInit = false;
	private boolean areButtonsShowing = false;
	private Context mycontext;
	private ImageView cross;
	private RelativeLayout rlButton;
	private Animations myani;
	private LinearLayout[] llayouts;
	private int duretime = 300;

	public ComposerLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		this.mycontext = context;
	}

	public ComposerLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.mycontext = context;
	}

	public ComposerLayout(Context context) {
		super(context);
		this.mycontext = context;
	}

	/**
	 * 初始化
	 *
	 * @param imgResId
	 *            子按钮图片drawable的id
	 * @param showhideButtonId
	 *            主按鈕drawable的id
	 * @param crossId
	 *            主按鈕上面十字片drawable的id
	 * @param pCode
	 *            位置代碼,例如“右上角”ALIGN_PARENT_BOTTOM|ALIGN_PARENT_RIGHT
	 * @param radius
	 *
	 * @param durationMillis
	 *            动画耗时
	 */
	public void init(int[] imgResId, int showhideButtonId, int crossId,
			byte pCode, int radius, final int durationMillis) {
		duretime = durationMillis;
		int align1 = 12, align2 = 14;
		if (pCode == RIGHTBOTTOM) { // 右下角
			align1 = ALIGN_PARENT_RIGHT;
			align2 = ALIGN_PARENT_BOTTOM;
		} else if (pCode == CENTERBOTTOM) {// 中下
			align1 = CENTER_HORIZONTAL;
			align2 = ALIGN_PARENT_BOTTOM;
		} else if (pCode == LEFTBOTTOM) { // 左下角
			align1 = ALIGN_PARENT_LEFT;
			align2 = ALIGN_PARENT_BOTTOM;
		} else if (pCode == LEFTCENTER) { // 左中
			align1 = ALIGN_PARENT_LEFT;
			align2 = CENTER_VERTICAL;
		} else if (pCode == LEFTTOP) { // 左上角
			align1 = ALIGN_PARENT_LEFT;
			align2 = ALIGN_PARENT_TOP;
		} else if (pCode == CENTERTOP) { // 中上
			align1 = CENTER_HORIZONTAL;
			align2 = ALIGN_PARENT_TOP;
		} else if (pCode == RIGHTTOP) { // 右上角
			align1 = ALIGN_PARENT_RIGHT;
			align2 = ALIGN_PARENT_TOP;
		} else if (pCode == RIGHTCENTER) { // 右中
			align1 = ALIGN_PARENT_RIGHT;
			align2 = CENTER_VERTICAL;
		}
		// 处理半径
		RelativeLayout.LayoutParams thislps = (LayoutParams) this
				.getLayoutParams();
		Bitmap mBottom = BitmapFactory.decodeResource(mycontext.getResources(),
				imgResId[0]);
		if (pCode == CENTERBOTTOM || pCode == CENTERTOP) {
			if (thislps.width != -1
					&& thislps.width != -2
					&& thislps.width < (radius + mBottom.getWidth() + radius * 0.1) * 2) {
				thislps.width = (int) ((radius * 1.1 + mBottom.getWidth()) * 2);
			}
		} else {
			if (thislps.width != -1
					&& thislps.width != -2
					&& thislps.width < radius + mBottom.getWidth() + radius
							* 0.1) {
				thislps.width = (int) (radius * 1.1 + mBottom.getWidth());
			}
		}
		if (pCode == LEFTCENTER || pCode == RIGHTCENTER) {
			if (thislps.height != -1
					&& thislps.height != -2
					&& thislps.height < (radius + mBottom.getHeight() + radius * 0.1) * 2) {
				thislps.width = (int) ((radius * 1.1 + mBottom.getHeight()) * 2);
			}
		} else {
			if (thislps.height != -1
					&& thislps.height != -2
					&& thislps.height < radius + mBottom.getHeight() + radius
							* 0.1) {
				thislps.height = (int) (radius * 1.1 + mBottom.getHeight());
			}
		}
		this.setLayoutParams(thislps);
		RelativeLayout rl1 = new RelativeLayout(mycontext);// 包含若干子按鈕

		rlButton = new RelativeLayout(mycontext); // 主按扭
		llayouts = new LinearLayout[imgResId.length];
		// N个子按鈕
		for (int i = 0; i < imgResId.length; i++) {
			ImageView img = new ImageView(mycontext);// 子按扭圖片

			img.setImageResource(imgResId[i]);
			LinearLayout.LayoutParams llps = new LinearLayout.LayoutParams(
					LinearLayout.LayoutParams.WRAP_CONTENT,
					LinearLayout.LayoutParams.WRAP_CONTENT);

			img.setLayoutParams(llps);
			llayouts[i] = new LinearLayout(mycontext);// 子按鈕
			llayouts[i].setId(100 + i);// 随便设个id,方便onclick的时候识别。随便设,如果发现同其他控件沖突就自行改一下。
			llayouts[i].addView(img);

			RelativeLayout.LayoutParams rlps = new RelativeLayout.LayoutParams(
					RelativeLayout.LayoutParams.WRAP_CONTENT,
					RelativeLayout.LayoutParams.WRAP_CONTENT);
			rlps.alignWithParent = true;
			rlps.addRule(align1, RelativeLayout.TRUE);
			rlps.addRule(align2, RelativeLayout.TRUE);
			llayouts[i].setLayoutParams(rlps);
			llayouts[i].setVisibility(View.INVISIBLE);// 此处不能为GONE
			rl1.addView(llayouts[i]);
		}
		RelativeLayout.LayoutParams rlps1 = new RelativeLayout.LayoutParams(
				RelativeLayout.LayoutParams.FILL_PARENT,
				RelativeLayout.LayoutParams.FILL_PARENT);
		rlps1.alignWithParent = true;
		rlps1.addRule(align1, RelativeLayout.TRUE);
		rlps1.addRule(align2, RelativeLayout.TRUE);
		rl1.setLayoutParams(rlps1);

		RelativeLayout.LayoutParams buttonlps = new RelativeLayout.LayoutParams(
				RelativeLayout.LayoutParams.WRAP_CONTENT,
				RelativeLayout.LayoutParams.WRAP_CONTENT);
		buttonlps.alignWithParent = true;
		buttonlps.addRule(align1, RelativeLayout.TRUE);
		buttonlps.addRule(align2, RelativeLayout.TRUE);
		rlButton.setLayoutParams(buttonlps);
		rlButton.setBackgroundResource(showhideButtonId);
		cross = new ImageView(mycontext);
		cross.setImageResource(crossId);
		RelativeLayout.LayoutParams crosslps = new RelativeLayout.LayoutParams(
				RelativeLayout.LayoutParams.WRAP_CONTENT,
				RelativeLayout.LayoutParams.WRAP_CONTENT);
		crosslps.alignWithParent = true;
		crosslps.addRule(CENTER_IN_PARENT, RelativeLayout.TRUE);
		cross.setLayoutParams(crosslps);
		rlButton.addView(cross);
		myani = new Animations(rl1, pCode, radius);
		rlButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if (areButtonsShowing) {
					myani.startAnimationsOut(duretime);
					cross.startAnimation(Animations.getRotateAnimation(-270,
							0, duretime));
				} else {
					myani.startAnimationsIn(duretime);
					cross.startAnimation(Animations.getRotateAnimation(0,
							-270, duretime));
				}
				areButtonsShowing = !areButtonsShowing;
			}
		});

		cross.startAnimation(Animations.getRotateAnimation(0, 360, 200));
		this.addView(rl1);
		this.addView(rlButton);
		hasInit = true;

	}

	public void collapse() {
		myani.startAnimationsOut(duretime);
		cross.startAnimation(Animations.getRotateAnimation(-270, 0, duretime));
		areButtonsShowing = false;
	}

	public void expand() {
		myani.startAnimationsIn(duretime);
		cross.startAnimation(Animations.getRotateAnimation(0, -270, duretime));
		areButtonsShowing = true;
	}

	public boolean isInit() {
		return hasInit;
	}

	public boolean isShow() {
		return areButtonsShowing;
	}

	/**
	 * 设置各子按钮OnClick事件
	 */
	public void setButtonsOnClickListener(final OnClickListener l) {

		if (llayouts != null) {
			for (int i = 0; i < llayouts.length; i++) {
				if (llayouts[i] != null)
					llayouts[i].setOnClickListener(new OnClickListener() {

						@Override
						public void onClick(final View view) {
							//此处添加其他事件比如按钮增大或者缩回菜单
							collapse();
							l.onClick(view);
						}

					});
			}
		}
	}
}

这里自定义了一个BaseActivity,使用BaseActivity的好处不用我说了吧:

package com.example.button;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;

public abstract class BaseActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setView();
		initView();
		setListener();
		initData();
	}

	@Override
	protected void onResume() {
		super.onResume();
	}

	@Override
	protected void onPause() {
		super.onPause();
	}

	/**
	 * 设置布局文件
	 */
	public abstract void setView();

	/**
	 * 初始化布局文件中的控件
	 */
	public abstract void initView();

	/**
	 * 设置控件的监听
	 */
	public abstract void setListener();

	private void initData() {
		String appID = "wx88818f8c48a95eb4";
	}
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
	    super.onActivityResult(requestCode, resultCode, data);
	}

}

动画设置类,Animations,这里用了一个开源动画库nineoldandroids.jar。下载文末原代码中有

package com.example.button;

import static com.nineoldandroids.view.ViewPropertyAnimator.animate;

import java.util.ArrayList;
import java.util.List;

import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.LinearLayout;

import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.Animator.AnimatorListener;
import com.nineoldandroids.view.ViewPropertyAnimator;

public class Animations {
	public final int R; // 半径
	public static byte RIGHTBOTTOM = 1, CENTERBOTTOM = 2, LEFTBOTTOM = 3,
			LEFTCENTER = 4, LEFTTOP = 5, CENTERTOP = 6, RIGHTTOP = 7,
			RIGHTCENTER = 8;

	private int pc; // 位置代号
	private ViewGroup clayout; // 父layout
	private final int amount; // 有幾多個按鈕
	private double fullangle = 180.0;// 在幾大嘅角度內排佈
	private byte xOri = 1, yOri = 1; // x、y值嘅方向,即系向上還是向下
	private boolean isOpen = false;// 记录是已经打开还是关闭
	private List<ViewPropertyAnimator> viewAnimators = new ArrayList<ViewPropertyAnimator>();

	/**
	 * 構造函數
	 *
	 * @param comlayout
	 *            包裹彈出按鈕嘅layout
	 * @param poscode
	 *            位置代號,分別對應RIGHTBOTTOM、CENTERBOTTOM、LEFTBOTTOM、LEFTCENTER、
	 *            LEFTTOP、CENTERTOP、RIGHTTOP、RIGHTCENTER
	 * @param radius
	 *            半徑
	 */
	public Animations(ViewGroup comlayout, int poscode, int radius) {
		this.pc = poscode;
		this.clayout = comlayout;
		this.amount = clayout.getChildCount();
		this.R = radius;

		// 初始化动画,每个view对应一个animator
		for (int i = 0; i < amount; i++) {
			View childAt = clayout.getChildAt(i);
			ViewPropertyAnimator anim = animate(childAt);
			viewAnimators.add(anim);
		}

		if (poscode == RIGHTBOTTOM) { // 右下角
			fullangle = 90;
			xOri = -1;
			yOri = -1;
		} else if (poscode == CENTERBOTTOM) {// 中下
			fullangle = 180;
			xOri = -1;
			yOri = -1;
		} else if (poscode == LEFTBOTTOM) { // 左下角
			fullangle = 90;
			xOri = 1;
			yOri = -1;
		} else if (poscode == LEFTCENTER) { // 左中
			fullangle = 180;
			xOri = 1;
			yOri = -1;
		} else if (poscode == LEFTTOP) { // 左上角
			fullangle = 90;
			xOri = 1;
			yOri = 1;
		} else if (poscode == CENTERTOP) { // 中上
			fullangle = 180;
			xOri = -1;
			yOri = 1;
		} else if (poscode == RIGHTTOP) { // 右上角
			fullangle = 90;
			xOri = -1;
			yOri = 1;
		} else if (poscode == RIGHTCENTER) { // 右中
			fullangle = 180;
			xOri = -1;
			yOri = -1;
		}
	}

	private class AnimListener implements AnimatorListener {

		private View target;

		public AnimListener(View _target) {
			target = _target;
		}

		@Override
		public void onAnimationStart(Animator animation) {

		}

		@Override
		public void onAnimationEnd(Animator animation) {
			if (!isOpen) {
				target.setVisibility(View.INVISIBLE);
			}
		}

		@Override
		public void onAnimationCancel(Animator animation) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onAnimationRepeat(Animator animation) {
			// TODO Auto-generated method stub

		}
	}

	/**
	 * 彈幾個按鈕出嚟
	 *
	 * @param durationMillis
	 *            用幾多時間
	 */
	public void startAnimationsIn(int durationMillis) {
		isOpen = true;
		for (int i = 0; i < clayout.getChildCount(); i++) {
			final LinearLayout inoutimagebutton = (LinearLayout) clayout
					.getChildAt(i);

			double offangle = fullangle / (amount - 1);

			final double deltaY, deltaX;
			if (pc == LEFTCENTER || pc == RIGHTCENTER) {
				deltaX = Math.sin(offangle * i * Math.PI / 180) * R;
				deltaY = Math.cos(offangle * i * Math.PI / 180) * R;
			} else {
				deltaY = Math.sin(offangle * i * Math.PI / 180) * R;
				deltaX = Math.cos(offangle * i * Math.PI / 180) * R;
			}

			ViewPropertyAnimator viewPropertyAnimator = viewAnimators.get(i);
			viewPropertyAnimator.setListener(null);

			inoutimagebutton.setVisibility(View.VISIBLE);
			viewPropertyAnimator.x(
					(float) (inoutimagebutton.getLeft() + xOri * deltaX)).y(
					(float) (inoutimagebutton.getTop() + yOri * deltaY));

		}
	}

	/**
	 * 收埋幾個按鈕入去
	 *
	 * @param durationMillis
	 *            用幾多時間
	 */
	public void startAnimationsOut(int durationMillis) {
		isOpen = false;
		for (int i = 0; i < clayout.getChildCount(); i++) {
			final LinearLayout inoutimagebutton = (LinearLayout) clayout
					.getChildAt(i);
			ViewPropertyAnimator viewPropertyAnimator = viewAnimators.get(i);
			viewPropertyAnimator.setListener(null);
			viewPropertyAnimator.x((float) inoutimagebutton.getLeft()).y(
					(float) inoutimagebutton.getTop());
			viewPropertyAnimator
					.setListener(new AnimListener(inoutimagebutton));

		}

	}

	/**
	 *
	 */
	public int getPosCode() {
		return this.pc;
	}

	/**
	 * 自转函数
	 *
	 * @param fromDegrees
	 *            从几多度
	 * @param toDegrees
	 *            到几多度
	 * @param durationMillis
	 *            m
	 */
	public static Animation getRotateAnimation(float fromDegrees,
			float toDegrees, int durationMillis) {
		RotateAnimation rotate = new RotateAnimation(fromDegrees, toDegrees,
				Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
				0.5f);
		rotate.setDuration(durationMillis);
		rotate.setFillAfter(true);
		return rotate;
	}
}

主Activity:TestActivity

package com.example.button;

import android.view.View;
import android.view.View.OnClickListener;
import android.widget.RelativeLayout;
import android.widget.Toast;

public class TestActivity extends BaseActivity {

	private ComposerLayout clayout;
	@Override
	public void setView() {
		setContentView(R.layout.activity_main);

	}

	@Override
	public void initView() {
		// 引用控件
		clayout = (ComposerLayout) findViewById(R.id.test);
		clayout.init(new int[] { R.drawable.composer_camera,
				R.drawable.composer_music, R.drawable.composer_place,
				R.drawable.composer_sleep, R.drawable.composer_thought,
				R.drawable.composer_with }, R.drawable.composer_button,
				R.drawable.composer_icn_plus, ComposerLayout.RIGHTCENTER, 180,
				300);

	}

	@Override
	public void setListener() {
		// 点击事件监听,100+0对应composer_camera,100+1对应composer_music……如此类推你有机个按钮就加几个按钮都行。
				OnClickListener clickit = new OnClickListener() {
					@Override
					public void onClick(View v) {
						if (v.getId() == 100 + 0) {
							Toast.makeText(TestActivity.this, "测试A", 0).show();
						} else if (v.getId() == 100 + 1) {
							Toast.makeText(TestActivity.this, "测试B...", 0).show();
						} else if (v.getId() == 100 + 2) {
							Toast.makeText(TestActivity.this, "测试C...", 0).show();
						} else if (v.getId() == 100 + 3) {
							Toast.makeText(TestActivity.this, "测试D...", 0).show();
						} else if (v.getId() == 100 + 4) {
							Toast.makeText(TestActivity.this, "测试E...", 0).show();
						} else if (v.getId() == 100 + 5) {
							Toast.makeText(TestActivity.this, "测试F..", 0).show();
						}
					}
				};
				clayout.setButtonsOnClickListener(clickit);

				RelativeLayout rl = (RelativeLayout) findViewById(R.id.rlparent);
				rl.setOnClickListener(new OnClickListener() {
					@Override
					public void onClick(View v) {
						// TODO Auto-generated method stub
						Toast.makeText(TestActivity.this, "父控件可以点击的哦!!!", 0).show();
						System.out.println("父控件可以点击。");
					}
				});

	}

}

接下来是布局文件activity_main:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/rlparent"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#ABCDEF" >

    <com.example.button.ComposerLayout
        android:id="@+id/test"
        android:layout_width="20dp"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true" >
    </com.example.button.ComposerLayout>

</RelativeLayout>

文中按钮图片资源:

下载nineoldandroids-2.4.0.jar

下载Demo

时间: 2025-01-01 22:18:08

Android模块化编程——炫酷小巧多功能Button的相关文章

Android模块化编程之引用本地的aar

随着项目越来越多,代码的复用就变得异常重要,这时候就要进行模块化编程,就是把一些通用的组件或者类库做成单独的模块,其他项目直接进行引用就好.针对Android开发最常见的就是Android Library,在Gradle出现之前引用Android Library的方式也很繁琐,但是有了Gradle一切变得非常简单方便. aar 何为aar?大家都知道jar文件把,如果你有一个Android Library项目,可以很容易的导出jar文件,然后在其他项目中很方便的引用,aar和jar类似,区别就是

视频编辑SDK---我们只提供API,任你自由设计炫酷的功能

做视频APP, 在于差异化,个性的APP; 你做一个别人一样功能的APP, 很难占领市场. 基于此.我们的SDK完全以API的形式,至于界面和操作炫酷的功能,任你自由发挥, 视频编辑:即类似秒拍,美拍,快手,小影等APP中对音视频做剪切/裁剪/分离/合并/标记/贴纸/叠加/滤镜等操作. 我们有Android版本基本视频编辑SDK: https://github.com/LanSoSdk/LanSoEditor_common 主要功能有: 1,使用在音视频的: 裁剪,剪切,分离,合并,转换,拼接,

超酷的计步器APP——炫酷功能实现,自定义水波纹特效、自定义炫酷开始按钮、属性动画的综合体验

超酷的计步器APP--炫酷功能实现,自定义水波纹特效.自定义炫酷开始按钮.属性动画的综合体验 好久没写博客了,没给大家分享技术了,真是有些惭愧.这段时间我在找工作,今年Android的行情也不怎么好,再加上我又是一个应届生,所以呢,更是不好找了.但是我没有放弃,经过自己的不懈努力,还是找到了自己喜欢的Android工作,心里的一块石头终于落下了.但是迎接我来的是更多的挑战,我喜欢那种不断的挑战自我,在困难中让自己变得更强大的感觉.相信阳光总在风雨后,因为每一个你不满意的现在,都有一个你没有努力的

Android实现炫酷SVG动画效果

svg是目前十分流行的图像文件格式了,svg严格来说应该是一种开放标准的矢量图形语言,使用svg格式我们可以直接用代码来描绘图像,可以用任何文字处理工具打开svg图像,通过改变部分代码来使图像具有交互功能,并可以随时插入到HTML中通过浏览器(如火狐浏览器)来观看.使用svg格式可让你设计激动人心的.高分辨率的Web图形页面. svg格式具备目前网络流行的jpg和png等格式无法具备的优势:可以任意放大图形显示,但绝不会以牺牲图像质量为代价;可在svg图像中保留可编辑和可搜寻的状态;平均来讲,s

Android例子源码--炫酷的仪表盘网速测试

Android例子源码--炫酷的仪表盘网速测试 本项目是一个仪表盘网速测试的安卓版本,原理就是下载一个固定大小的文件来进行测试,可以测试当前速度,和平均速度,跟电脑上的测速差不多,有一个很精美的仪表盘效果.本项目编码UTF-8默认编译版本4.2.2. 下载地址:http://www.devstore.cn/code/info/100.html 运行截图:    干货推荐: Google Android 官方培训教程中文版 第一行代码 Android编程权威指南 疯狂Android讲义(第2版)

Android基础控件——ImageView的自定义,巧用Matrix实现图片不变形的炫酷PK条

前言 在开发中常常会遇到PK条制作,如果在PK条中是纯色的情况下,比较好办,如下:我们通常会设置其权重进行更新两个PK条的进度,实现起来也简单 //更新PkBar宽度比例 private void updateLayoutParams(float ratio) { LinearLayout.LayoutParams paramsLeft = (LinearLayout.LayoutParams) mLeftBar.getLayoutParams(); LinearLayout.LayoutPar

开源分享三(炫酷的Android Loading动画)

开源分享三(炫酷的Android Loading动画) 分享GitHub上的一些Loading,为了提升产品用户体验,一个好的Loading必然是不可缺少的,对于一些耗时需要用户等待的页面来说会转移用户注意力,不会显得那么烦躁,所以你可以看到市面上一些App中的各种各样的Loading动画,从这些实现思路上可以打开你们自己的思维,没准也会有创新的Loading动画出现. android-shapeLoadingView 新版58同城加载页面动画. CircleProgress 一个效果很酷炫很创

Android 自定义控件玩转字体变色 打造炫酷ViewPager指示器

Android 自定义控件玩转字体变色 打造炫酷ViewPager指示器

Android 教你打造炫酷的ViewPagerIndicator 不仅仅是高仿MIUI

1.概述 哈,今天给大家带来一个ViewPagerIndicator的制作,相信大家在做tabIndicator的时候,大多数人都用过 TabPageIndicator,并且很多知名APP都使用过这个开源的指示器.大家有没有想过如何自己去实现这样的一个指示器,并且代码会有多复杂 呢~~~今天,我就带领大家来从无到有的实现这样一个指示器,当然了,不准备一模一样,搞得没有创新似的,再看标题,跟MIUI相关,所以我们准备做一个 特性与TabPageIndicator一致的,但是样子和MIUI的Tab一