Android 自定義View實現QQ運動積分抽獎轉盤

  因為偶爾關注QQ運動, 看到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 (Pair<Pair<Integer, Integer>,Pair<Integer, 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;}

  將每一個小卡片的坐標信息(left,top,?right,?bottom)信息,保存在?ArrayList<Pair<Pair<Integer, Integer>,Pair<Integer, Integer>>>??mCardPosttionInfoList 中,?當點擊VIew時獲取到點擊的x?y?坐標和

list中保存的坐標信息做對比,如果index == 5 ,則說明點擊的是抽獎所在的小卡片區域。

?

  代碼托管在:?https://github.com/aquarius520/LotteryView? 歡迎Star 、Fork

?

轉載于:https://www.cnblogs.com/sphere/p/7736807.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/390999.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/390999.shtml
英文地址,請注明出處:http://en.pswp.cn/news/390999.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

瑞立視:厚積薄發且具有“工匠精神”的中國品牌

一家成立兩年的公司&#xff1a;是如何在VR行業趨于穩定的情況下首次融資就獲得如此大額的金額呢&#xff1f; 2017年VR行業內宣布融資的公司寥寥無幾&#xff0c;無論是投資人還是消費者對這個 “寵兒”都開始紛紛投以懷疑的目光。但就在2017年7月27日&#xff0c;深圳市一家…

蘋果系統使用svg 動畫_為什么要使用SVG圖像:如何為SVG設置動畫并使其快速閃電化

蘋果系統使用svg 動畫我們為什么要使用SVG&#xff1f; (Why Are We Using SVG?) The web development sector is growing at a rapid pace, and SVG (scalable vector graphics) images are becoming more popular. As vector images, SVGs are composed of mathematical equ…

CSV模塊的使用

CSV模塊的使用 1、csv簡介 CSV (Comma Separated Values)&#xff0c;即逗號分隔值&#xff08;也稱字符分隔值&#xff0c;因為分隔符可以不是逗號&#xff09;&#xff0c;是一種常用的文本 格式&#xff0c;用以存儲表格數據&#xff0c;包括數字或者字符。很多程序在處理數…

Java里面遍歷list的方式

問題&#xff1a;Java里面遍歷list的方式 對于Java語言有點陌生&#xff0c;我嘗試熟悉遍歷list&#xff08;或者其他集合&#xff09;的所有方法&#xff08;或者是其他正確的語法&#xff09;和它們每一個方法的優缺點 給定 List的list對象&#xff0c;我知道有下列方法去循…

python 重啟內核_Python從零開始的內核回歸

python 重啟內核Every beginner in Machine Learning starts by studying what regression means and how the linear regression algorithm works. In fact, the ease of understanding, explainability and the vast effective real-world use cases of linear regression is…

bzoj千題計劃282:bzoj4517: [Sdoi2016]排列計數

http://www.lydsy.com/JudgeOnline/problem.php?id4517 組合數錯排公式 #include<cstdio> #include<iostream>using namespace std;#define N 1000001const int mod1e97;long long fac[N],inv[N],f[N];void read(int &x) {x0; char cgetchar();while(!isdigit…

chrome啟用flash_如何在Google Chrome中啟用Adobe Flash Player

chrome啟用flashRemember Adobe Flash player? Its that nifty software that lets websites embed videos and web games. Whole websites can even be powered by Flash.還記得Adobe Flash Player嗎&#xff1f; 正是這些漂亮的軟件使網站可以嵌入視頻和網絡游戲。 整個網站…

怎么樣把Java的字符串轉化為字節數組?

問題&#xff1a;怎么樣把Java的字符串轉化為字節數組 有沒有任何方法把Java的字符串轉化為字節數組 我嘗試這樣: System.out.println(response.split("\r\n\r\n")[1]); System.out.println("******"); System.out.println(response.split("\r\n\r\…

Forward團隊-爬蟲豆瓣top250項目-模塊開發過程

項目托管平臺地址:https://github.com/xyhcq/top250 開發模塊功能: 寫入文件功能 開發時間:3小時 實現將爬取到的信息寫入到文件中的功能 實現過程&#xff1a; # 打開文件 fopen("top250.txt","w") 在別的隊員寫的代碼基礎上&#xff0c;加入功能代碼 de…

CSS3 outline-offset 屬性 項目中input會遇到

outline在一個聲明中設置所有的輪廓屬性。outline:顏色&#xff08;outline-line&#xff09;樣式&#xff08;outline-style&#xff09;寬度&#xff08;outline-width&#xff09; outline-offset 屬性對輪廓進行偏移&#xff0c;并在邊框邊緣進行繪制。 輪廓在兩方面與邊框…

回歸分析中自變量共線性_具有大特征空間的回歸分析中的變量選擇

回歸分析中自變量共線性介紹 (Introduction) Performing multiple regression analysis from a large set of independent variables can be a challenging task. Identifying the best subset of regressors for a model involves optimizing against things like bias, multi…

winform窗體模板_如何驗證角模板驅動的窗體

winform窗體模板介紹 (Introduction) In this article, we will learn about validations in Angular template-driven forms. We will create a simple user registration form and implement some inbuilt validations on it. Along with the inbuilt validations, we will a…

【loj6191】「美團 CodeM 復賽」配對游戲 概率期望dp

題目描述 n次向一個棧中加入0或1中隨機1個&#xff0c;如果一次加入0時棧頂元素為1&#xff0c;則將這兩個元素彈棧。問最終棧中元素個數的期望是多少。 輸入 一行一個正整數 n 。 輸出 一行一個實數&#xff0c;表示期望剩下的人數&#xff0c;四舍五入保留三位小數。 樣例輸入…

查找滿足斷言的第一個元素

問題&#xff1a;查找滿足斷言的第一個元素 我剛剛開始使用Java 8的lambdas&#xff0c;我嘗試去實現一些我在函數式語言里面經常用的 例如&#xff0c;大部分的函數式語言里有一些查找函數&#xff0c;針對序列或者list進行操作&#xff0c;返回使得斷言為真的第一個元素。我…

Lock和synchronized的選擇

學習資源:http://www.cnblogs.com/dolphin0520/p/3923167.html 一.java.util.concurrent.locks包下常用的類 1.Lock public interface Lock { void lock();//用來獲取鎖。如果鎖已被其他線程獲取&#xff0c;則進行等待。void lockInterruptibly() throws InterruptedException…

python 面試問題_值得閱讀的30個Python面試問題

python 面試問題Interview questions are quite tricky to predict. In most cases, even peoples with great programming ability fail to answer some simple questions. Solving the problem with your code is not enough. Often, the interviewer will expect you to hav…

spring boot中 使用http請求

因為項目需求&#xff0c;需要兩個系統之間進行通信&#xff0c;經過一番調研&#xff0c;決定使用http請求。服務端沒有什么好說的&#xff0c;本來就是使用web 頁面進行訪問的&#xff0c;所以spring boot啟動后&#xff0c;controller層的接口就自動暴露出來了&#xff0c;客…

arduino joy_如何用Joy開發Kubernetes應用

arduino joyLet’s face it: Developing distributed applications is painful.讓我們面對現實&#xff1a;開發分布式應用程序很痛苦。 Microservice architectures might be great for decoupling and scalability but they are intimidatingly complex when it comes to de…

怎么樣得到平臺相關的換行符?

問題&#xff1a;怎么樣得到平臺相關的換行符&#xff1f; Java里面怎么樣得到平臺相關的換行符。我不可能到處都用"\n" 回答一 In addition to the line.separator property, if you are using java 1.5 or later and the String.format (or other formatting me…

scrapy常用工具備忘

scrapy常用的命令分為全局和項目兩種命令&#xff0c;全局命令就是不需要依靠scrapy項目&#xff0c;可以在全局環境下運行&#xff0c;而項目命令需要在scrapy項目里才能運行。一、全局命令##使用scrapy -h可以看到常用的全局命令 [rootaliyun ~]# scrapy -h Scrapy 1.5.0 - n…