android星星评分自定义控件

来源:互联网 发布:gis地图数据购买 编辑:程序博客网 时间:2024/05/20 22:26

实现效果图如下,功能类似淘宝的订单评价,点击星星表示评分的高低;

自定义控件封装星星展示、点击操作、并提供给上层当前选中的星星数,上层只要设置星星选中、未选中的效果图等参数即可:


上代码:

1. 自定义LinearLayout:

package com.stars.test;import java.util.ArrayList;import java.util.List;import android.content.Context;import android.util.AttributeSet;import android.view.View;import android.widget.ImageView;import android.widget.LinearLayout;import com.drawable.test.DrawableAttrs;import com.drawable.test.DrawableTools;import com.stars.test.StarLinearLayoutLogic.IStarSelectedLis;/** * 评分星星控件 * @author thduan * @date 2016-1-12 下午4:58:42 */public class StarLinearLayout extends LinearLayout {private Context mContext;private StarLayoutParams mParams;private List<ImageView> stars;private StarLinearLayoutLogic logic;    public StarLinearLayout(Context context) {        this(context, null);    }    public StarLinearLayout(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }        public StarLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        mContext = context;        init();    }       private void init() {    logic = new StarLinearLayoutLogic(getStarSelectedLis());    stars = new ArrayList<ImageView>();    }        public void setStarParams(StarLayoutParams params) {    mParams = params;    logic.setParams(params);        updateStars();    invalidate();    }        private void updateStars() {    if(mParams == null) return;    if(stars != null) {    stars.clear();    removeAllViews();    }    for(int i = 0; i < mParams.getTotalStarNum(); i++) {    ImageView imageView = createStar(i);    stars.add(imageView);    addView(imageView);    }    }        /**     * 创建星星imageview     * @param pos     * @return     */    private ImageView createStar(final int pos) {    ImageView imageView = new ImageView(mContext);    // 另一个文章中有介绍DrawableToos工具:     // http://blog.csdn.net/duantihi/article/details/50492423    DrawableTools.setImageDrawableWithStateList(imageView,     new DrawableAttrs()    .setNormalDrawable(mParams.getNormalStar())    .setSelectedDrawable(mParams.getSelectedStar()));    if(mParams.isSelectable()) {  //可点击    imageView.setEnabled(true);    }else {  //不可点击,仅展示imageView.setEnabled(false);}    if(pos < mParams.getSelectedStarNum()) { //已选中的星星imageView.setSelected(true);}else {   //未被选中的星星imageView.setSelected(false);}    imageView.setPadding(mParams.getStarHorizontalSpace()/2, 0, mParams.getStarHorizontalSpace()/2, 0);    imageView.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {logic.onStarClick(pos);}});    return imageView;    }        /**     * 星星选择数变化后的UI处理     * @return     */    private IStarSelectedLis getStarSelectedLis() {    return new IStarSelectedLis() {@Overridepublic void onSelected(int curStarNum) {for(int i = 0; i < mParams.getTotalStarNum(); i++){if(i < curStarNum) {stars.get(i).setSelected(true);}else {stars.get(i).setSelected(false);}}}};    }        public StarLinearLayoutLogic getLogic() {    return logic;    }}
2. 逻辑类:

package com.stars.test;/** * 评价星星逻辑控制 * @author thduan * @date 2016-1-12 下午4:37:41 */public class StarLinearLayoutLogic {/** 当前已选择的星星数 */private int curStarNum;private StarLayoutParams mParams;private IStarSelectedLis starSelectedLi;public interface IStarSelectedLis {void onSelected(int curStarNum);}public StarLinearLayoutLogic(IStarSelectedLis lis) {starSelectedLi = lis;}public void setParams(StarLayoutParams params) {mParams = params;curStarNum = params.getSelectedStarNum();}public float getCurStarNum() {return curStarNum;}/** * 返回当前选中的星星数给上层 */public void onStarClick(int clickPosition) {curStarNum = clickPosition + 1;if(starSelectedLi != null) {starSelectedLi.onSelected(curStarNum);}}}
3.上层传的参数类

package com.stars.test;import android.graphics.drawable.Drawable;/** * 星星构造参数 * @author thduan * @date 2016-1-12 下午3:21:07 */public class StarLayoutParams {/** 默认选择的星星数为3 */public static final int DEF_SELECTED_STAR_NUM = 3;/** 星星总数 */public static final int DEF_TOTAL_STAR_NUM = 6;/** 星星之间的默认间距 */public static final int DEF_STAR_HORIZONTAL_SPACE = 10;/** 未被选中的星星图片 */private Drawable normalStar;/** 被选中的星星图片 */private Drawable selectedStar;/** 星星控件是否可点击选择 */private boolean isSelectable;private int selectedStarNum = DEF_SELECTED_STAR_NUM;private int totalStarNum = DEF_TOTAL_STAR_NUM;private int starHorizontalSpace = DEF_STAR_HORIZONTAL_SPACE;public Drawable getNormalStar() {return normalStar;}public StarLayoutParams setNormalStar(Drawable normalStar) {this.normalStar = normalStar;return this;}public Drawable getSelectedStar() {return selectedStar;}public StarLayoutParams setSelectedStar(Drawable selectedStar) {this.selectedStar = selectedStar;return this;}public boolean isSelectable() {return isSelectable;}public StarLayoutParams setSelectable(boolean isSelectable) {this.isSelectable = isSelectable;return this;}public int getSelectedStarNum() {return selectedStarNum;}public StarLayoutParams setSelectedStarNum(int selectedStarCnt) {this.selectedStarNum = selectedStarCnt;return this;}public int getTotalStarNum() {return totalStarNum;}public StarLayoutParams setTotalStarNum(int totalStarCnt) {this.totalStarNum = totalStarCnt;return this;}public int getStarHorizontalSpace() {return starHorizontalSpace;}public StarLayoutParams setStarHorizontalSpace(int starHorizontalSpace) {this.starHorizontalSpace = starHorizontalSpace;return this;}}
4. 使用

xml定义

    <com.stars.test.StarLinearLayout        android:id="@+id/starsLayout"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginTop="30dip"        android:orientation="horizontal" />
activity中使用

private StarLinearLayout starsLayout;    private void starsTest() {    starsLayout = (StarLinearLayout) findViewById(R.id.starsLayout);    StarLayoutParams params = new StarLayoutParams();    params.setNormalStar(getResources().getDrawable(R.drawable.star_normal))    .setSelectedStar(getResources().getDrawable(R.drawable.star_selected))    .setSelectable(true)    .setSelectedStarNum(3)    .setTotalStarNum(6)    .setStarHorizontalSpace(20);    starsLayout.setStarParams(params);    }

edit by duantihi, 2016-01-27 16:10:39

上次发的代码中有Bug,工程代码上传到csdn了,资源中无法修改,故此处说明一下,地址:http://download.csdn.net/detail/duantihi/9403209

StarsLinearLayout.java类中的 updateStars 和 createStar方法修改为如下才正常:

    private void updateStars() {    if(mParams == null) return;    if(stars != null) {    stars.clear();    removeAllViews();    }    int newStarNum = mParams.isSelectable() ? mParams.getTotalStarNum() : mParams.getSelectedStarNum();    for(int i = 0; i < newStarNum; i++) {    ImageView imageView = createStar(i);    stars.add(imageView);    addView(imageView);    }    }        /**     * 创建星星imageview     * @param pos     * @return     */    private ImageView createStar(final int pos) {    ImageView imageView = new ImageView(mContext);    DrawableTools.setImageDrawableWithStateList(imageView,     new DrawableAttrs()    .setNormalDrawable(mParams.getNormalStar())    .setSelectedDrawable(mParams.getSelectedStar()));    if(mParams.isSelectable()) {  //可点击    imageView.setEnabled(true);    if(pos < mParams.getSelectedStarNum()) { //已选中的星星    imageView.setSelected(true);    }else {   //未被选中的星星    imageView.setSelected(false);    }    }else {  //不可点击,仅展示imageView.setEnabled(false);imageView.setSelected(true);}    imageView.setPadding(mParams.getStarHorizontalSpace()/2, 0, mParams.getStarHorizontalSpace()/2, 0);    imageView.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {logic.onStarClick(pos);}});    return imageView;    }








0 1