牛X素材推荐之TriangleRectangleLabelView
来源:互联网 发布:淘客帝国源码 编辑:程序博客网 时间:2024/04/29 19:09
转载请注明出处:王亟亟的大牛之路
Git上看到一个比较给力的自定义展示标签的View,分享给大家TriangleRectangleLabelView。然后根据原作者的代码我会对其中运用的一些技术点加以解释,在此在此谢谢原作者的开源精神
先贴一下运行效果:
包结构
整体实现还是很轻量级的,只有一个实现的class和attrs来处理初始化。
TriangleRectangleLabelView(作者已详细标注)
public class TriangleRectangleLabelView extends TextView { private static final String TAG = TriangleRectangleLabelView.class.getSimpleName(); private static final int DEFAULT_BG_COLOR = 0xff41c7cd; private static final int DEFAULT_CIRCLE_COLOR = 0xffffffff; private static final int DEFAULT_LINE_COLOR = 0xfffb9ece; private static final int DEFAULT_HEIGHT = 30;//dp private static final int DEFAULT_WIDTH = 70;//dp private static final int DEFAULT_ROUND_RECT_RADIUS = 8;//px private static final int DEFAULT_ROUND_RECT_WIDTH = 8;//px private Paint mBgPaint; private Paint mCirclePaint; private Paint mLinePaint; private int mRoundRectWidth = DEFAULT_ROUND_RECT_WIDTH;//圆角矩形宽度 private int mRoundRectRadius = DEFAULT_ROUND_RECT_RADIUS;//矩形圆角半径 private int mCircleRadius = 8;//圆点半径 private int mCircleSpaceRectangle = 16;//圆点到标签的间隔 private int mSpaceHeight = 8;//背景上下间隔 private int mLineWidth = 2;//竖线宽度 private int mBgColor = DEFAULT_BG_COLOR;//背景颜色 private int mLineColor = DEFAULT_LINE_COLOR;//竖直线颜色 private int mCircleColor = DEFAULT_CIRCLE_COLOR;//圆点颜色 private LINE_MODE mLineMode = LINE_MODE.MIDDLE;//竖线模式 private boolean isShowLine = false;//是否显示竖线 private boolean isShowCircle = true;//是否显示圆点 private boolean isDrawRoundRect = true;//是否显示矩形圆角 private boolean isLeft = true;//是否箭头朝左显示 private boolean isFirstPadding = true; public static enum LINE_MODE { START, MIDDLE, END } public TriangleRectangleLabelView(Context context) { this(context, null); } public TriangleRectangleLabelView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public TriangleRectangleLabelView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initAttrs(attrs); init(); } private void initAttrs(AttributeSet attrs) { if (attrs != null) { TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.TriangleRectangleLabelView); mBgColor = a.getColor(R.styleable.TriangleRectangleLabelView_trlvBgColor, mBgColor); mLineColor = a.getColor(R.styleable.TriangleRectangleLabelView_trlvLineColor, mLineColor); mCircleColor = a.getColor(R.styleable.TriangleRectangleLabelView_trlvCircleColor, mCircleColor); isLeft = a.getBoolean(R.styleable.TriangleRectangleLabelView_trlvIsLeft, isLeft); isShowLine = a.getBoolean(R.styleable.TriangleRectangleLabelView_trlvIsShowLine, isShowLine); isShowCircle = a.getBoolean(R.styleable.TriangleRectangleLabelView_trlvIsShowCircle, isShowCircle); isDrawRoundRect = a.getBoolean(R.styleable.TriangleRectangleLabelView_trlvIsDrawRoundRect, isDrawRoundRect); mCircleRadius = a.getDimensionPixelSize(R.styleable.TriangleRectangleLabelView_trlvCircleRadius, mCircleRadius); mCircleSpaceRectangle = a.getDimensionPixelSize(R.styleable.TriangleRectangleLabelView_trlvCircleSpaceRectangle, mCircleSpaceRectangle); mLineWidth = a.getDimensionPixelSize(R.styleable.TriangleRectangleLabelView_trlvLineWidth, mLineWidth); mRoundRectWidth = a.getDimensionPixelSize(R.styleable.TriangleRectangleLabelView_trlvRoundRectWidth, mRoundRectWidth); mRoundRectRadius = a.getDimensionPixelSize(R.styleable.TriangleRectangleLabelView_trlvRoundRectRadius, mRoundRectRadius); DisplayMetrics dm = getResources().getDisplayMetrics(); int minHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_HEIGHT, dm); int minWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_WIDTH, dm); setMinHeight(minHeight); setMinWidth(minWidth); a.recycle(); } } private void init() { mBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mBgPaint.setStrokeWidth(4); mBgPaint.setStyle(Paint.Style.FILL); mBgPaint.setColor(mBgColor); mBgPaint.setAntiAlias(true); mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mCirclePaint.setStrokeWidth(1); mCirclePaint.setStyle(Paint.Style.FILL); mCirclePaint.setColor(mCircleColor); mCirclePaint.setAntiAlias(true); mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mLinePaint.setStrokeWidth(mLineWidth); mLinePaint.setStyle(Paint.Style.FILL); mLinePaint.setColor(mLineColor); mLinePaint.setAntiAlias(true); } /** * 设置圆角矩形宽度 * * @param roundRectWidth px */ public void setRoundRectWidth(int roundRectWidth) { this.mRoundRectWidth = roundRectWidth; postInvalidate(); } /** * 设置圆角矩形圆角半径 * * @param roundRectRadius px */ public void setRoundRectRadius(int roundRectRadius) { this.mRoundRectRadius = roundRectRadius; postInvalidate(); } public void setBgColor(int color) { mBgColor = color; mBgPaint.setColor(mBgColor); postInvalidate(); } public void setLineColor(int color) { mLineColor = color; mLinePaint.setColor(getContext().getResources().getColor(mLineColor)); postInvalidate(); } /** * 设置竖直线模式 * * @param lineMode LINE_MODE: START, MIDDLE, END */ public void setLineMode(LINE_MODE lineMode) { this.mLineMode = lineMode; postInvalidate(); } /** * 是否箭头朝向左 * * @param isLeft true:left false:right */ public void setLeft(boolean isLeft) { this.isLeft = isLeft; postInvalidate(); } /** * 设置 View 上下间距 * * @param spaceHeight px */ public void setSpaceHeight(int spaceHeight) { this.mSpaceHeight = spaceHeight; isFirstPadding = true; postInvalidate(); } /** * 设置原点与标签的间隔 * * @param circleSpaceRectangle px */ public void setCircleSpaceRectangle(int circleSpaceRectangle) { this.mCircleSpaceRectangle = circleSpaceRectangle; isFirstPadding = true; postInvalidate(); } /** * 设置原点半径 * * @param circleRadius px */ public void setCircleRadius(int circleRadius) { this.mCircleRadius = circleRadius; isFirstPadding = true; postInvalidate(); } /** * 设置分割线宽度 * * @param lineWidth px */ public void setLineWidth(int lineWidth) { this.mLineWidth = lineWidth; mLinePaint.setStrokeWidth(mLineWidth); postInvalidate(); } public void setShowLine(boolean isShowLine) { this.isShowLine = isShowLine; postInvalidate(); } public void setShowCircle(boolean isShowCircle) { this.isShowCircle = isShowCircle; postInvalidate(); } public void setDrawRoundRect(boolean isDrawRoundRect) { this.isDrawRoundRect = isDrawRoundRect; postInvalidate(); } @Override protected void onDraw(Canvas canvas) { drawBackground(canvas); super.onDraw(canvas); } private void drawBackground(Canvas canvas) { int height = getHeight(); int width = getWidth(); Log.d(TAG, "height = " + height); Log.d(TAG, "width = " + width); Log.d(TAG, "isFirstPadding = " + isFirstPadding); //-------------------Set Text Padding Begin----------------------------// if (isFirstPadding) { int paddingLeft = mCircleRadius * 2 + mCircleSpaceRectangle + (height - mSpaceHeight) / 2 + 2; setPadding(isLeft ? paddingLeft : mRoundRectWidth, mSpaceHeight + 4, isLeft ? mRoundRectWidth + 4 : paddingLeft, mSpaceHeight + 4); setGravity(Gravity.CENTER_VERTICAL); isFirstPadding = false; } //-------------------Set Text Padding End----------------------------// //-------------------Draw Line Begin----------------------------// int startLineX = isShowLine ? (isLeft ? mCircleRadius : width - mCircleRadius) : 0; if (isShowLine) { if (mLineMode == LINE_MODE.START) { canvas.drawLine(startLineX, height / 2, startLineX, height, mLinePaint); } else if (mLineMode == LINE_MODE.MIDDLE) { canvas.drawLine(startLineX, height, startLineX, 0, mLinePaint); } else if (mLineMode == LINE_MODE.END) { canvas.drawLine(startLineX, height / 2, startLineX, 0, mLinePaint); } } //-------------------Draw Line End----------------------------// //-------------------Draw Circle Begin----------------------------// int startCircleX = isShowCircle ? (isLeft ? mCircleRadius : width - mCircleRadius) : 0; if (isShowCircle) { canvas.drawCircle(startCircleX, height / 2, mCircleRadius, mCirclePaint); } //-------------------Draw Circle End----------------------------// //-------------------Draw RoundRect Begin----------------------------// int roundLeft = isDrawRoundRect ? (isLeft ? width - mRoundRectWidth : 0) : 0; int roundRight = isDrawRoundRect ? (isLeft ? width : mRoundRectWidth) : 0; if (isDrawRoundRect) { //draw RoundRect RectF rect = new RectF(); rect.left = roundLeft; rect.top = mSpaceHeight; rect.right = roundRight; rect.bottom = height - mSpaceHeight; canvas.drawRoundRect(rect, mRoundRectRadius, mRoundRectRadius, mBgPaint); } //-------------------Draw RoundRect End----------------------------// //-------------------Draw Triangle And Rectangle Begin----------------------------// if (isLeft) { //draw Triangle And Rectangle int startX = mCircleSpaceRectangle + 2 * mCircleRadius; Point a = new Point(startX, height / 2); Point b = new Point(startX + (height - mSpaceHeight) / 2, height - mSpaceHeight); Point c = new Point(width - (isDrawRoundRect ? mRoundRectWidth / 2 : 0), height - mSpaceHeight); Point d = new Point(width - (isDrawRoundRect ? mRoundRectWidth / 2 : 0), mSpaceHeight); Point e = new Point(startX + (height - mSpaceHeight) / 2, mSpaceHeight); Point f = new Point(startX, height / 2); Path path = new Path(); path.moveTo(a.x, a.y); path.lineTo(b.x, b.y); path.lineTo(c.x, c.y); path.lineTo(d.x, d.y); path.lineTo(e.x, e.y); path.lineTo(f.x, f.y); canvas.drawPath(path, mBgPaint); } else { //draw Triangle And Rectangle int startX = width - (mCircleSpaceRectangle + 2 * mCircleRadius); Point a = new Point(startX, height / 2); Point b = new Point(startX - (height - mSpaceHeight) / 2, height - mSpaceHeight); Point c = new Point((isDrawRoundRect ? mRoundRectWidth / 2 : 0), height - mSpaceHeight); Point d = new Point((isDrawRoundRect ? mRoundRectWidth / 2 : 0), mSpaceHeight); Point e = new Point(startX - (height - mSpaceHeight) / 2, mSpaceHeight); Point f = new Point(startX, height / 2); Path path = new Path(); path.moveTo(a.x, a.y); path.lineTo(b.x, b.y); path.lineTo(c.x, c.y); path.lineTo(d.x, d.y); path.lineTo(e.x, e.y); path.lineTo(f.x, f.y); canvas.drawPath(path, mBgPaint); } //-------------------Draw Triangle And Rectangle End----------------------------// }}
分析:
如果要设置组合标签,就是都连在一起的需要做一下操作
((TriangleRectangleLabelView)findViewById(R.id.trlv1)).setLineMode(TriangleRectangleLabelView.LINE_MODE.START); ((TriangleRectangleLabelView)findViewById(R.id.trlv2)).setLineMode(TriangleRectangleLabelView.LINE_MODE.MIDDLE); ((TriangleRectangleLabelView)findViewById(R.id.trlv3)).setLineMode(TriangleRectangleLabelView.LINE_MODE.MIDDLE); ((TriangleRectangleLabelView)findViewById(R.id.trlv4)).setLineMode(TriangleRectangleLabelView.LINE_MODE.END);
在initAttrs()方法内对标签内容进行了各种初始化,如果你的产品并不需要加以变化,可以写死,那还省蛮多代码的。
这个自定义View牛X的就是在drawBackground()方法中的画布和逻辑计算,写的还是相当缜密的。
重点提拎一下屏幕参数类DisplayMetics
这个类是干嘛的?
提供了一种关于显示的通用信息,如显示大小,分辨率和字体。
这个类怎么初始化?
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics;
而我们的自定义控件使用的是 DisplayMetrics dm = getResources().getDisplayMetrics();
补充下获取的参数是以像素为单位(Pixel) ,“像素”所指的是“绝对像素”而非“相对像素”。
通过 DisplayMetrics的 toString()方法可以获取到 DisplayMetrics的大部分 fields信息,如下是在分辨率为 480x320情况下的一些输出信息:
然后就是一系列的单位了
与分辨率无关的度量单位可以解决这一问题,Android支持下列所有单位:
px(像素):屏幕上的点。
in(英寸):长度单位。
mm(毫米):长度单位。
pt(磅):1/72英寸。
dp(与密度无关的像素):一种基于屏幕密度的抽象单位。在每英寸160点的显示器上,1dp = 1px。
dip:与dp相同,多用于android/ophone示例中。
sp(与刻度无关的像素):与dp类似,但是可以根据用户的字体大小首选项进行缩放。
因为网络问题,也贴下别的 需要的文件,源码就不传了
主布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity" android:orientation="vertical" android:gravity="center_horizontal" android:background="@drawable/bg"> <labelviewdemo.wjj.com.labelviewdemo.TriangleRectangleLabelView android:id="@+id/trv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#fff" android:singleLine="true" android:text="Nice" app:trlvIsLeft="false" app:trlvCircleRadius="4dp" android:textSize="16sp" android:layout_marginLeft="48dp" android:layout_marginTop="50dp" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> <labelviewdemo.wjj.com.labelviewdemo.TriangleRectangleLabelView xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#fff" android:singleLine="true" android:text="Label 1" android:layout_below="@id/trv_name" android:textSize="16sp" android:layout_toEndOf="@id/trv_name" android:layout_toRightOf="@id/trv_name" app:trlvIsLeft="true" app:trlvCircleRadius="4dp" app:trlvBgColor="#ff000000" app:trlvCircleColor="#ffffff" app:trlvRoundRectRadius="12dp" app:trlvRoundRectWidth="10dp" /> <labelviewdemo.wjj.com.labelviewdemo.TriangleRectangleLabelView android:id="@+id/trlv1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#fff" android:singleLine="true" android:text="标签1" android:textSize="16sp" android:layout_centerVertical="true" android:layout_toEndOf="@id/trv_name" android:layout_toRightOf="@id/trv_name" app:trlvIsLeft="true" app:trlvCircleRadius="4dp" app:trlvBgColor="#72ddbf" app:trlvCircleColor="#95e8cd" app:trlvIsShowLine="true" /> <labelviewdemo.wjj.com.labelviewdemo.TriangleRectangleLabelView android:id="@+id/trlv2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#fff" android:singleLine="true" android:text="标签2" android:textSize="16sp" android:layout_below="@id/trlv1" android:layout_toEndOf="@id/trv_name" android:layout_toRightOf="@id/trv_name" app:trlvIsLeft="true" app:trlvCircleRadius="4dp" app:trlvBgColor="#a596d6" app:trlvCircleColor="#b6b2db" app:trlvIsShowLine="true" /> <labelviewdemo.wjj.com.labelviewdemo.TriangleRectangleLabelView android:id="@+id/trlv3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#fff" android:singleLine="true" android:text="标签3" android:textSize="16sp" android:layout_below="@id/trlv2" android:layout_toEndOf="@id/trv_name" android:layout_toRightOf="@id/trv_name" app:trlvIsLeft="true" app:trlvCircleRadius="4dp" app:trlvBgColor="#efbe78" app:trlvCircleColor="#f1cf9e" app:trlvIsShowLine="true" /> <labelviewdemo.wjj.com.labelviewdemo.TriangleRectangleLabelView android:id="@+id/trlv4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#fff" android:singleLine="true" android:text="标签4" android:textSize="16sp" android:layout_below="@id/trlv3" android:layout_toEndOf="@id/trv_name" android:layout_toRightOf="@id/trv_name" app:trlvIsLeft="true" app:trlvCircleRadius="4dp" app:trlvBgColor="#f96bbc" app:trlvCircleColor="#fc9dcf" app:trlvIsShowLine="true" /></RelativeLayout>
MainActivity
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ((TriangleRectangleLabelView)findViewById(R.id.trlv1)).setLineMode(TriangleRectangleLabelView.LINE_MODE.START); ((TriangleRectangleLabelView)findViewById(R.id.trlv2)).setLineMode(TriangleRectangleLabelView.LINE_MODE.MIDDLE); ((TriangleRectangleLabelView)findViewById(R.id.trlv3)).setLineMode(TriangleRectangleLabelView.LINE_MODE.MIDDLE); ((TriangleRectangleLabelView)findViewById(R.id.trlv4)).setLineMode(TriangleRectangleLabelView.LINE_MODE.END); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); }}
谢谢大家
- 牛X素材推荐之TriangleRectangleLabelView
- 牛X素材推荐之StackOverView
- 牛X素材推荐之MaterialTextField
- 牛X素材推荐之BannerTime
- 素材推荐
- 素材网站->推荐
- 游戏素材网站推荐!!!
- UI设计素材资源网站推荐
- ENVI5.x入门学习素材包分享
- 《多情恨》素材之十二
- Android开发之素材获取
- 素材
- 素材
- 素材
- 素材
- 素材
- 素材
- Mac OS X必备APP推荐之二
- 应用系统Url交互之数据加密
- 【4】Windows客户端C/C++编程规范“建议”——表达式和运算
- 【Unity】小地图遮罩Shader
- 从a站点跳转到b站点,通过url的参数判断是否让该用户选择身份
- CSS中常用到的清除浮动
- 牛X素材推荐之TriangleRectangleLabelView
- iOS开发UI篇—使用UItableview完成一个简单的QQ好友列表(二)
- [oracle学习笔记]之一:sql/plus基础操作
- 匿名内部类
- 在Tomcat 6下运行正常,但是在Tomcat 7下异常。
- 使用docker-compose快速安装redmine
- tcpdump抓包分析详解
- VC6调试时,如何查看vector中的内容?
- shell脚本报错 /bin/bash^M: bad interpreter