Android自定义View,仿QQ显示用户等级
最近公司產品需求,有一個類似QQ等級顯示的UI效果,用太陽、月亮和星星這三種圖標表示用戶的等級,有點類似RatingBar效果,但又有很多不一樣的地方,Github上搜了一大圈,沒有找到滿意的;仔細想想,實現起來也比較簡單,最后還是決定自己寫一個算了,也練習下自定義View。
要達到的效果
截了一張TIM的效果圖,其實效果差不多:
最終實現的效果
我只添加了三級顯示,并沒有添加皇冠。因為我的QQ等級離皇冠還差的很遠…
≡(▔﹏▔)≡,不過實現原理上并沒有任何的區別。
實現原理簡介
本Demo主要用到的知識就是自定義View中基本的View測量(onMeasure)和繪制(onDraw),加上簡單的QQ等級步進算法。大致思路就是根據用戶設置的等級(level字段),通過等級步進算法,計算出該等級可以用xx個太陽,xx個月亮和xx個星星表示出來;用一個list存儲所有的等級圖標,然后把這些小圖標連續的繪制出來。
實現代碼
代碼僅200多行,我已經添加了詳細的注釋:
package com.mewlxy.qqlevelbar;import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.View;import java.util.ArrayList; import java.util.List;/*** 類描述:* 創建人:luoxingyuan* 創建時間:2017/8/20 21:45* 修改人:luoxingyuan* 修改時間:2017/8/20 21:45* 修改備注:*/public class QQLevelBar extends View {private Context context;private int viewWidth;private int viewHeight;private int margin;private Bitmap sunBitmap;private Bitmap moonBitmap;private Bitmap starBitmap;private Paint bitmapPaint;private int level;private int step = 5;//默認步進,就是五個星星==一個月亮,QQ是4private int drawableResId1;private int drawableResId2;private int drawableResId3;private List<String> list; //這里面的每個元素就代表一個需要繪制的小圖標public int getLevel(){return level;}public void setLevel(int level){this.level = level;}public int getStep(){return step;}public void setStep(int step){this.step = step;}public int getDrawableResId1(){return drawableResId1;}public void setDrawableResId1(int drawableResId1){this.drawableResId1 = drawableResId1;}public int getDrawableResId2(){return drawableResId2;}public void setDrawableResId2(int drawableResId2){this.drawableResId2 = drawableResId2;}public int getDrawableResId3(){return drawableResId3;}public void setDrawableResId3(int drawableResId3){this.drawableResId3 = drawableResId3;}//重寫構造方法,讓所有構造方法都指向三個參數的方法。public QQLevelBar(Context context){this(context, null, 0);}public QQLevelBar(Context context, @Nullable AttributeSet attrs){this(context, attrs, 0);}public QQLevelBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr){super(context, attrs, defStyleAttr);this.context = context;//獲取自定義屬性樣式列表TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.qq_level_view);level = typedArray.getInt(R.styleable.qq_level_view_level, 0);step = typedArray.getInt(R.styleable.qq_level_view_step, 5);drawableResId1 = typedArray.getResourceId(R.styleable.qq_level_view_drawable_1, R.drawable.icon_sun_checked);drawableResId2 = typedArray.getResourceId(R.styleable.qq_level_view_drawable_2, R.drawable.icon_moon_checked);drawableResId3 = typedArray.getResourceId(R.styleable.qq_level_view_drawable_3, R.drawable.icon_star_checked);//獲取完了之后別忘了回收typedArray.recycle();init();}//初始化一些資源private void init(){sunBitmap = BitmapFactory.decodeResource(getResources(), drawableResId1);moonBitmap = BitmapFactory.decodeResource(getResources(), drawableResId2);starBitmap = BitmapFactory.decodeResource(getResources(), drawableResId3);bitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);list = calculateLevel(level);}@Override//View測量protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){//獲取寬度和高度的測量模式int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);switch (widthMode){//如果使用者沒有明確指定View的尺寸,那么我們就給它設置一個默認值case MeasureSpec.AT_MOST:case MeasureSpec.UNSPECIFIED://這里我的默認寬度是根據圖片大小和圖片數量計算出來的,具體的含義后面會說viewWidth = (sunBitmap.getWidth() + sunBitmap.getWidth() / 3) * list.size() + sunBitmap.getWidth() / 2;break;case MeasureSpec.EXACTLY://如果用戶明確指定了尺寸,就按照用戶指定的來viewWidth = MeasureSpec.getSize(widthMeasureSpec);break;}switch (heightMode){case MeasureSpec.AT_MOST:case MeasureSpec.UNSPECIFIED://View高度默認設置為圖片高度的兩倍,如果涉及到換行,這里還需要做動態計算,我就先偷個懶viewHeight = sunBitmap.getHeight() * 2;break;case MeasureSpec.EXACTLY:viewHeight = MeasureSpec.getSize(widthMeasureSpec);break;}setMeasuredDimension(viewWidth, viewHeight);//把測量出來的寬高尺寸設置到view中去,這個很重要margin = sunBitmap.getHeight() / 2;//上下左右的margin值}@Overrideprotected void onDraw(Canvas canvas)//在這里繪制想要的效果{int bitmapMargin = sunBitmap.getWidth() / 3;//圖片之間的橫向間隔for (int i = 0; i < list.size(); i++){//從list中循環取出元素,根據元素的值來判斷該繪制哪種圖標if (list.get(i).equals("日")){//繪制太陽圖標,(橫坐標為圖片寬度+相鄰兩張圖片的間隔)*i+整體左邊的margin值,縱坐標為view的高度/2-整體的margin值,下面的繪制同理canvas.drawBitmap(sunBitmap, (sunBitmap.getWidth() + bitmapMargin) * i + sunBitmap.getWidth() / 2,viewHeight / 2 - margin, bitmapPaint);} else if (list.get(i).equals("月")){canvas.drawBitmap(moonBitmap, (moonBitmap.getWidth() + bitmapMargin) * i + moonBitmap.getWidth() / 2,viewHeight / 2 - margin, bitmapPaint);} else{canvas.drawBitmap(starBitmap, (starBitmap.getWidth() + bitmapMargin) * i + starBitmap.getWidth() / 2,viewHeight / 2 - margin, bitmapPaint);}}}/*** 輸入要表示的等級,計算所需要的各種圖標的個數,并返回list* @param level* @return*/private List<String> calculateLevel(int level){List<String> list = new ArrayList<>();int sunNum = level / (step * step);//太陽圖標的個數為:等級/步進的平方(一個太陽為25級)int moonNum = (level - (step * step) * sunNum) / step;//月亮的個數:總等級先減去太陽表示的等級/步進值int starNum = level - sunNum * (step * step) - moonNum * step;//同理,計算出星星的個數//根據不同圖標的個數添加不同的元素for (int i = 0; i < sunNum; i++){list.add("日");}for (int i = 0; i < moonNum; i++){list.add("月");}for (int i = 0; i < starNum; i++){list.add("星");}return list;} }自定義屬性
<?xml version="1.0" encoding="utf-8"?> <resources><declare-styleable name="qq_level_view"><attr name="level" format="integer"/><!--設置等級--><attr name="step" format="integer"/><!--設置步進--><attr name="drawable_1" format="reference"/><!--一級圖片--><attr name="drawable_2" format="reference"/><!--二級圖片--><attr name="drawable_3" format="reference"/><!--三級圖片--></declare-styleable> </resources>可根據自己的實際需求添加更多的自定義屬性,這里就簡單的添加了幾個。
源碼
https://github.com/lxygithub/QQLevelBar
可下載源碼自行改造出自己想要的效果,如果能給個star那就更好了。
(~ ̄▽ ̄)~
使用
這里是最簡單的用法,當然你可以設置自己的想要的步進值和圖標。
<com.mewlxy.qqlevelbar.QQLevelBarandroid:layout_width="match_parent"android:layout_height="wrap_content"app:level="111"/>歡迎關注我的簡書
http://www.jianshu.com/u/2cea96e81d55
總結
以上是生活随笔為你收集整理的Android自定义View,仿QQ显示用户等级的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 树莓派基本配置
- 下一篇: android lomo设计与实现,拍静