先看效果圖
實(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"/>
需要源碼的可給我留言宴猾。