Android 自定義view之星級(jí)評(píng)分控件實(shí)現(xiàn)

先看效果圖


實(shí)現(xiàn)邏輯惕味,先自定義一個(gè)單獨(dú)的五角星view,然后使用組合控件的放式實(shí)現(xiàn)最終效果把兔。

比較初級(jí)沪伙,適合新手看一看,大牛見笑了县好,哈哈哈围橡。

自定義view無非就是用測量onMeasure() 繪制 ondraw()位置onlayout()三個(gè)方法。

補(bǔ)充一句缕贡,本人英語實(shí)在垃圾翁授,見笑見笑。

廢話不多說晾咪,上代碼收擦。

StarView 五角星view

public class StarView extends View implements View.OnClickListener {

? ? Context mContext;

? ? private int centerX;

? ? Paint.Style style;

? ? private int mIndex;

? ? boolean fill;

? ? boolean noChooseFill;

? ? //是否選中

? ? boolean choose;

? ? //顏色

? ? private int color=0XE3E3E3;

? ? private int noChooseColor=0XFF5722;

? ? //默認(rèn)顏色白色

? ? private int defuatColor=0XFFFFFF;

? ? //寬度

? ? private int wight;

? ? //高度

? ? private int height;

? ? //畫筆

? ? Paint mPaint;

? ? public StarView(Context context) {

super(context);

? ? ? ? this.mContext=context;

? ? ? ? initPaint();

? ? ? ? this.setOnClickListener(this);

? ? }

public StarView(Context context,? AttributeSet attrs) {

super(context, attrs);

? ? ? ? this.mContext=context;

? ? ? ? setAttributes(attrs);

? ? ? ? initPaint();

? ? ? ? this.setOnClickListener(this);

? ? }

public StarView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

? ? ? ? this.mContext=context;

? ? ? ? setAttributes(attrs);

? ? ? ? initPaint();

? ? ? ? this.setOnClickListener(this);

? ? }

@Override

? ? protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

? ? ? ? int wightSize=MeasureSpec.getSize(widthMeasureSpec);

? ? ? ? int wightMode=MeasureSpec.getMode(widthMeasureSpec);

? ? ? ? switch (wightMode){

case MeasureSpec.EXACTLY:

wight=wightSize;

break;

? ? ? ? ? ? case MeasureSpec.AT_MOST:

wight=50;

break;

? ? ? ? ? ? case MeasureSpec.UNSPECIFIED:

wight=wightSize;

break;

? ? ? ? }

int heightSize=MeasureSpec.getSize(heightMeasureSpec);

? ? ? ? int heightMode=MeasureSpec.getMode(heightMeasureSpec);

? ? ? ? switch (heightMode){

case MeasureSpec.EXACTLY:

height=heightSize;

break;

? ? ? ? ? ? case MeasureSpec.AT_MOST:

height=50;

break;

? ? ? ? ? ? case MeasureSpec.UNSPECIFIED:

height=heightSize;

break;

? ? ? ? }

}

/*

*

*繪制五角星的方式根據(jù)正無邊形的外切圓形來計(jì)算五角星的十個(gè)坐標(biāo)點(diǎn),用moveto,lineto進(jìn)行繪制

*/

@Override

? ? protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

? ? ? ? if(fill){

isFill();

? ? ? ? ? ? mPaint.setColor(color);

? ? ? ? }else{

mPaint.setColor(noChooseColor);

? ? ? ? ? ? mPaint.setStyle(style);

? ? ? ? }

? ? ? ? centerX=wight/2;

? ? ? ? int radius=wight/2;

? ? ? ? float sideLength= (float) (radius*Math.sin(Math.PI/5));

? ? ? ? float starLenght= (float) (sideLength/Math.cos(Math.PI/5));//五角星邊長

? ? ? ? float commentLenght= (float) (starLenght+(Math.sin(Math.PI/10)*starLenght));

? ? ? ? float sin36= (float) (Math.sin(Math.PI/5)*starLenght);

? ? ? ? float sin18= (float) (Math.sin(Math.PI/10)*starLenght);

? ? ? ? float cos18= (float) (Math.cos(Math.PI/10)*starLenght);

? ? ? ? float cos36= (float) (Math.cos(Math.PI/5)*starLenght);

? ? ? ? float? margin_top=(height-(cos18+sin36+cos18))/2;

? ? ? ? Path path=new Path();

? ? ? ? //逆時(shí)針繪制

? ? ? ? path.moveTo(centerX,margin_top);//上頂點(diǎn)坐標(biāo)谍倦。

? ? ? ? path.lineTo((centerX-sin18), cos18+margin_top);//2

? ? ? ? path.lineTo(centerX-commentLenght, cos18+margin_top);//3

? ? ? ? path.lineTo(centerX-commentLenght+cos36,cos18+sin36+margin_top);//4

? ? ? ? path.lineTo(centerX-commentLenght+cos36-sin18,cos18+sin36+cos18+margin_top);//5

? ? ? ? path.lineTo(centerX,cos18+cos18+margin_top);//6

? ? ? ? path.lineTo(centerX+cos36,cos18+sin36+cos18+margin_top);//7

? ? ? ? path.lineTo(centerX+cos36-sin18,cos18+sin36+margin_top);//8

? ? ? ? path.lineTo(wight-(centerX-commentLenght),cos18+margin_top);//9

? ? ? ? path.lineTo(centerX+sin18,cos18+margin_top);//10

? ? ? ? path.lineTo(centerX,margin_top);//上頂點(diǎn)坐標(biāo)塞赂。

? ? ? ? canvas.drawPath(path,mPaint);

? ? }

/**

* 獲取自定義屬性

*/

? ? public? void? setAttributes(AttributeSet attrs){

TypedArray typedArray=mContext.obtainStyledAttributes(attrs,R.styleable.StarView);

? ? ? ? color=typedArray.getColor(R.styleable.StarView_color,defuatColor);

? ? ? ? typedArray.recycle();

? ? }

/**

* 初始化paint

*/

? ? public void initPaint(){

mPaint=new Paint();

? ? ? ? mPaint.setAntiAlias(true);

? ? ? ? mPaint.setStrokeWidth(5f);

? ? ? ? mPaint.setDither(true); //設(shè)置防抖動(dòng)

? ? }

/**

* 是否填充五角星

*/

? ? public void? isFill(){

if(fill){

style=Paint.Style.FILL;

? ? ? ? }else{

style=Paint.Style.STROKE;

? ? ? ? }

mPaint.setStyle(style);

? ? }

@Override

? ? public void onClick(View v) {

clickCallBack.choose(mIndex);

? ? }

/**

* 為單個(gè)五角星添加下標(biāo)進(jìn)行標(biāo)記

*/

? ? public? void setIndex(int index){

mIndex=index;

? ? }

/**

* 設(shè)置星星顏色

*/

? ? public void setColor(int mColor){

color=mColor;

? ? }

/**

? ? * @param _noChooseColor 未選中時(shí)候畫筆的顏色

*/

? ? public void setNoChooseColor(int _noChooseColor) {

noChooseColor=_noChooseColor;

? ? }

/**

? ? * @param _noChooseFill 未選中時(shí)候是否進(jìn)行填充

*/

? ? public void setNoChooseFill(boolean _noChooseFill) {

noChooseFill=_noChooseFill;

? ? ? ? if(_noChooseFill){

style=Paint.Style.FILL;//填充

? ? ? ? }else{

style=Paint.Style.STROKE;//不填充

? ? ? ? }

}

public interface? ClickCallBack{

void choose(int index);

? ? }

private ClickCallBackclickCallBack;

? ? public void setClickCallBack(ClickCallBack clickCallBack){

this.clickCallBack=clickCallBack;

? ? }

/**

* 選中

*/

? ? public void choose(boolean mFill){

fill=mFill;

? ? ? ? invalidate();

? ? }

}

組合控件 StarBar。

public class StarBar extends LinearLayout implements StarView.ClickCallBack {

Context mContext;

? ? private int color;

? ? private int noChooseColor;

? ? private int starNum=1;//星星數(shù)目

? ? private float size;//星星大小

? ? private StarView starView;

? ? private float margin;

? ? private boolean noChooseFill;

? ? private ListstarViews=new ArrayList<>();

? ? public StarBar(Context context) {

super(context);

? ? ? ? this.mContext=context;

? ? }

private int chooseNum;//選中了幾個(gè),默認(rèn)為0

? ? public StarBar(Context context, AttributeSet attrs) {

super(context, attrs);

? ? ? ? this.mContext=context;

? ? ? ? setAttr(attrs);

? ? ? ? addStar();

? ? }

public StarBar(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

? ? ? ? this.mContext=context;

? ? ? ? setAttr(attrs);

? ? ? ? addStar();

? ? }

public void setAttr(AttributeSet attrs){

TypedArray typedArray=mContext.obtainStyledAttributes(attrs,R.styleable.StarBar);

? ? ? ? color=typedArray.getColor(R.styleable.StarBar_starcolor,0XFFFFFF);

? ? ? ? starNum=typedArray.getInt(R.styleable.StarBar_star_num,0xFFFFFF);

? ? ? ? size=typedArray.getDimension(R.styleable.StarBar_size,0f);

? ? ? ? margin=typedArray.getDimension(R.styleable.StarBar_star_margin,10f);

? ? ? ? noChooseColor=typedArray.getColor(R.styleable.StarBar_no_choose_color,0XEEEEEE);

? ? ? ? noChooseFill=typedArray.getBoolean(R.styleable.StarBar_no_choose_fill,false);

? ? ? ? typedArray.recycle();

? ? }

public void addStar(){

for(int i=0;i

starView=new StarView(mContext);

? ? ? ? ? ? starView.setColor(color);

? ? ? ? ? ? starView.setNoChooseColor(noChooseColor);

? ? ? ? ? ? starView.setNoChooseFill(noChooseFill);

? ? ? ? ? ? starView.setIndex(i);

? ? ? ? ? ? LinearLayout.LayoutParams layoutParams=new LinearLayout.LayoutParams((int)size,(int)size);

? ? ? ? ? ? layoutParams.rightMargin= (int)margin;

? ? ? ? ? ? starView.setLayoutParams(layoutParams);

? ? ? ? ? ? starView.setClickCallBack(this);

? ? ? ? ? ? addView(starView);

? ? ? ? ? ? starViews.add(starView);

? ? ? ? }

}

@Override

? ? public void choose(int index) {

for(int i=0;i

if(i<=index){

starViews.get(i).choose(true);

? ? ? ? ? ? ? ? }else{

starViews.get(i).choose(false);

? ? ? ? ? ? ? ? }

}

chooseNumCallBack.chooseNum(index+1);

? ? }

public interface? ChooseNumCallBack{

/**

* 返回選擇的數(shù)目

*/

? ? ? ? void chooseNum(int chooseStarNum);

? ? }

private ChooseNumCallBackchooseNumCallBack;

? ? public void setChooseNumCallBack(ChooseNumCallBack chooseNumCallBack){

this.chooseNumCallBack=chooseNumCallBack;

? ? }

}

使用方法

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

? ? xmlns:app="http://schemas.android.com/apk/res-auto"

? ? xmlns:tools="http://schemas.android.com/tools"

? ? android:layout_width="match_parent"

? ? android:layout_height="match_parent"

? ? tools:context=".MainActivity">

? ? ? android:id="@+id/stars"

? ? ? android:layout_width="match_parent"

? ? ? android:layout_height="100dp"

? ? ? app:starcolor="#E00404"

? ? ? android:orientation="horizontal"

? ? ? app:size="50dp"

? ? ? android:gravity="center"

? ? ? app:star_num="6"

? ? ? app:star_margin="10dp"

? ? ? app:no_choose_fill="true"

? ? ? app:no_choose_color="#D1D1D1"

? ? ? />

</RelativeLayout>

其中

app:starcolor為選中時(shí)五角星的顏色

app:size="50dp"五角星的尺寸? ?注:不應(yīng)超過布局的尺寸

app:star_num="6" 五角星的數(shù)量? ?根據(jù)自己實(shí)際情況使用? ??

app:star_margin="10dp"? 每個(gè)五角星之間的距離

app:no_choose_fill="true"? 沒有被選擇的五角星是否為填充模式

app:no_choose_color="#D1D1D1" 沒有被選擇的五角星的顏色


MainActivity看效果昼蛀。

public class MainActivityextends AppCompatActivity {

@Override

? ? protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

? ? ? ? setContentView(R.layout.activity_main);

? ? ? ? StarBar starBar=findViewById(R.id.stars);

? ? ? ? starBar.setChooseNumCallBack(new StarBar.ChooseNumCallBack() {

@Override

? ? ? ? ? ? public void chooseNum(int chooseStarNum) {

? ? ? ? ? ? Toast.makeText(MainActivity.this,chooseStarNum+"星評(píng)價(jià)",Toast.LENGTH_SHORT).show();

? ? ? ? ? ? }

});

? ? }

}


自定義的屬性

<?xml version="1.0" encoding="utf-8"?>

? ? <declare-styleable name="StarView">


? ? ? ? <attr name="color" format="color"/>

? ? <declare-styleable name="StarBar">


? ? ? ? <attr name="starcolor" format="color"/>


? ? ? ? <attr name="size" format="dimension" />


? ? ? ? <attr name="star_num" format="integer"/>


? ? ? ? <attr name="star_margin" format="dimension"/>


? ? ? ? <attr name="no_choose_color" format="color"/>


? ? ? ? <attr name="no_choose_fill" format="boolean"/>

需要源碼的可給我留言宴猾。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市叼旋,隨后出現(xiàn)的幾起案子仇哆,更是在濱河造成了極大的恐慌,老刑警劉巖夫植,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件税产,死亡現(xiàn)場離奇詭異,居然都是意外死亡偷崩,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門撞羽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阐斜,“玉大人,你說我怎么就攤上這事诀紊≮顺觯” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長笤喳。 經(jīng)常有香客問我为居,道長,這世上最難降的妖魔是什么杀狡? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任蒙畴,我火速辦了婚禮,結(jié)果婚禮上呜象,老公的妹妹穿的比我還像新娘膳凝。我一直安慰自己,他們只是感情好恭陡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布蹬音。 她就那樣靜靜地躺著,像睡著了一般休玩。 火紅的嫁衣襯著肌膚如雪著淆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天拴疤,我揣著相機(jī)與錄音永部,去河邊找鬼。 笑死遥赚,一個(gè)胖子當(dāng)著我的面吹牛扬舒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播凫佛,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼讲坎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了愧薛?” 一聲冷哼從身側(cè)響起晨炕,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎毫炉,沒想到半個(gè)月后瓮栗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瞄勾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年费奸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片进陡。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡愿阐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出趾疚,到底是詐尸還是另有隱情缨历,我是刑警寧澤以蕴,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站辛孵,受9級(jí)特大地震影響丛肮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜魄缚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一宝与、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鲜滩,春花似錦伴鳖、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至嗓蘑,卻和暖如春须肆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背桩皿。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來泰國打工豌汇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人泄隔。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓拒贱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親佛嬉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子逻澳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容