/**打星题控件
*/
public class StarsView extends View {
private OnStarChangeListener mOnStarChangeListener;
private int starWidth;
private int starHeight;
private int starMargin;
private int starCount;
private int currIndex;// 当前星星索引,-1为未选中,取值为-1~starCount-1
private Paint paint;
private Bitmap starNomal, starSelect;
public StarsView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public StarsView(Context context) {
super(context);
init();
}
private void init() {
setOnTouchListener(mOnTouchListener);
paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(1);
}
public interface OnStarChangeListener {
/**
* 手指滑动到的星星
* @param index
*/
void onStarSlide(int index);
/**
* 选中星星
* @param index
*/
void onStarSelect(int index);
}
public void setOnStarChangeListener(
OnStarChangeListener onStarChangeListener) {
mOnStarChangeListener = onStarChangeListener;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
int height = starHeight + getPaddingTop() + getPaddingBottom();
int width = getPaddingStart() + getPaddingEnd() + starCount * starWidth
+ (starCount <= 1 ? 0 : starMargin * (starCount - 1));
setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth
: width, modeHeight == MeasureSpec.EXACTLY ? sizeHeight
: height);
}
public void setStarSizeMargin(int starWidth, int starHeight, int starMargin) {
this.starWidth = starWidth;
this.starHeight = starHeight;
this.starMargin = starMargin;
invalidate();
}
public void setStar(int starCount, int starIdx) {
this.starCount = starCount;
this.currIndex = starIdx;
invalidate();
}
public void setStar(int starIdx) {
this.currIndex = starIdx;
invalidate();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
starNomal = BitmapFactory.decodeResource(getResources(),
R.drawable.star_nomal);
starSelect = BitmapFactory.decodeResource(getResources(),
R.drawable.star_select);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
starNomal.recycle();
starSelect.recycle();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
for (int i = 0, startX = 0; i < starCount; i++) {
Bitmap bitmap = currIndex < i ? starNomal : starSelect;
if (i == 0) {
startX += isRtl ? getWidth() - getPaddingStart() - starWidth
: getPaddingStart();
} else {
startX += isRtl ? -starWidth - starMargin : starWidth
+ starMargin;
}
Rect src = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
Rect dst = new Rect(startX, getPaddingTop(), startX + starWidth,
getPaddingTop() + starHeight);
canvas.drawBitmap(bitmap, src, dst, paint);
}
}
private int getTouchIndex(int eventX) {
int selectIdx = -1;
boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
if (!isRtl && eventX < getPaddingStart()) {
return -1;
} else if (isRtl && eventX > getWidth() - getPaddingStart()) {
return -1;
}
for (int i = 0, startX = 0, endX = 0; i < starCount; i++) {
if (isRtl) {
startX = i == 0 ? getWidth() - getPaddingStart() - starWidth
- starMargin : startX - starWidth - starMargin;
endX = startX + starWidth + starMargin;
if (i == starCount - 1) {
startX = Integer.MIN_VALUE;
}
} else {
startX = i == 0 ? getPaddingStart() : endX;
endX = i == starCount - 1 ? Integer.MAX_VALUE : startX
+ starWidth + starMargin;
}
if (eventX >= startX & eventX <= endX) {
selectIdx = i;
break;
}
}
return selectIdx;
}
private OnTouchListener mOnTouchListener = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int selectIdx = getTouchIndex((int) (event.getX() + 0.5));
boolean needRefresh = selectIdx != currIndex;
if (needRefresh) {
setStar(selectIdx);
}
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
if (mOnStarChangeListener != null && needRefresh) {
mOnStarChangeListener.onStarSlide(selectIdx);
}
break;
case MotionEvent.ACTION_CANCEL:
if (mOnStarChangeListener != null) {
mOnStarChangeListener.onStarSelect(selectIdx);
}
break;
default:
break;
}
return true;
}
};
}
activity代码:
public class StarActivity extends Activity {
private TextView tv_msg;
private StarsView starsView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_star);
tv_msg = (TextView) findViewById(R.id.tv_msg);
LinearLayout contaner = (LinearLayout) findViewById(R.id.contaner);
starsView = new StarsView(this);
starsView.setOnStarChangeListener(mOnStarChangeListener);
tv_msg.setText("五星级神机,送女友很有面子");
starsView.setStar(5, 0);
starsView.setStarSizeMargin(80, 80, 20);
starsView.setPadding(60, 5, 60, 5);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
contaner.addView(starsView, lp);
}
private OnStarChangeListener mOnStarChangeListener = new OnStarChangeListener() {
@Override
public void onStarSlide(int index) {
String msg = "";
switch (index) {
case 0:
msg = "五星级神机,送女友很有面子";
break;
case 1:
msg = "高大上,丈母娘愛不釋手";
break;
case 2:
msg = "还行吧,凑合着用";
break;
case 3:
msg = "一般般";
break;
case 4:
msg = "有点垃圾,nainai的,无语了。。。";
break;
default:
break;
}
tv_msg.setText(msg);
}
@Override
public void onStarSelect(int index) {
Log.e("zx", "選中星星:" + index);
}
};
}
布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="20dp"
android:paddingRight="20dp">
<TextView
android:id="@+id/tv_titile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="你觉得XX手机怎样啊?"
android:layout_marginLeft="20dp"/>
<LinearLayout
android:id="@+id/contaner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp">
</LinearLayout>
<TextView android:id="@+id/tv_msg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
/>
</LinearLayout>
效果图