Android中自定义RatingBar

  1. 效果图

    运行的效果图

  2. 自定义的RatingView

package com.example.ratingbar;

import java.util.ArrayList;

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class Rating extends ViewGroup {

    /* * 四张图片 */
    private int[] pictures;

    private ArrayList<TextView> array = new ArrayList<TextView>();

    /* * 当前的位置 */
    private int position = 0;

    /* * 總的數據的長度 */
    private int length = 0;
    /* * 间隔 */
    private int jiange = 0;
    //
    private int xingWidth = 0;
    private int xingHeight = 0;

    public Rating(Context context, AttributeSet attrs, int defStyleAttr,
            int defStyleRes) {
        this(context, attrs);
    }

    public Rating(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs);
    }

    public Rating(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
        pictures = new int[4];

        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.Rating);
        pictures[0] = a.getResourceId(R.styleable.Rating_graySchedule,
                R.drawable.line_grey);
        pictures[1] = a.getResourceId(R.styleable.Rating_highSchedule,
                R.drawable.line_yellow);
        pictures[2] = a.getResourceId(R.styleable.Rating_grayRating,
                R.drawable.xing1);
        pictures[3] = a.getResourceId(R.styleable.Rating_highRating,
                R.drawable.xing2);
        jiange = a.getInt(R.styleable.Rating_jiange, (int) TypedValue
                .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources()
                        .getDisplayMetrics()));
        a.recycle();

        for (int i = 0; i < 6; i++) {
            // ImageView imageView = new ImageView(getContext());
            TextView textView = new TextView(getContext());
            if (i == 0) {
                textView.setBackgroundResource(pictures[2]);
                textView.setText(String.valueOf(i));
            } else {
                textView.setBackgroundResource(pictures[0]);
            }
            textView.setGravity(Gravity.CENTER);
            ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.WRAP_CONTENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
            MarginLayoutParams params2 = new MarginLayoutParams(params);
            textView.setLayoutParams(params2);
            addView(textView);
            array.add(textView);
        }
        length = array.size();
    }

    public Rating(Context context) {
        this(context, null);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // TODO Auto-generated method stub
        /** * 获得此ViewGroup上级容器为其推荐的宽和高,以及计算模式 */
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);

        // 计算出所有的childView的宽和高
        measureChildren(widthMeasureSpec, heightMeasureSpec);

        int cCount = getChildCount();

        int cWidth = 0;
        int cHeight = 0;
        MarginLayoutParams cParams = null;

        int maxHeight = 0;
        int maxWidth = 0;

        //
        int mW = 0;
        /** * 根据childView计算的出的宽和高,以及设置的margin计算容器的宽和高,主要用于容器是warp_content时 */
        for (int i = 0; i < cCount; i++) {
            View childView = getChildAt(i);
            cWidth = childView.getMeasuredWidth();
            cHeight = childView.getMeasuredHeight();
            cParams = (MarginLayoutParams) childView.getLayoutParams();

            if (i == 0) {
                maxHeight = cHeight + cParams.topMargin + cParams.bottomMargin;
                mW = cWidth + cParams.leftMargin + cParams.rightMargin;
            } else {
                int t1 = cWidth + cParams.leftMargin + cParams.rightMargin;
                if (t1 > mW) {
                    mW = t1;
                }
                int t2 = cHeight + cParams.topMargin + cParams.bottomMargin;
                if (t2 > maxHeight) {
                    maxHeight = t2;
                }
            }
            xingWidth = mW;
            xingHeight = maxHeight;
            maxWidth += cWidth + cParams.leftMargin + cParams.rightMargin;
        }
        maxWidth += (length - 1) * jiange;
        /** * 如果是wrap_content设置为我们计算的值 否则:直接设置为父容器计算的值 */
        setMeasuredDimension((widthMode == MeasureSpec.EXACTLY) ? sizeWidth
                : maxWidth, (heightMode == MeasureSpec.EXACTLY) ? sizeHeight
                : maxHeight);
    }

    @Override
    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // TODO Auto-generated method stub
        int height = getHeight();

        int cCount = getChildCount();
        int cWidth = 0;
        int cHeight = 0;
        MarginLayoutParams cParams = null;

        int h = 0;
        /** * 遍历所有childView根据其宽和高,以及margin进行布局 */
        for (int i = 0; i < cCount; i++) {
            View childView = getChildAt(i);
            cWidth = childView.getMeasuredWidth();
            cHeight = childView.getMeasuredHeight();
            cParams = (MarginLayoutParams) childView.getLayoutParams();

            int cl = 0, ct = 0, cr = 0, cb = 0;
            cl = cParams.leftMargin + h;
            ct = (height - cHeight) / 2 - cParams.topMargin;
            // ct = cParams.topMargin;
            cr = cl + cWidth + cParams.rightMargin;
            cb = cHeight + ct;
            h = cr + jiange;
            childView.layout(cl, ct, cr, cb);
        }

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // TODO Auto-generated method stub
        if (xingWidth == 0 || xingHeight == 0) {
            return super.onTouchEvent(event);
        }
        int x = (int) event.getX();
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            if (!dealPosition(x)) {
                return super.onTouchEvent(event);
            }
            int number = x / (xingWidth + jiange);
            if (number + 1 > length) {
                return super.onTouchEvent(event);
            } else {
                dealHuaMian(number);
                // array.get(number).setBackgroundResource(R.drawable.xing1);
            }
            break;
        case MotionEvent.ACTION_UP:

            break;
        case MotionEvent.ACTION_MOVE:

            break;
        }
        return super.onTouchEvent(event);
    }

    /* * 处理坐标的问题 */
    private boolean dealPosition(int x) {
        int t = x % (jiange + xingWidth);
        if (t > xingWidth && t < xingWidth + jiange) {
            return false;
        } else {
            return true;
        }
    }

    /* * 处理显示的画面 */
    private void dealHuaMian(int p) {
        if (p < 0) {
            return;
        }
        if (p + 1 > length) {
            return;
        }
        if (p == position) {
            // 不需要任何处理
        } else if (p > position) {
            // 向前
            for (int i = position; i <= p - 1; i++) {
                TextView textView = array.get(i);
                textView.setBackgroundResource(pictures[1]);
                textView.setText("");
            }
            TextView tv = array.get(p);
            tv.setBackgroundResource(pictures[3]);
            tv.setText(String.valueOf(p));
        } else if (p < position) {
            // 向后
            for (int i = position; i >= p + 1; i--) {
                TextView textView = array.get(i);
                textView.setBackgroundResource(pictures[0]);
                textView.setText("");
            }
            TextView tv = array.get(p);
            if (p == 0) {
                tv.setBackgroundResource(pictures[2]);
            } else {
                tv.setBackgroundResource(pictures[3]);
            }
            tv.setText(String.valueOf(p));
        }
        position = p;
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        // TODO Auto-generated method stub
        Parcelable superState = super.onSaveInstanceState();
        SavedState ss = new SavedState(superState);
        ss.state = position;
        return ss;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        // TODO Auto-generated method stub
        SavedState ss = (SavedState) state;
        super.onRestoreInstanceState(ss.getSuperState());
        position = ss.state;
        refreshDate();
    }

    /* * 重新刷新数据 */
    private void refreshDate() {
        for (int i = 0; i < position; i++) {
            TextView textView = array.get(i);
            textView.setBackgroundResource(pictures[1]);
            textView.setText("");
        }
        TextView tv = array.get(position);
        if (position == 0) {
            tv.setBackgroundResource(pictures[2]);
        } else {
            tv.setBackgroundResource(pictures[3]);
        }
        tv.setText(String.valueOf(position));
    }

    static class SavedState extends BaseSavedState {
        private int state;

        SavedState(Parcelable superState) {
            super(superState);
        }

        private SavedState(Parcel in) {
            super(in);
            state = in.readInt();
        }

        @Override
        public void writeToParcel(Parcel out, int flags) {
            super.writeToParcel(out, flags);
            out.writeInt(state);
        }

        public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
            public SavedState createFromParcel(Parcel in) {
                return new SavedState(in);
            }

            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }
        };
    }

    // 接口
    /* * 取得当前的评分数目 */
    public int getRatingNumber() {
        return position;
    }

    /* * 设置图像 */
    public void setRatingPictures(int p1, int p2, int p3, int p4) {
        pictures[0] = p1;
        pictures[1] = p2;
        pictures[2] = p3;
        pictures[3] = p4;
    }

}
  1. 在res\values文件夹下建立attr.xml文件
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="Rating">
        <attr name="grayRating" format="reference" />
        <attr name="highRating" format="reference" />
        <attr name="graySchedule" format="reference" />
        <attr name="highSchedule" format="reference" />
        <attr name="jiange" format="integer" />
    </declare-styleable>

</resources>
  1. 布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" 
    android:orientation="vertical"
    xmlns:app="http://schemas.android.com/apk/res/com.example.ratingbar">
    <!--  xmlns:example="http://schemas.android.com/apk/res/com.example.ratingbar" -->

    <com.example.ratingbar.Rating
        android:id="@+id/rating1"
        app:jiange="10"
        app:graySchedule="@drawable/line_grey"
        app:highSchedule="@drawable/line_yellow"
        app:grayRating="@drawable/xing1"
        app:highRating="@drawable/xing2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <com.example.ratingbar.Rating
        android:id="@+id/rating2"
        app:jiange="10"
        app:graySchedule="@drawable/line_grey"
        app:highSchedule="@drawable/line_yellow"
        app:grayRating="@drawable/xing1"
        app:highRating="@drawable/xing2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <com.example.ratingbar.Rating
        android:id="@+id/rating3"
        app:jiange="10"
        app:graySchedule="@drawable/line_grey"
        app:highSchedule="@drawable/line_yellow"
        app:grayRating="@drawable/xing1"
        app:highRating="@drawable/xing2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <com.example.ratingbar.Rating
        android:id="@+id/rating4"
        app:jiange="10"
        app:graySchedule="@drawable/line_grey"
        app:highSchedule="@drawable/line_yellow"
        app:grayRating="@drawable/xing1"
        app:highRating="@drawable/xing2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <com.example.ratingbar.Rating
        android:id="@+id/rating5"
        app:jiange="10"
        app:graySchedule="@drawable/line_grey"
        app:highSchedule="@drawable/line_yellow"
        app:grayRating="@drawable/xing1"
        app:highRating="@drawable/xing2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <com.example.ratingbar.Rating
        android:id="@+id/rating6"
        app:jiange="10"
        app:graySchedule="@drawable/line_grey"
        app:highSchedule="@drawable/line_yellow"
        app:grayRating="@drawable/xing1"
        app:highRating="@drawable/xing2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />


</LinearLayout> 

欢迎大神们指教,免费下载代码地址

你可能感兴趣的:(RatingBar,自定义,ViewGroup)