大唐网站建设,阿里云的wordpress如何设置,江西建设监督网站,手机端网站建设因为偶尔关注QQ运动#xff0c; 看到QQ运动的积分抽奖界面比较有意思#xff0c;所以就尝试用自定义View实现了下#xff0c;原本想通过开发者选项查看下界面的一些信息#xff0c;后来发现积分抽奖界面是在WebView中展示的#xff0c;应该是在H5页面中用js代码实现的 看到QQ运动的积分抽奖界面比较有意思所以就尝试用自定义View实现了下原本想通过开发者选项查看下界面的一些信息后来发现积分抽奖界面是在WebView中展示的应该是在H5页面中用js代码实现的暂时不去管它了。 这里的自定义View针对的是继承自View的情况你可以将Canvas想象为画板 Paint为画笔自定义View的过程和在画板上用画笔作画其实类似想象在画板上作画的过程你要画一个多大图形对应View的测量 onMeasure方法你要画什么样的图形比如圆形方形等等对应View的onDraw方法在掌握了View的一些基础概念位置参数、触摸事件、滑动测量模式、事件分发机制、绘制流程等知识后自定义View的时候就不觉得复杂了。 不管是多么复杂的View其内部基本都可以拆分至一个个小单元比如如下的QQ运动积分抽奖画面QQ -- 动态 -- 运动 -- 我 -- 积分 这里我们只关注抽奖的转盘因为是截图没有动画效果具体可以在自己的手机上查看下。这个抽奖的界面看似复杂其实可以分为几个部分 1. 最外层圆环其中有小圆圈闪动 2, 内部圆角矩形 3. 内部圆角卡片包含一个图片或说明文字 第一步我们要继承View类 如果需要自定义属性则应该实现带三个参数的构造方法这里将自定义View命名为 LotteryView public LotteryView(Context context) {this(context, null);}public LotteryView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public LotteryView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context, attrs);} 在init方法中可以做一些初始化的操作比如需要用的颜色值画笔Paint 宽高信息等如果有自定义属性也可以在init方法中处理。 接着可以设定View的宽高信息这里我们将View设置为正方形 Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//super.onMeasure(widthMeasureSpec, heightMeasureSpec);setMeasuredDimension(mSelfTotalWidth, mSelfTotalWidth);} 调用setMeasureDimension方法宽高都设置为 mSelfTotalWidth。这里我们宽高是限定的值所以不需要的处理不同测量模式的情况如果是其他自定义View要支持wrap_content属性需要在onMeasure方法中自行处理 第一步 绘制外层带圆角的圆环 /** 外层带圆角矩形圆环 */private void drawOuterRoundCircle(Canvas canvas) {canvas.save();canvas.clipRect(mOuterCircleWidth getPaddingLeft(),mOuterCircleWidth getPaddingTop(),mSelfTotalWidth - mOuterCircleWidth - getPaddingRight(),mSelfTotalWidth - mOuterCircleWidth - getPaddingBottom(),Region.Op.DIFFERENCE);canvas.drawRoundRect(getPaddingLeft(),getPaddingTop(),mSelfTotalWidth - getPaddingRight(),mSelfTotalWidth - getPaddingBottom(),18, 18, mOuterCirclePaint);canvas.restore();} 绘制外层圆环中的小圆圈 private void drawOuterDecorateSmallCircle(Canvas canvas) {int result mInvalidateCircleCount % 2;// topint x 0, y 0;int sideSize mSelfTotalWidth - mOuterCircleWidth * 2 - getPaddingLeft() - getPaddingRight(); // 除去最外边圆环后的边长for (int i 0; i 10; i) {mSmallCirclePaint.setColor(i % 2 result ? mSmallCircleYellowColor : mSmallCircleBlueColor);x mOuterCircleWidth (sideSize - mSmallCircleRadius * 2 * 9) / 9 * i mSmallCircleRadius * 2 * i getPaddingLeft();y (mOuterCircleWidth - mSmallCircleRadius * 2) / 2 mSmallCircleRadius getPaddingTop();canvas.drawCircle(x, y, mSmallCircleRadius, mSmallCirclePaint);}// bottomfor (int i 0; i 10; i) {mSmallCirclePaint.setColor(i % 2 result ? mSmallCircleYellowColor : mSmallCircleBlueColor);x mOuterCircleWidth (sideSize - mSmallCircleRadius * 2 * 9) / 9 * i mSmallCircleRadius * 2 * i getPaddingLeft();y mSelfTotalWidth - mOuterCircleWidth (mOuterCircleWidth - mSmallCircleRadius * 2) / 2 mSmallCircleRadius - getPaddingBottom();canvas.drawCircle(x, y, mSmallCircleRadius, mSmallCirclePaint);}// leftfor(int i 0; i 9; i) {mSmallCirclePaint.setColor(i % 2 (result 0 ? 1 : 0) ? mSmallCircleYellowColor : mSmallCircleBlueColor);x mOuterCircleWidth / 2 getPaddingLeft();y mOuterCircleWidth*2 (sideSize - mSmallCircleRadius * 2 * 9) / 9 * i mSmallCircleRadius * 2 * i getPaddingTop();canvas.drawCircle(x, y, mSmallCircleRadius, mSmallCirclePaint);}// rightfor(int i 0; i 9; i) {mSmallCirclePaint.setColor(i % 2 result ? mSmallCircleYellowColor : mSmallCircleBlueColor);x mSelfTotalWidth - mOuterCircleWidth / 2 - getPaddingRight();y mOuterCircleWidth*2 (sideSize - mSmallCircleRadius * 2 * 9) / 9 * i mSmallCircleRadius * 2 * i getPaddingTop();canvas.drawCircle(x, y, mSmallCircleRadius, mSmallCirclePaint);}} View Code 第二步绘制内部的圆角矩形即卡片所在区域的背景 private void drawInnerBackground(Canvas canvas) {canvas.drawRect(mOuterCircleWidth getPaddingLeft(), mOuterCircleWidth getPaddingTop(),mSelfTotalWidth - mOuterCircleWidth - getPaddingRight(),mSelfTotalWidth - mOuterCircleWidth - getPaddingBottom(), mInnerPaint);} 第三步 绘制内部小卡片 private void drawInnerCards(Canvas canvas) {int left 0, top 0, right 0, bottom 0;int spaceNum 0;for(int i 0 ; i 9 ; i) {spaceNum i % 3 1;left mOuterCircleWidth mInnerCardWidth * (i%3) mInnerCardSpace * spaceNum getPaddingLeft();top mOuterCircleWidth mInnerCardWidth * (i/3) mInnerCardSpace * (i/3 1) getPaddingTop();right left mInnerCardWidth;bottom top mInnerCardWidth;if(!mHadInitial) {mCardPositionInfoList.add(new Pair(new Pair(left, right), new Pair(top, bottom)));}drawInnerRoundCard(canvas, left, top, right, bottom, i);}mHadInitial true;} 全部绘制完成后在onTouchEvent中处理点击事件即可如何判定我们点击的是抽奖的区域这里使用对比位置信息的方法 如下 private int getTouchPositionInCardList(int x, int y) {if(mCardPositionInfoList ! null) {int index 1;for (PairPairInteger, Integer,PairInteger, Integer pair : mCardPositionInfoList) {if(x pair.first.first x pair.first.second y pair.second.first y pair.second.second) {return index;}index;}}return 0;} 将每一个小卡片的坐标信息lefttop right bottom信息保存在 ArrayListPairPairInteger, Integer,PairInteger, Integer mCardPosttionInfoList 中 当点击VIew时获取到点击的x y 坐标和 list中保存的坐标信息做对比如果index 5 则说明点击的是抽奖所在的小卡片区域。 代码托管在 https://github.com/aquarius520/LotteryView 欢迎Star 、Fork 转载于:https://www.cnblogs.com/sphere/p/7736807.html