制作像RatingBar

时间:2015-12-03 18:15:11

标签: android ontouchlistener motionevent ratingbar

我需要显示一个像ImageView一样的点阵(RatingBar),这里有一个例子:

enter image description here

这几乎是RatingBar旋转,但我有一个问题,这个应用程序是像素完美的,因此我需要在点之间添加一些余量。使用RatingBar无法做到这一点。由于我所面临的所有问题都试图使用我放弃的RatingBar而我决定制作自己的组件,到目前为止这是组件:

public class DotContainerView extends LinearLayout {

    @InjectView(R.id.view_dot_container)
    LinearLayout vDotContainer;

    private OnRatingBarChangeListener mListener;

    public DotContainerView(Context context) {
        super(context);
        initialize();
    }

    public DotContainerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initialize();
    }

    public DotContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initialize();
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public DotContainerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        initialize();
    }

    private void initialize() {
        View root = LayoutInflater.from(getContext()).inflate(R.layout.view_dot_container, this);
        ButterKnife.inject(this, root);
        setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                v.onTouchEvent(event);
                return false;
            }
        });
    }

    public void setRating(int rating) {
        for (int index = 0; index < rating; index++) {
            vDotContainer.getChildAt(index).setSelected(false);
        }
        for (int index = rating; index < 10; index++) {
            vDotContainer.getChildAt(index).setSelected(true);
        }
    }

    public void setOnRatingBarChangeListener(DotContainerView.OnRatingBarChangeListener listener) {
        mListener = listener;
    }

    //region OnTouch
    @OnTouch(R.id.fragment_brightness_control_dot_1)
    public boolean onDot1Touched() {
        setRating(1);
        mListener.onRatingChanged(this, 1, true);
        return true;
    }

    @OnTouch(R.id.fragment_brightness_control_dot_2)
    public boolean onDot2Touched() {
        setRating(2);
        mListener.onRatingChanged(this, 2, true);
        return true;
    }

    @OnTouch(R.id.fragment_brightness_control_dot_3)
    public boolean onDot3Touched() {
        setRating(3);
        mListener.onRatingChanged(this, 3, true);
        return true;
    }

    @OnTouch(R.id.fragment_brightness_control_dot_4)
    public boolean onDot4Touched() {
        setRating(4);
        mListener.onRatingChanged(this, 4, true);
        return true;
    }

    @OnTouch(R.id.fragment_brightness_control_dot_5)
    public boolean onDot5Touched() {
        setRating(5);
        mListener.onRatingChanged(this, 5, true);
        return true;
    }

    @OnTouch(R.id.fragment_brightness_control_dot_6)
    public boolean onDot6Touched() {
        setRating(6);
        mListener.onRatingChanged(this, 6, true);
        return true;
    }

    @OnTouch(R.id.fragment_brightness_control_dot_7)
    public boolean onDot7Touched() {
        setRating(7);
        mListener.onRatingChanged(this, 7, true);
        return true;
    }

    @OnTouch(R.id.fragment_brightness_control_dot_8)
    public boolean onDot8Touched() {
        setRating(8);
        mListener.onRatingChanged(this, 8, true);
        return true;
    }

    @OnTouch(R.id.fragment_brightness_control_dot_9)
    public boolean onDot9Touched() {
        setRating(9);
        mListener.onRatingChanged(this, 9, true);
        return true;
    }

    @OnTouch(R.id.fragment_brightness_control_dot_10)
    public boolean onDot10Touched() {
        setRating(10);
        mListener.onRatingChanged(this, 10, true);
        return true;
    }
    //endregion

    public interface OnRatingBarChangeListener {
        public void onRatingChanged(DotContainerView ratingBar, float value, boolean fromUser);
    }
}

此代码工作正常,如果我点击一个点,所有以前的点都会被选中。唯一的问题是,如果我将手指拖过点,他们就不会像RatingBar那样做出反应,只有当我点击每个点时。怎么解决这个问题?请避免告诉我&#34;使用RatingBar&#34;。

1 个答案:

答案 0 :(得分:0)

我最终做了这样的事情:

CMAKE_PREFIX_PATH

我知道那些可以改进的东西,但是对于那些想要快速做事而不会在import android.annotation.TargetApi; import android.content.Context; import android.os.Build; import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.widget.LinearLayout; import butterknife.ButterKnife; import butterknife.InjectView; /** * @author astinx * @since 0.2 * <p> * Simple widget that shows an array of dots which can be tapped like a {@link android.widget.RatingBar} */ public class DotContainerView extends LinearLayout implements View.OnTouchListener { @InjectView(R.id.view_dot_container) LinearLayout vDotContainer; private OnRatingBarChangeListener mListener; public DotContainerView(Context context) { super(context); initialize(); } public DotContainerView(Context context, AttributeSet attrs) { super(context, attrs); initialize(); } public DotContainerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initialize(); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public DotContainerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); initialize(); } private void initialize() { View root = LayoutInflater.from(getContext()).inflate(R.layout.view_dot_container, this); ButterKnife.inject(this, root); vDotContainer.setOnTouchListener(this); } public void setRating(int rating) { //If the rating = 5 for (int index = 0; index < rating; index++) { //This sets the children 10, 9, 8, 5... vDotContainer.getChildAt(Math.abs(index - 10) - 1).setSelected(true); } for (int index = rating; index < 10; index++) { //Ant this sets the children 6, 7, 8, 9, 10 vDotContainer.getChildAt(Math.abs(index - 10) - 1).setSelected(false); } } public void setOnRatingBarChangeListener(DotContainerView.OnRatingBarChangeListener listener) { mListener = listener; } @Override public boolean onTouch(View v, MotionEvent event) { float rawX = event.getX(); float rawY = event.getY(); setRating(rawX, rawY); return true; } @Override public boolean onInterceptHoverEvent(MotionEvent event) { float rawX = event.getX(); float rawY = event.getY(); setRating(rawX, rawY); return super.onInterceptHoverEvent(event); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { float rawX = event.getX(); float rawY = event.getY(); setRating(rawX, rawY); return false; } protected void setRating(float rawX, float rawY) { Log.d("DotContainer", "x=" + rawX + ";y=" + rawY); int dotIndexByCoords = 10 - findDotIndexByCoords(rawX, rawY); setRating(dotIndexByCoords); mListener.onRatingChanged(this, dotIndexByCoords, true); } private View findViewByIndex(int childIndex) { return vDotContainer.getChildAt(childIndex); } /** * Iterates all over the {@link LinearLayout} searching for the closest child to x,y * @param x The x axis * @param y The y axis * @return The index of the child, -1 if isn't found. */ private int findDotIndexByCoords(float x, float y) { for (int childIndex = 0; childIndex < vDotContainer.getChildCount(); childIndex++) { float y1 = vDotContainer.getChildAt(childIndex).getY(); float y2 = vDotContainer.getChildAt(childIndex + 1).getY(); if (y1 <= y && y <= y2) { Log.d("DotContainer", "Child no "+ childIndex); return childIndex; } } return -1; } public interface OnRatingBarChangeListener { public void onRatingChanged(DotContainerView ratingBar, float value, boolean fromUser); } } 吼叫和诅咒的人来说,这很快就会完成任务。基本上只是一个包含RatingBar数组的LinearLayout,每个数组都有一个可绘制的选择器,可以更改drawable是否被按下。这个类重写了方法ImageView并返回false,因此它会被连续调用,在这个方法中我们检查点击了哪个点。