本文共 6778 字,大约阅读时间需要 22 分钟。
先上图看实现效果:
首先在res/values/ 下建立一个attrs.xml , 在里面定义我们的属性,只定义三个,有间距、分值和是否可以编辑:
自定义一个View继承LinearLayout,在构造方法中获取我们自定义的属性:
import android.content.Context;import android.content.res.TypedArray;import android.util.AttributeSet;import android.view.View;import android.view.View.OnClickListener;import android.widget.ImageView;import android.widget.LinearLayout;import java.util.ArrayList;import java.util.List;public class StarLinearLayout extends LinearLayout implements OnClickListener { /** * 星星之间的间距 */ private int mMargin = 10; /** * 是否可点击 */ private boolean isEdit; /** * 初始的值 */ private float mScore = 0; private Liststars = new ArrayList<>(); public StarLinearLayout(Context context) { this(context, null); } public StarLinearLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public StarLinearLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); if (attrs != null) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.star); mMargin = (int) a.getDimension(R.styleable.star_margin, 10); isEdit = a.getBoolean(R.styleable.star_isEdit, false); mScore = a.getFloat(R.styleable.star_score, 0); a.recycle(); } init(); setScore(mScore); }
在初始化的方法里面把星星动态添加进去(当然这里是用的图片),然后绑定点击的监听:
private void init() { LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); params.weight = 1; params.rightMargin = mMargin; for (int i = 0; i < 5; i++) { ImageView star = new ImageView(getContext()); star.setImageResource(R.mipmap.ic_star_select); stars.add(star); addView(star, params); star.setOnClickListener(this); } }
下面就是设置分数和获取分数的方法(根据值来决定需要放置的星星图片):
public void setScore(float score) { if (score < 0 || score > 5) score = 0; mScore = score; setStar(((int) (10 * score)) / 5); } public float getScore() { return mScore; } private void setStar(int level) { int i; for (i = 0; i < level / 2; i++) { stars.get(i).setImageResource(R.mipmap.ic_star_select); } if (level % 2 > 0) { stars.get(i).setImageResource(R.mipmap.ic_star_select_half); i++; } for (; i < stars.size(); i++) { stars.get(i).setImageResource(R.mipmap.ic_star_unselect); } }
最后剩下就是添加监听:
@Override public void onClick(View v) { if (stars.contains(v)) { if (!isEdit) return; int index = stars.indexOf(v); setScore(index + 1); changeListener.Change(index + 1); } } ChangeListener changeListener; // 为每个接口设置监听器 public void setChangeListener(ChangeListener change) { this.changeListener = change; } public interface ChangeListener { void Change(int level); }
activity中的代码:
public class MainActivity extends AppCompatActivity { private StarLinearLayout mStar; private TextView tvScore; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mStar = (StarLinearLayout) findViewById(R.id.Star); tvScore = (TextView) findViewById(R.id.tv_score); mStar.setScore((float) 2.5); tvScore.setText("当前评分:" + mStar.getScore() + "分"); mStar.setChangeListener(new StarLinearLayout.ChangeListener() { @Override public void Change(int level) { tvScore.setText("当前评分:" + level + "分"); Toast.makeText(MainActivity.this, "您给了" + level + "分", Toast.LENGTH_LONG).show(); } }); }}
xml中的写法:
自定义类的全部代码:
import android.content.Context;import android.content.res.TypedArray;import android.util.AttributeSet;import android.view.View;import android.view.View.OnClickListener;import android.widget.ImageView;import android.widget.LinearLayout;import java.util.ArrayList;import java.util.List;public class StarLinearLayout extends LinearLayout implements OnClickListener { /** * 星星之间的间距 */ private int mMargin = 10; /** * 是否可点击 */ private boolean isEdit; /** * 初始的值 */ private float mScore = 0; private Liststars = new ArrayList<>(); public StarLinearLayout(Context context) { this(context, null); } public StarLinearLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public StarLinearLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); if (attrs != null) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.star); mMargin = (int) a.getDimension(R.styleable.star_margin, 10); isEdit = a.getBoolean(R.styleable.star_isEdit, false); mScore = a.getFloat(R.styleable.star_score, 0); a.recycle(); } init(); setScore(mScore); } private void init() { LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); params.weight = 1; params.rightMargin = mMargin; for (int i = 0; i < 5; i++) { ImageView star = new ImageView(getContext()); star.setImageResource(R.mipmap.ic_star_select); stars.add(star); addView(star, params); star.setOnClickListener(this); } } public void setScore(float score) { if (score < 0 || score > 5) score = 0; mScore = score; setStar(((int) (10 * score)) / 5); } public float getScore() { return mScore; } private void setStar(int level) { int i; for (i = 0; i < level / 2; i++) { stars.get(i).setImageResource(R.mipmap.ic_star_select); } if (level % 2 > 0) { stars.get(i).setImageResource(R.mipmap.ic_star_select_half); i++; } for (; i < stars.size(); i++) { stars.get(i).setImageResource(R.mipmap.ic_star_unselect); } } @Override public void onClick(View v) { if (stars.contains(v)) { if (!isEdit) return; int index = stars.indexOf(v); setScore(index + 1); changeListener.Change(index + 1); } } ChangeListener changeListener; // 为每个接口设置监听器 public void setChangeListener(ChangeListener change) { this.changeListener = change; } public interface ChangeListener { void Change(int level); }}
源码地址:>