android进阶-Android控件架构与自定义控件详解(二)
2017-10-08 17:02
399 查看
**
1.1弧形展示
1.2 音频条形状
**
**
1.重新View绘制新的控件
**1.1弧形展示
public class CircleProgressView extends View { private int mMeasureHeigth; private int mMeasureWidth; private Paint mCirclePaint; private float mCircleXY; private float mRadius; private Paint mArcPaint; private RectF mArcRectF; private float mSweepAngle; private float mSweepValue = 66; private Paint mTextPaint; private String mShowText; private float mShowTextSize; public CircleProgressView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public CircleProgressView(Context context, AttributeSet attrs) { super(context, attrs); } public CircleProgressView(Context context) { super(context); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { mMeasureWidth = MeasureSpec.getSize(widthMeasureSpec); mMeasureHeigth = MeasureSpec.getSize(heightMeasureSpec); setMeasuredDimension(mMeasureWidth, mMeasureHeigth); initView(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 绘制圆 canvas.drawCircle(mCircleXY, mCircleXY, mRadius, mCirclePaint); // 绘制弧线 canvas.drawArc(mArcRectF, 270, mSweepAngle, false, mArcPaint); // 绘制文字 canvas.drawText(mShowText, 0, mShowText.length(), mCircleXY, mCircleXY + (mShowTextSize / 4), mTextPaint); } private void initView() { float length = 0; if (mMeasureHeigth >= mMeasureWidth) { length = mMeasureWidth; } else { length = mMeasureHeigth; } //圆 mCircleXY = length / 2; mRadius = (float) (length * 0.5 / 2); mCirclePaint = new Paint(); mCirclePaint.setAntiAlias(true); mCirclePaint.setColor(getResources().getColor( android.R.color.holo_blue_bright)); //弧线 mArcRectF = new RectF( (float) (length * 0.1), (float) (length * 0.1), (float) (length * 0.9), (float) (length * 0.9)); mSweepAngle = (mSweepValue / 100f) * 360f; mArcPaint = new Paint(); mArcPaint.setAntiAlias(true); mArcPaint.setColor(getResources().getColor( android.R.color.holo_blue_bright)); mArcPaint.setStrokeWidth((float) (length * 0.1)); mArcPaint.setStyle(Style.STROKE); mShowText = setShowText(); mShowTextSize = setShowTextSize(); mTextPaint = new Paint(); mTextPaint.setTextSize(mShowTextSize); mTextPaint.setTextAlign(Paint.Align.CENTER); } private float setShowTextSize() { this.invalidate(); return 50; } private String setShowText() { this.invalidate(); return "Android Skill"; } public void forceInvalidate() { this.invalidate(); } //设置不同状态值 public void setSweepValue(float sweepValue) { if (sweepValue != 0) { mSweepValue = sweepValue; } else { mSweepValue = 25; } this.invalidate(); } }
1.2 音频条形状
demo下载地址
public class VolumeView extends View { private int mWidth; private int mRectWidth; private int mRectHeight; private Paint mPaint; private int mRectCount; private int offset = 5; private double mRandom; private LinearGradient mLinearGradient; public VolumeView(Context context) { super(context); initView(); } public VolumeView(Context context, AttributeSet attrs) { super(context, attrs); initView(); } public VolumeView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(); } private void initView() { mPaint = new Paint(); mPaint.setColor(Color.BLUE); mPaint.setStyle(Paint.Style.FILL); mRectCount = 12; } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mWidth = getWidth(); mRectHeight = getHeight(); mRectWidth = (int) (mWidth * 0.6 / mRectCount); mLinearGradient = new LinearGradient( 0, 0, mRectWidth, mRectHeight, Color.YELLOW, Color.BLUE, Shader.TileMode.CLAMP); mPaint.setShader(mLinearGradient); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); for (int i = 0; i < mRectCount; i++) { mRandom = Math.random(); float currentHeight = (float) (mRectHeight * mRandom); canvas.drawRect( (float) (mWidth * 0.4 / 2 + mRectWidth * i + offset), currentHeight, (float) (mWidth * 0.4 / 2 + mRectWidth * (i + 1)), mRectHeight, mPaint); } postInvalidateDelayed(300); } }
**
2.自定义ViewGroup
****
demo下载地址
**public class MyScrollView extends ViewGroup { private int mScreenHeight; private Scroller mScroller; private int mLastY; private int mStart; private int mEnd; public MyScrollView(Context context) { super(context); initView(context); } public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); initView(context); } public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(context); } private void initView(Context context) { WindowManager wm = (WindowManager) context.getSystemService( Context.WINDOW_SERVICE); DisplayMetrics dm = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(dm); mScreenHeight = dm.heightPixels; mScroller = new Scroller(context); } /** * 确定整个ViewGroup的高度,即子view进行放置位置的设定 * 每一个View占一屏的高度,因此整个ViewGroup的高度寄子VIEW的个数乘以屏幕的高度 * @param changed * @param l * @param t * @param r * @param b */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int childCount = getChildCount(); // 设置ViewGroup的高度 MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams(); mlp.height = mScreenHeight * childCount; setLayoutParams(mlp); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); if (child.getVisibility() != View.GONE) { child.layout(l, i * mScreenHeight, r, (i + 1) * mScreenHeight); } } } /** * 在ViewGroup能够滚动之前,需要先放置好它的子view * 使用遍历的方式来通知子View对自身进行测量 * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int count = getChildCount(); for (int i = 0; i < count; ++i) { View childView = getChildAt(i); measureChild(childView, widthMeasureSpec, heightMeasureSpec); } } /** * 给viewGroup添加响应事件 * 在onTouchEvent()的ACTION_MOVE事件中,只要使用scrollBy(0,dy) * @param event * @return */ @Override public boolean onTouchEvent(MotionEvent event) { int y = (int) event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mLastY = y; mStart = getScrollY(); break; case MotionEvent.ACTION_MOVE: if (!mScroller.isFinished()) { mScroller.abortAnimation(); } int dy = mLastY - y; if (getScrollY() < 0) { dy = 0; } if (getScrollY() > getHeight() - mScreenHeight) { dy = 0; } scrollBy(0, dy); mLastY = y; break; case MotionEvent.ACTION_UP: int dScrollY = checkAlignment(); if (dScrollY > 0) { if (dScrollY < mScreenHeight / 3) { mScroller.startScroll( 0, getScrollY(), 0, -dScrollY); } else { mScroller.startScroll( 0, getScrollY(), 0, mScreenHeight - dScrollY); } } else { if (-dScrollY < mScreenHeight / 3) { mScroller.startScroll( 0, getScrollY(), 0, -dScrollY); } else { mScroller.startScroll( 0, getScrollY(), 0, -mScreenHeight - dScrollY); } } break; } postInvalidate(); return true; } private int checkAlignment() { int mEnd = getScrollY(); boolean isUp = ((mEnd - mStart) > 0) ? true : false; int lastPrev = mEnd % mScreenHeight; int lastNext = mScreenHeight - lastPrev; if (isUp) { //向上的 return lastPrev; } else { return -lastNext; } } @Override public void computeScroll() { super.computeScroll(); if (mScroller.computeScrollOffset()) { scrollTo(0, mScroller.getCurrY()); postInvalidate(); } } }
相关文章推荐
- android进阶-Android控件架构与自定义控件详解(一)
- 3.4.Android控件架构与自定义控件详解之ViewGroup的测量与绘制
- Android控件架构与自定义控件详解——Android群英传
- 第三章 Android控件架构与自定义控件详解
- 3.5.Android控件架构与自定义控件详解之自定义View(一)
- Android控件架构与自定义控件详解
- 【笔记】第三章Android控件架构与自定义控件详解(1)
- 《Android群英传》读书笔记3.Android控件架构与自定义控件详解
- Android控件架构与自定义控件详解(三)自定义ViewGroup
- Android进阶——自定义View之必学的系统控件架构及自定义控件概述
- 阅读徐宜生《Android群英传》的笔记——第3章 Android控件架构与自定义控件详解(3.6-3.8)
- 3.1.Android控件架构与自定义控件详解之控件架构
- Android控件架构与自定义控件详解(二)——自定义View
- Android控件架构与自定义控件详解(三)——自定义ViewGroup
- 3.2.Android控件架构与自定义控件详解之View的测量
- 第三章Android 控件架构与 自定义控件详解(Android群英传)
- Android控件架构与自定义控件详解(四)——事件拦截机制分析
- 3.5.Android控件架构与自定义控件详解之自定义View(二)
- Android控件架构与自定义控件详解
- Android控件架构与自定义控件详解(四)事件拦截机制分析