先看效果图
实现逻辑,先自定义一个单独的五角星view,然后使用组合控件的放式实现最终效果。
比较初级,适合新手看一看,大牛见笑了,哈哈哈。
自定义view无非就是用测量onMeasure() 绘制 ondraw()位置onlayout()三个方法。
补充一句,本人英语实在垃圾,见笑见笑。
废话不多说,上代码。
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;
//默认颜色白色
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;
}
}
/*
*
*绘制五角星的方式根据正无边形的外切圆形来计算五角星的十个坐标点,用moveto,lineto进行绘制
*/
@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();
//逆时针绘制
path.moveTo(centerX,margin_top);//上顶点坐标。
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);//上顶点坐标。
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); //设置防抖动
}
/**
* 是否填充五角星
*/
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);
}
/**
* 为单个五角星添加下标进行标记
*/
public void setIndex(int index){
mIndex=index;
}
/**
* 设置星星颜色
*/
public void setColor(int mColor){
color=mColor;
}
/**
* @param _noChooseColor 未选中时候画笔的颜色
*/
public void setNoChooseColor(int _noChooseColor) {
noChooseColor=_noChooseColor;
}
/**
* @param _noChooseFill 未选中时候是否进行填充
*/
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;//星星数目
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;//选中了几个,默认为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{
/**
* 返回选择的数目
*/
void chooseNum(int chooseStarNum);
}
private ChooseNumCallBackchooseNumCallBack;
public void setChooseNumCallBack(ChooseNumCallBack chooseNumCallBack){
this.chooseNumCallBack=chooseNumCallBack;
}
}
使用方法
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" />
其中
app:starcolor为选中时五角星的颜色
app:size="50dp"五角星的尺寸 注:不应超过布局的尺寸
app:star_num="6" 五角星的数量 根据自己实际情况使用
app:star_margin="10dp" 每个五角星之间的距离
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+"星评价",Toast.LENGTH_SHORT).show();
}
});
}
}
自定义的属性
需要源码的可给我留言。