Setting下的自定义控件LinearColorBar
来源:互联网 发布:linux 清空arp缓存 编辑:程序博客网 时间:2024/04/29 18:23
版本:1.0
日期:2014.3.21
版权:© 2013,2014 kince 转载注明出处
Setting应用下使用了不少自定义控件,比如这些效果:
流量显示
电量显示
存储空间显示
先介绍最后这个存储空间显示的LinearColorBar,通过名字就可以看出是是继承于LinearLayout,确实也是如此。分析一下这个效果,在控件的左边显示已经使用了多少空间,右边是所有可用空间。上面还有所显示的类别,RAM。当然最主要的还是那个环形的效果。看一下LinearColorBar的实现代码:
/****/package com.example.settingscustomviewdemo.widget;import android.content.Context;import android.graphics.Canvas;import android.graphics.LinearGradient;import android.graphics.Paint;import android.graphics.Path;import android.graphics.Rect;import android.graphics.Shader;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.widget.LinearLayout;public class LinearColorBar extends LinearLayout { static final int LEFT_COLOR = 0xff0099cc; static final int MIDDLE_COLOR = 0xff0099cc; static final int RIGHT_COLOR = 0xff888888; private float mRedRatio; private float mYellowRatio; private float mGreenRatio; private boolean mShowingGreen; final Rect mRect = new Rect(); final Paint mPaint = new Paint(); int mLastInterestingLeft, mLastInterestingRight; int mLineWidth; final Path mColorPath = new Path(); final Path mEdgePath = new Path(); final Paint mColorGradientPaint = new Paint(); final Paint mEdgeGradientPaint = new Paint(); public LinearColorBar(Context context, AttributeSet attrs) { super(context, attrs); setWillNotDraw(false); mPaint.setStyle(Paint.Style.FILL); mColorGradientPaint.setStyle(Paint.Style.FILL); mColorGradientPaint.setAntiAlias(true); mEdgeGradientPaint.setStyle(Paint.Style.STROKE); mLineWidth = getResources().getDisplayMetrics().densityDpi >= DisplayMetrics.DENSITY_HIGH ? 2 : 1; mEdgeGradientPaint.setStrokeWidth(mLineWidth); mEdgeGradientPaint.setAntiAlias(true); } public void setRatios(float red, float yellow, float green) { mRedRatio = red; mYellowRatio = yellow; mGreenRatio = green; invalidate(); } public void setShowingGreen(boolean showingGreen) { if (mShowingGreen != showingGreen) { mShowingGreen = showingGreen; updateIndicator(); invalidate(); } } private void updateIndicator() { int off = getPaddingTop() - getPaddingBottom(); if (off < 0) off = 0; mRect.top = off; mRect.bottom = getHeight(); if (mShowingGreen) { mColorGradientPaint.setShader(new LinearGradient( 0, 0, 0, off-2, RIGHT_COLOR&0xffffff, RIGHT_COLOR, Shader.TileMode.CLAMP)); } else { mColorGradientPaint.setShader(new LinearGradient( 0, 0, 0, off-2, MIDDLE_COLOR&0xffffff, MIDDLE_COLOR, Shader.TileMode.CLAMP)); } mEdgeGradientPaint.setShader(new LinearGradient( 0, 0, 0, off/2, 0x00a0a0a0, 0xffa0a0a0, Shader.TileMode.CLAMP)); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); updateIndicator(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int width = getWidth(); int left = 0; int right = left + (int)(width*mRedRatio); int right2 = right + (int)(width*mYellowRatio); int right3 = right2 + (int)(width*mGreenRatio); int indicatorLeft, indicatorRight; if (mShowingGreen) { indicatorLeft = right2; indicatorRight = right3; } else { indicatorLeft = right; indicatorRight = right2; } if (mLastInterestingLeft != indicatorLeft || mLastInterestingRight != indicatorRight) { mColorPath.reset(); mEdgePath.reset(); if (indicatorLeft < indicatorRight) { final int midTopY = mRect.top; final int midBottomY = 0; final int xoff = 2; mColorPath.moveTo(indicatorLeft, mRect.top); mColorPath.cubicTo(indicatorLeft, midBottomY, -xoff, midTopY, -xoff, 0); mColorPath.lineTo(width+xoff-1, 0); mColorPath.cubicTo(width+xoff-1, midTopY, indicatorRight, midBottomY, indicatorRight, mRect.top); mColorPath.close(); final float lineOffset = mLineWidth+.5f; mEdgePath.moveTo(-xoff+lineOffset, 0); mEdgePath.cubicTo(-xoff+lineOffset, midTopY, indicatorLeft+lineOffset, midBottomY, indicatorLeft+lineOffset, mRect.top); mEdgePath.moveTo(width+xoff-1-lineOffset, 0); mEdgePath.cubicTo(width+xoff-1-lineOffset, midTopY, indicatorRight-lineOffset, midBottomY, indicatorRight-lineOffset, mRect.top); } mLastInterestingLeft = indicatorLeft; mLastInterestingRight = indicatorRight; } if (!mEdgePath.isEmpty()) { canvas.drawPath(mEdgePath, mEdgeGradientPaint); canvas.drawPath(mColorPath, mColorGradientPaint); } if (left < right) { mRect.left = left; mRect.right = right; mPaint.setColor(LEFT_COLOR); canvas.drawRect(mRect, mPaint); width -= (right-left); left = right; } right = right2; if (left < right) { mRect.left = left; mRect.right = right; mPaint.setColor(MIDDLE_COLOR); canvas.drawRect(mRect, mPaint); width -= (right-left); left = right; } right = left + width; if (left < right) { mRect.left = left; mRect.right = right; mPaint.setColor(RIGHT_COLOR); canvas.drawRect(mRect, mPaint); } }}
读完源码看一下它的变量,画笔Paint不说了,用于设置笔触的样式。除此之外就是Rect和Path了,关于这两个类的功能,其实从字面意思大体可以猜得出来。Rect是用于绘制矩形的,Path则用于画线,包括直线、二次曲线、三次曲线等。那从这两个类的用途就不难猜出它们各自在LinaerColorBar中的作用了,Rect用于绘制使用了多少空间的进度条,Path则是用于绘制那个二次型图案。
然后直接进入Draw()方法,开始初始化一些变量,这些变量之后会使用到。
int width = getWidth();//获取组件宽度 int left = 0; // int right = left + (int) (width * mRedRatio);// int right2 = right + (int) (width * mYellowRatio);// int right3 = right2 + (int) (width * mGreenRatio);// int indicatorLeft, indicatorRight; if (mShowingGreen) { indicatorLeft = right2; indicatorRight = right3; } else { indicatorLeft = right; indicatorRight = right2; }
这几个right值就是根据设置的空间使用大小转换而来的,其实就是控件宽度的比例值,在画Rect的时候传入即可。接着往下看,
mColorPath.moveTo(indicatorLeft, mRect.top); mColorPath.cubicTo(indicatorLeft, midBottomY, -xoff, midTopY, -xoff, 0); mColorPath.lineTo(width + xoff - 1, 0); mColorPath.cubicTo(width + xoff - 1, midTopY, indicatorRight, midBottomY, indicatorRight, mRect.top); mColorPath.close();
这段代码就是用于画这个弧形的,首先moveTo()方法,将画笔移动到这个点,然后使用cubicTo方法画一个二次曲线,因为画笔设置了Paint.Style.FILL,所以看起来像是一片的效果,而不是直线。
final float lineOffset = mLineWidth + .5f; mEdgePath.moveTo(-xoff + lineOffset, 0); mEdgePath.cubicTo(-xoff + lineOffset, midTopY, indicatorLeft + lineOffset, midBottomY, indicatorLeft + lineOffset, mRect.top); mEdgePath.moveTo(width + xoff - 1 - lineOffset, 0); mEdgePath.cubicTo(width + xoff - 1 - lineOffset, midTopY, indicatorRight - lineOffset, midBottomY, indicatorRight - lineOffset, mRect.top);
这段代码用于在之前的基础上描边,
这样,弧形效果就实现了。然后就是下面的矩形了,
if (left < right) { mRect.left = left; mRect.right = right; mPaint.setColor(LEFT_COLOR); canvas.drawRect(mRect, mPaint); width -= (right - left); left = right; } right = right2; if (left < right) { mRect.left = left; mRect.right = right; mPaint.setColor(MIDDLE_COLOR); canvas.drawRect(mRect, mPaint); width -= (right - left); left = right; } right = left + width; if (left < right) { mRect.left = left; mRect.right = right; mPaint.setColor(RIGHT_COLOR); canvas.drawRect(mRect, mPaint); }
这个就相对简单了,用Rect直接画就行了。
总结:这个自定义的控件是继承于系统原有的容器控件LinearLayout,为什么要选择LinearLayout呢,其实也可以是RelativeLayout,容器控件都可以,只要把那三个TextView安放好位置就行。然后就是绘图了,这里结合了Paint、Path、Rect以及Canvas的使用,其实自定义控件很多时候就是使用这几个类,所以对这几个类的掌握尤为重要。那最后就是逻辑,这也是很重要的一个部分,对于效果我们可能想到使用什么类去实现,那对于效果的控制与变化就需要依靠逻辑了。
demo下载
5 0
- Setting下的自定义控件LinearColorBar
- 一个好用的Setting开关(自定义组合控件)
- Win8 下的自定义控件
- wince下, c# 自定义的 MessageBox 控件
- conf下setting.xml的核心配置
- xcode 自定义build Setting
- VS2008下web页面上传图片的自定义控件源码
- 在iOS 5下自定义控件的外观
- 自定义View四--搜索框下的建议标签控件
- 歌词显示控件的实现下——自定义View
- maven中使动态使用自定义的setting.
- window下制作自定义控件
- Android下自定义IP控件
- 自定义控件的自定义属性
- 自定义控件的自定义属性
- 自定义控件--自定义控件的属性
- 自定义控件的自定义的属性attrs.xml下的declare-styleable中format详解
- 自定义控件的自定义的属性attrs.xml下的declare-styleable中format详解
- 手游公司日记(2)
- C++--异常(Exceptions)
- 第三周作业
- CentOS6.5 安装Zend Studio 以及 破解
- 第三周作业
- Setting下的自定义控件LinearColorBar
- Cocos2d-JS-v3.0-alpha环境配置,用Cocos2d console维护使用
- 贝贝走进ku6eyh我在在雅虎的是
- Python中dict字典使用方法
- SQL SERVER 2008 自动备份图解教程
- TWaver HTML5学习笔记 —— 拓扑右键菜单
- 制作ios-framework
- UVa 755 487-3279
- (一)游戏实现的原理和机制