我需要显示一个像ImageView
一样的点阵(RatingBar
),这里有一个例子:
这几乎是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;。
答案 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,因此它会被连续调用,在这个方法中我们检查点击了哪个点。