1.首先繼承 ViewGroup 實(shí)現(xiàn)相關(guān)的構(gòu)造函數(shù)
public class Grade extends ViewGroup {
private Context mContext;
public Grade(Context context) {
super(context);
this.mContext = context;
}
public Grade(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
}
2.在構(gòu)造函數(shù)中獲取自定義屬性
public Grade(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
//獲取自定義屬性
TypedArray typedArray=mContext.obtainStyledAttributes(attrs,R.styleable.Grade);
isOnclick=typedArray.getBoolean(R.styleable.Grade_isOnclick,false);
number=typedArray.getInt(R.styleable.Grade_number,5);
value=typedArray.getInt(R.styleable.Grade_selectValue,0);
selectImage=typedArray.getResourceId(R.styleable.Grade_selectImage,0);
noselectImage=typedArray.getResourceId(R.styleable.Grade_noSelectImage,0);
}
3.接著就初始化一些數(shù)據(jù) 我們先初始化我們選中和沒(méi)選中默認(rèn)的圖片
/**
* 初始化Bitmap
* @param selectImage
* @param noselectImage
*/
public void initBitmap(int selectImage,int noselectImage) {
if (selectImage!=0&&noselectImage!=0){//如果沒(méi)有主動(dòng)設(shè)置選中和沒(méi)選中的圖片的時(shí)候 默認(rèn)使用默認(rèn)的圖片
yes = BitmapFactory.decodeResource(getResources(), selectImage);
no = BitmapFactory.decodeResource(getResources(),noselectImage);
}else {
yes = BitmapFactory.decodeResource(getResources(), R.mipmap.pingfenyes);
no = BitmapFactory.decodeResource(getResources(), R.mipmap.pingfen);
}
}
4.圖片初始化完成之后 這個(gè)時(shí)候 我們就可以去往 ViewGroup 中去添加我們的子 View 也就是星星的控件
/**
* 初始化評(píng)分控件
*/
public void initImageView() {
for (int i = 0; i < number; i++) {//將星星添加到View當(dāng)中去
final ImageView imageView = new ImageView(mContext);
imageView.setImageBitmap(no);
imageView.setTag(false);
addView(imageView);
}
}
5.添加完成后 我們就要確定他們的位置了 在 onLayout 方法中去擺放它的位置
/**
* 確定擺放的位置
* @param changed
* @param l
* @param t
* @param r
* @param b
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
count = getChildCount();
setSelectvalue(value);
int right = 0;
int left = 0;
//循環(huán)的設(shè)置子view的位置
for (int i = 0; i < count; i++) {
ImageView view = (ImageView) getChildAt(i);
right += no.getWidth();
view.layout(left, 0, right, no.getHeight());
left += no.getWidth();
final int finalI = i;
if (isOnclick){//設(shè)置是否可點(diǎn)擊
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
setSelectvalue(finalI+1);
if (ongradeClickItemListener!=null){
ongradeClickItemListener.currentItem(finalI+1);
}
}
});
}
}
}
6.確定擺放位置之后 我們接著要處理他們點(diǎn)擊的時(shí)候 選中和不選中的效果 這里我是用循環(huán) 去輪循各個(gè)子 view
/**
* 設(shè)置選中的邏輯
* @param value
*/
public void setSelectvalue(int value){
if (value>count){//如果主動(dòng)設(shè)置的選中數(shù)值大于星星的數(shù)值 那么做保護(hù)
Toast.makeText(mContext,"設(shè)定的選擇數(shù)值大于星星的個(gè)數(shù)",Toast.LENGTH_SHORT).show();
return;
}
//循環(huán)的去設(shè)置選中或者不選中
for (int j=0;j<value;j++){
ImageView imageView= (ImageView) getChildAt(j);
imageView.setImageBitmap(yes);
imageView.setTag(true);
}
for (int k=value;k<count;k++){
ImageView imageView= (ImageView) getChildAt(k);
imageView.setImageBitmap(no);
imageView.setTag(false);
}
}
好了,基本上到這里,控件就基本上完成了。接著 做一些完善,測(cè)量控件的寬高,對(duì)外提供點(diǎn)擊事件的接口等,完整代碼如下:
package com.example.yinshuai.diyview.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.example.yinshuai.diyview.R;
/**
* Created by yinshuai on 2017/7/7.
* 1.可以設(shè)置星星的數(shù)目
* 2.可以設(shè)置選中的數(shù)目
* 3.可以替換選中或不選中的圖片
* 4.定制化高
*/
public class Grade extends ViewGroup {
private Bitmap yes;//選中的圖片
private Bitmap no;//沒(méi)選中的圖片
private Context mContext;
private int number;//星星的個(gè)數(shù)
private OnGradeClickItemListener ongradeClickItemListener;
private int count;//當(dāng)前有多少個(gè)子view
private int value=0;//當(dāng)前選中的位置
private boolean isOnclick;//是否可點(diǎn)擊
private int selectImage;//選中的圖片資源引用
private int noselectImage;//沒(méi)選中的圖片資源引用
public Grade(Context context) {
super(context);
this.mContext = context;
initBitmap(0,0);//初始化圖片資源文件
initImageView();//初始化圖片控件
setWillNotDraw(false);
}
public Grade(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
//獲取自定義屬性
TypedArray typedArray=mContext.obtainStyledAttributes(attrs,R.styleable.Grade);
isOnclick=typedArray.getBoolean(R.styleable.Grade_isOnclick,false);
number=typedArray.getInt(R.styleable.Grade_number,5);
value=typedArray.getInt(R.styleable.Grade_selectValue,0);
selectImage=typedArray.getResourceId(R.styleable.Grade_selectImage,0);
noselectImage=typedArray.getResourceId(R.styleable.Grade_noSelectImage,0);
initBitmap(selectImage,noselectImage);
initImageView();
setWillNotDraw(false);
}
/**
* 寬高測(cè)量
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode=MeasureSpec.getMode(widthMeasureSpec);
int widthSize=MeasureSpec.getSize(widthMeasureSpec);
int heightMode=MeasureSpec.getMode(heightMeasureSpec);
int heightSize=MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
if (widthMode==MeasureSpec.EXACTLY){
width=widthSize;
}else {
width=no.getWidth()*number;
}
if (heightMode==MeasureSpec.EXACTLY){
height=heightSize;
}else {
height=no.getHeight();
}
setMeasuredDimension(width,height);
}
/**
* 定義點(diǎn)擊事件接口
*/
public interface OnGradeClickItemListener {
void currentItem(int pos);
}
/**
* 對(duì)外提供點(diǎn)擊事件接口
* @param ongradeClickItemListener
*/
public void setOnGradeClickItemListener(OnGradeClickItemListener ongradeClickItemListener) {
this.ongradeClickItemListener = ongradeClickItemListener;
}
/**
* 初始化Bitmap
* @param selectImage
* @param noselectImage
*/
public void initBitmap(int selectImage,int noselectImage) {
if (selectImage!=0&&noselectImage!=0){//如果沒(méi)有主動(dòng)設(shè)置選中和沒(méi)選中的圖片的時(shí)候 默認(rèn)使用默認(rèn)的圖片
yes = BitmapFactory.decodeResource(getResources(), selectImage);
no = BitmapFactory.decodeResource(getResources(),noselectImage);
}else {
yes = BitmapFactory.decodeResource(getResources(), R.mipmap.pingfenyes);
no = BitmapFactory.decodeResource(getResources(), R.mipmap.pingfen);
}
}
/**
* 初始化評(píng)分控件
*/
public void initImageView() {
for (int i = 0; i < number; i++) {//將星星添加到View當(dāng)中去
final ImageView imageView = new ImageView(mContext);
imageView.setImageBitmap(no);
imageView.setTag(false);
addView(imageView);
}
}
/**
* 確定擺放的位置
* @param changed
* @param l
* @param t
* @param r
* @param b
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
count = getChildCount();
setSelectvalue(value);
int right = 0;
int left = 0;
//循環(huán)的設(shè)置子view的位置
for (int i = 0; i < count; i++) {
ImageView view = (ImageView) getChildAt(i);
right += no.getWidth();
view.layout(left, 0, right, no.getHeight());
left += no.getWidth();
final int finalI = i;
if (isOnclick){//設(shè)置是否可點(diǎn)擊
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
setSelectvalue(finalI+1);
if (ongradeClickItemListener!=null){
ongradeClickItemListener.currentItem(finalI+1);
}
}
});
}
}
}
/**
* 設(shè)置選中的邏輯
* @param value
*/
public void setSelectvalue(int value){
if (value>count){//如果主動(dòng)設(shè)置的選中數(shù)值大于星星的數(shù)值 那么做保護(hù)
Toast.makeText(mContext,"設(shè)定的選擇數(shù)值大于星星的個(gè)數(shù)",Toast.LENGTH_SHORT).show();
return;
}
//循環(huán)的去設(shè)置選中或者不選中
for (int j=0;j<value;j++){
ImageView imageView= (ImageView) getChildAt(j);
imageView.setImageBitmap(yes);
imageView.setTag(true);
}
for (int k=value;k<count;k++){
ImageView imageView= (ImageView) getChildAt(k);
imageView.setImageBitmap(no);
imageView.setTag(false);
}
}
/**
* 對(duì)外提供設(shè)置選擇的接口
* @param value
*/
public void setValue(int value){
this.value=value;
}
}
github項(xiàng)目地址:GradeView
個(gè)人博客:小白的博客
最終的效果:

Grade.gif