SmoothCheckBox类
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.Checkable;
/**
* Author : andy
* Date : 16/1/21 11:28
* Email : andyxialm@gmail.com
* Github : github.com/andyxialm
* Description : A custom CheckBox with animation for Android
*/
public class SmoothCheckBox extends View implements Checkable {
private static final String KEY_INSTANCE_STATE = "InstanceState";
private static final int COLOR_TICK = Color.WHITE;
private static final int COLOR_UNCHECKED = Color.WHITE;
private static final int COLOR_CHECKED = Color.parseColor("#FB4846");
private static final int COLOR_FLOOR_UNCHECKED = Color.parseColor("#DFDFDF");
private static final int DEF_DRAW_SIZE = 25;
private static final int DEF_ANIM_DURATION = 300;
private Paint mPaint, mTickPaint, mFloorPaint;
private Point[] mTickPoints;
private Point mCenterPoint;
private Path mTickPath;
private float mLeftLineDistance, mRightLineDistance, mDrewDistance;
private float mScaleVal = 1.0f, mFloorScale = 1.0f;
private int mWidth, mAnimDuration, mStrokeWidth;
private int mCheckedColor, mUnCheckedColor, mFloorColor, mFloorUnCheckedColor;
private boolean mChecked;
private boolean mTickDrawing;
private OnCheckedChangeListener mListener;
public SmoothCheckBox(Context context) {
this(context, null);
}
public SmoothCheckBox(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SmoothCheckBox(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SmoothCheckBox(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(attrs);
}
private void init(AttributeSet attrs) {
TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.SmoothCheckBox);
int tickColor = ta.getColor(R.styleable.SmoothCheckBox_color_tick, COLOR_TICK);
mAnimDuration = ta.getInt(R.styleable.SmoothCheckBox_duration, DEF_ANIM_DURATION);
mFloorColor = ta.getColor(R.styleable.SmoothCheckBox_color_unchecked_stroke, COLOR_FLOOR_UNCHECKED);
mCheckedColor = ta.getColor(R.styleable.SmoothCheckBox_color_checked, COLOR_CHECKED);
mUnCheckedColor = ta.getColor(R.styleable.SmoothCheckBox_color_unchecked, COLOR_UNCHECKED);
mStrokeWidth = ta.getDimensionPixelSize(R.styleable.SmoothCheckBox_stroke_width, TextSizeUtils.dip2px(getContext(), 0));
ta.recycle();
mFloorUnCheckedColor = mFloorColor;
mTickPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTickPaint.setStyle(Paint.Style.STROKE);
mTickPaint.setStrokeCap(Paint.Cap.ROUND);
mTickPaint.setColor(tickColor);
mFloorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mFloorPaint.setStyle(Paint.Style.FILL);
mFloorPaint.setColor(mFloorColor);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(mCheckedColor);
mTickPath = new Path();
mCenterPoint = new Point();
mTickPoints = new Point[3];
mTickPoints[0] = new Point();
mTickPoints[1] = new Point();
mTickPoints[2] = new Point();
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
toggle();
mTickDrawing = false;
mDrewDistance = 0;
if (isChecked()) {
startCheckedAnimation();
} else {
startUnCheckedAnimation();
}
}
});
}
@Override
protected Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle();
bundle.putParcelable(KEY_INSTANCE_STATE, super.onSaveInstanceState());
bundle.putBoolean(KEY_INSTANCE_STATE, isChecked());
return bundle;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (state instanceof Bundle) {
Bundle bundle = (Bundle) state;
boolean isChecked = bundle.getBoolean(KEY_INSTANCE_STATE);
setChecked(isChecked);
super.onRestoreInstanceState(bundle.getParcelable(KEY_INSTANCE_STATE));
return;
}
super.onRestoreInstanceState(state);
}
@Override
public boolean isChecked() {
return mChecked;
}
@Override
public void toggle() {
this.setChecked(!isChecked());
}
@Override
public void setChecked(boolean checked) {
mChecked = checked;
reset();
invalidate();
if (mListener != null) {
mListener.onCheckedChanged(SmoothCheckBox.this, mChecked);
}
}
/**
* checked with animation
*
* @param checked checked
* @param animate change with animation
*/
public void setChecked(boolean checked, boolean animate) {
if (animate) {
mTickDrawing = false;
mChecked = checked;
mDrewDistance = 0f;
if (checked) {
startCheckedAnimation();
} else {
startUnCheckedAnimation();
}
if (mListener != null) {
mListener.onCheckedChanged(SmoothCheckBox.this, mChecked);
}
} else {
this.setChecked(checked);
}
}
private void reset() {
mTickDrawing = true;
mFloorScale = 1.0f;
mScaleVal = isChecked() ? 0f : 1.0f;
mFloorColor = isChecked() ? mCheckedColor : mFloorUnCheckedColor;
mDrewDistance = isChecked() ? (mLeftLineDistance + mRightLineDistance) : 0;
}
private int measureSize(int measureSpec) {
int defSize = TextSizeUtils.dip2px(getContext(), DEF_DRAW_SIZE);
int specSize = MeasureSpec.getSize(measureSpec);
int specMode = MeasureSpec.getMode(measureSpec);
int result = 0;
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
case MeasureSpec.AT_MOST:
result = Math.min(defSize, specSize);
break;
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(measureSize(widthMeasureSpec), measureSize(heightMeasureSpec));
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
mWidth = getMeasuredWidth();
mStrokeWidth = (mStrokeWidth == 0 ? getMeasuredWidth() / 10 : mStrokeWidth);
mStrokeWidth = mStrokeWidth > getMeasuredWidth() / 5 ? getMeasuredWidth() / 5 : mStrokeWidth;
mStrokeWidth = (mStrokeWidth < 3) ? 3 : mStrokeWidth;
mCenterPoint.x = mWidth / 2;
mCenterPoint.y = getMeasuredHeight() / 2;
mTickPoints[0].x = Math.round((float) getMeasuredWidth() / 30 * 7);
mTickPoints[0].y = Math.round((float) getMeasuredHeight() / 30 * 14);
mTickPoints[1].x = Math.round((float) getMeasuredWidth() / 30 * 13);
mTickPoints[1].y = Math.round((float) getMeasuredHeight() / 30 * 20);
mTickPoints[2].x = Math.round((float) getMeasuredWidth() / 30 * 22);
mTickPoints[2].y = Math.round((float) getMeasuredHeight() / 30 * 10);
mLeftLineDistance = (float) Math.sqrt(Math.pow(mTickPoints[1].x - mTickPoints[0].x, 2) +
Math.pow(mTickPoints[1].y - mTickPoints[0].y, 2));
mRightLineDistance = (float) Math.sqrt(Math.pow(mTickPoints[2].x - mTickPoints[1].x, 2) +
Math.pow(mTickPoints[2].y - mTickPoints[1].y, 2));
mTickPaint.setStrokeWidth(mStrokeWidth);
}
@Override
protected void onDraw(Canvas canvas) {
drawBorder(canvas);
drawCenter(canvas);
drawTick(canvas);
}
private void drawCenter(Canvas canvas) {
mPaint.setColor(mUnCheckedColor);
float radius = (mCenterPoint.x - mStrokeWidth) * mScaleVal;
canvas.drawCircle(mCenterPoint.x, mCenterPoint.y, radius, mPaint);
}
private void drawBorder(Canvas canvas) {
mFloorPaint.setColor(mFloorColor);
int radius = mCenterPoint.x;
canvas.drawCircle(mCenterPoint.x, mCenterPoint.y, radius * mFloorScale, mFloorPaint);
}
private void drawTick(Canvas canvas) {
if (mTickDrawing && isChecked()) {
drawTickPath(canvas);
}
}
private void drawTickPath(Canvas canvas) {
mTickPath.reset();
// draw left of the tick
if (mDrewDistance < mLeftLineDistance) {
float step = (mWidth / 20.0f) < 3 ? 3 : (mWidth / 20.0f);
mDrewDistance += step;
float stopX = mTickPoints[0].x + (mTickPoints[1].x - mTickPoints[0].x) * mDrewDistance / mLeftLineDistance;
float stopY = mTickPoints[0].y + (mTickPoints[1].y - mTickPoints[0].y) * mDrewDistance / mLeftLineDistance;
mTickPath.moveTo(mTickPoints[0].x, mTickPoints[0].y);
mTickPath.lineTo(stopX, stopY);
canvas.drawPath(mTickPath, mTickPaint);
if (mDrewDistance > mLeftLineDistance) {
mDrewDistance = mLeftLineDistance;
}
} else {
mTickPath.moveTo(mTickPoints[0].x, mTickPoints[0].y);
mTickPath.lineTo(mTickPoints[1].x, mTickPoints[1].y);
canvas.drawPath(mTickPath, mTickPaint);
// draw right of the tick
if (mDrewDistance < mLeftLineDistance + mRightLineDistance) {
float stopX = mTickPoints[1].x + (mTickPoints[2].x - mTickPoints[1].x) * (mDrewDistance - mLeftLineDistance) / mRightLineDistance;
float stopY = mTickPoints[1].y - (mTickPoints[1].y - mTickPoints[2].y) * (mDrewDistance - mLeftLineDistance) / mRightLineDistance;
mTickPath.reset();
mTickPath.moveTo(mTickPoints[1].x, mTickPoints[1].y);
mTickPath.lineTo(stopX, stopY);
canvas.drawPath(mTickPath, mTickPaint);
float step = (mWidth / 20) < 3 ? 3 : (mWidth / 20);
mDrewDistance += step;
} else {
mTickPath.reset();
mTickPath.moveTo(mTickPoints[1].x, mTickPoints[1].y);
mTickPath.lineTo(mTickPoints[2].x, mTickPoints[2].y);
canvas.drawPath(mTickPath, mTickPaint);
}
}
// invalidate
if (mDrewDistance < mLeftLineDistance + mRightLineDistance) {
postDelayed(new Runnable() {
@Override
public void run() {
postInvalidate();
}
}, 10);
}
}
private void startCheckedAnimation() {
ValueAnimator animator = ValueAnimator.ofFloat(1.0f, 0f);
animator.setDuration(mAnimDuration / 3 * 2);
animator.setInterpolator(new LinearInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mScaleVal = (float) animation.getAnimatedValue();
mFloorColor = getGradientColor(mUnCheckedColor, mCheckedColor, 1 - mScaleVal);
postInvalidate();
}
});
animator.start();
ValueAnimator floorAnimator = ValueAnimator.ofFloat(1.0f, 0.8f, 1.0f);
floorAnimator.setDuration(mAnimDuration);
floorAnimator.setInterpolator(new LinearInterpolator());
floorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mFloorScale = (float) animation.getAnimatedValue();
postInvalidate();
}
});
floorAnimator.start();
drawTickDelayed();
}
private void startUnCheckedAnimation() {
ValueAnimator animator = ValueAnimator.ofFloat(0f, 1.0f);
animator.setDuration(mAnimDuration);
animator.setInterpolator(new LinearInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mScaleVal = (float) animation.getAnimatedValue();
mFloorColor = getGradientColor(mCheckedColor, mFloorUnCheckedColor, mScaleVal);
postInvalidate();
}
});
animator.start();
ValueAnimator floorAnimator = ValueAnimator.ofFloat(1.0f, 0.8f, 1.0f);
floorAnimator.setDuration(mAnimDuration);
floorAnimator.setInterpolator(new LinearInterpolator());
floorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mFloorScale = (float) animation.getAnimatedValue();
postInvalidate();
}
});
floorAnimator.start();
}
private void drawTickDelayed() {
postDelayed(new Runnable() {
@Override
public void run() {
mTickDrawing = true;
postInvalidate();
}
}, mAnimDuration);
}
private static int getGradientColor(int startColor, int endColor, float percent) {
int startA = Color.alpha(startColor);
int startR = Color.red(startColor);
int startG = Color.green(startColor);
int startB = Color.blue(startColor);
int endA = Color.alpha(endColor);
int endR = Color.red(endColor);
int endG = Color.green(endColor);
int endB = Color.blue(endColor);
int currentA = (int) (startA * (1 - percent) + endA * percent);
int currentR = (int) (startR * (1 - percent) + endR * percent);
int currentG = (int) (startG * (1 - percent) + endG * percent);
int currentB = (int) (startB * (1 - percent) + endB * percent);
return Color.argb(currentA, currentR, currentG, currentB);
}
public void setOnCheckedChangeListener(OnCheckedChangeListener l) {
this.mListener = l;
}
public interface OnCheckedChangeListener {
void onCheckedChanged(SmoothCheckBox checkBox, boolean isChecked);
}
}
TextSizeUtils
public class TextSizeUtils {
/**
* 将px值转换为dip或dp值,保证尺寸大小不变
*
* @param pxValue
* (DisplayMetrics类中属性density)
* @return
*/
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
/**
* 将dip或dp值转换为px值,保证尺寸大小不变
*
* @param dipValue
* (DisplayMetrics类中属性density)
* @return
*/
public static int dip2px(Context context, float dipValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
/**
* 将px值转换为sp值,保证文字大小不变
*
* @param pxValue
* (DisplayMetrics类中属性scaledDensity)
* @return
*/
public static int px2sp(Context context, float pxValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (pxValue / fontScale + 0.5f);
}
/**
* 将sp值转换为px值,保证文字大小不变
*
* @param spValue
* (DisplayMetrics类中属性scaledDensity)
* @return
*/
public static int sp2px(Context context, float spValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
}
ExpandableListAdapter
public class ExpandableListAdapter extends BaseExpandableListAdapter {
private Context context;
private GoodBean goodBean;
private UpdateView updateViewListener;
protected static final int KEY_DATA = 0xFFF11133;
public ExpandableListAdapter(Context context, GoodBean goodBean) {
this.context = context;
this.goodBean = goodBean;
}
@Override
public int getGroupCount() {
return goodBean.getContent().size();
}
@Override
public int getChildrenCount(int groupPosition) {
return goodBean.getContent().get(groupPosition).getGooddetail().size();
}
@Override
public Object getGroup(int groupPosition) {
return goodBean.getContent().get(groupPosition);
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return goodBean.getContent().get(groupPosition).getGooddetail().get(childPosition);
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
GroupViewHolder holder = null;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.item_shopingcargroup, parent, false);
holder = new GroupViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (GroupViewHolder) convertView.getTag();
}
holder.cbGroupItem.setTag(groupPosition);
holder.cbGroupItem.setOnClickListener(listener);
holder.tvPosition.setText(goodBean.getContent().get(groupPosition).getAdress());
if (goodBean.getContent().get(groupPosition).isselected()) {
if (!holder.cbGroupItem.isChecked()) {
holder.cbGroupItem.setChecked(true);
}
} else {
holder.cbGroupItem.setChecked(false);
}
return convertView;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
ChildViewHolder holder = null;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.item_shopingcarchild, parent, false);
holder = new ChildViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ChildViewHolder) convertView.getTag();
}
String tag = groupPosition + "," + childPosition;
holder.cbItem.setTag(tag);
holder.tvReduce.setTag(tag);
holder.tvAdd.setTag(tag);
holder.ivDelete.setTag(tag);
holder.ivIcon.setTag(tag);
holder.cbItem.setOnClickListener(listener);
holder.tvReduce.setOnClickListener(listener);
final ChildViewHolder finalHolder = holder;
holder.tvAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//添加商品数量
updateViewListener.callBackImg(finalHolder.ivIcon);
String tag = view.getTag().toString();
String[] split;
int groupId = 0;
int childId = 0;
int allCount = goodBean.getAllcount();
int allMoney = goodBean.getAllmoney();
if (tag.contains(",")) {
split = tag.split(",");
groupId = Integer.parseInt(split[0]);
childId = Integer.parseInt(split[1]);
}
String var2 = goodBean.getContent().get(groupId).getGooddetail().get(childId).getCount();
goodBean.getContent().get(groupId).getGooddetail().get(childId).setCount(addCount(var2));
allMoney = goodBean.getAllmoney();
if (goodBean.getContent().get(groupId).getGooddetail().get(childId).isselected()) {
allMoney += Integer.valueOf(goodBean.getContent().get(groupId).getGooddetail().get(childId).getPrice());
updateViewListener.update(goodBean.isAllSelect(), allCount, allMoney);
}
goodBean.setAllmoney(allMoney);
notifyDataSetChanged();
}
});
holder.ivDelete.setOnClickListener(listener);
if (goodBean.getContent().get(groupPosition).getGooddetail().get(childPosition).isselected()) {
holder.cbItem.setChecked(true);
} else {
holder.cbItem.setChecked(false);
}
holder.tvPrice.setText("¥" + goodBean.getContent().get(groupPosition).getGooddetail().get(childPosition).getPrice());
EditTextWatcher textWatcher = (EditTextWatcher) holder.etCount.getTag(KEY_DATA);
if (textWatcher != null) {
holder.etCount.removeTextChangedListener(textWatcher);
}
holder.etCount.setText(String.valueOf(goodBean.getContent().get(groupPosition).getGooddetail().get(childPosition).getCount()));
EditTextWatcher watcher = new EditTextWatcher(goodBean.getContent().get(groupPosition).getGooddetail().get(childPosition));
holder.etCount.setTag(KEY_DATA, watcher);
holder.etCount.addTextChangedListener(watcher);
holder.etCount.setText(goodBean.getContent().get(groupPosition).getGooddetail().get(childPosition).getCount());
return convertView;
}
/**
* EditText内容改变的监听
*/
class EditTextWatcher implements TextWatcher {
private GoodBean.ContentBean.GooddetailBean Gooddetail;
public EditTextWatcher(GoodBean.ContentBean.GooddetailBean item) {
this.Gooddetail = item;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (!TextUtils.isEmpty(s.toString().trim())) {
String textNum = s.toString().trim();
Gooddetail.setCount(textNum);
}
}
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return false;
}
View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
SmoothCheckBox checkBox;
String tag = v.getTag().toString();
String[] split;
int groupId = 0;
int childId = 0;
int childSize = 0;
int groupPosition = 0;
int allCount = goodBean.getAllcount();
int allMoney = goodBean.getAllmoney();
if (tag.contains(",")) {
split = tag.split(",");
groupId = Integer.parseInt(split[0]);
childId = Integer.parseInt(split[1]);
} else {
groupPosition = Integer.parseInt(tag);
childSize = goodBean.getContent().get(groupPosition).getGooddetail().size();
}
switch (v.getId()) {
case R.id.cb_GroupItem:
checkBox = (SmoothCheckBox) v;
goodBean.getContent().get(groupPosition).setIsselected(!checkBox.isChecked());
if (!checkBox.isChecked()) {
for (int i = 0; i < childSize; i++) {
if (!goodBean.getContent().get(groupPosition).getGooddetail().get(i).isselected()) {
allCount++;
goodBean.getContent().get(groupPosition).getGooddetail().get(i).setIsselected(!checkBox.isChecked());
allMoney += Integer.valueOf(goodBean.getContent().get(groupPosition).getGooddetail().get(i).getCount())
* Integer.valueOf(goodBean.getContent().get(groupPosition).getGooddetail().get(i).getPrice());
}
}
} else {
allCount -= childSize;
for (int i = 0; i < childSize; i++) {
goodBean.getContent().get(groupPosition).getGooddetail().get(i).setIsselected(!checkBox.isChecked());
allMoney -= Integer.valueOf(goodBean.getContent().get(groupPosition).getGooddetail().get(i).getCount())
* Integer.valueOf(goodBean.getContent().get(groupPosition).getGooddetail().get(i).getPrice());
}
}
int cm = 0;
//判断是否所有的父item都被选中,决定全选按钮状态
for (int i = 0; i < goodBean.getContent().size(); i++) {
if (goodBean.getContent().get(i).isselected()) {
cm++;
}
}
if (cm == goodBean.getContent().size()) {
goodBean.setAllSelect(true);
} else {
goodBean.setAllSelect(false);
}
goodBean.setAllcount(allCount);
goodBean.setAllmoney(allMoney);
notifyDataSetChanged();
updateViewListener.update(goodBean.isAllSelect(), allCount, allMoney);
break;
//单个子项item被点击
case R.id.cb_Item:
checkBox = (SmoothCheckBox) v;
int n = 0;
int m = 0;
goodBean.getContent().get(groupId).getGooddetail().get(childId).setIsselected(!checkBox.isChecked());
//遍历父item所有数据,统计被选中的item数量
for (int i = 0; i < goodBean.getContent().get(groupId).getGooddetail().size(); i++) {
if (goodBean.getContent().get(groupId).getGooddetail().get(i).isselected()) {
n++;
}
}
//判断是否所有的子item都被选中,决定父item状态
if (n == goodBean.getContent().get(groupId).getGooddetail().size()) {
goodBean.getContent().get(groupId).setIsselected(true);
} else {
goodBean.getContent().get(groupId).setIsselected(false);
}
//判断是否所有的父item都被选中,决定全选按钮状态
for (int i = 0; i < goodBean.getContent().size(); i++) {
if (goodBean.getContent().get(i).isselected()) {
m++;
}
}
if (m == goodBean.getContent().size()) {
goodBean.setAllSelect(true);
} else {
goodBean.setAllSelect(false);
}
//判断子item状态,更新结算总商品数和合计Money
if (!checkBox.isChecked()) {
allCount++;
allMoney += Integer.valueOf(goodBean.getContent().get(groupId).getGooddetail().get(childId).getCount())
* Integer.valueOf(goodBean.getContent().get(groupId).getGooddetail().get(childId).getPrice());
} else {
allCount--;
allMoney -= Integer.valueOf(goodBean.getContent().get(groupId).getGooddetail().get(childId).getCount())
* Integer.valueOf(goodBean.getContent().get(groupId).getGooddetail().get(childId).getPrice());
}
goodBean.setAllcount(allCount);
goodBean.setAllmoney(allMoney);
notifyDataSetChanged();
updateViewListener.update(goodBean.isAllSelect(), allCount, allMoney);
break;
case R.id.tv_Reduce:
//减少商品数量
String var1 = goodBean.getContent().get(groupId).getGooddetail().get(childId).getCount();
if (Integer.valueOf(var1) > 1) {
goodBean.getContent().get(groupId).getGooddetail().get(childId).setCount(reduceCount(var1));
if (goodBean.getContent().get(groupId).getGooddetail().get(childId).isselected()) {
allMoney -= Integer.valueOf(goodBean.getContent().get(groupId).getGooddetail().get(childId).getPrice());
updateViewListener.update(goodBean.isAllSelect(), allCount, allMoney);
}
goodBean.setAllmoney(allMoney);
notifyDataSetChanged();
}
break;
/* case R.id.tv_Add:
//添加商品数量
String var2 = goodBean.getContent().get(groupId).getGooddetail().get(childId).getCount();
goodBean.getContent().get(groupId).getGooddetail().get(childId).setCount(addCount(var2));
allMoney = goodBean.getAllmoney();
if (goodBean.getContent().get(groupId).getGooddetail().get(childId).isselected()) {
allMoney += Integer.valueOf(goodBean.getContent().get(groupId).getGooddetail().get(childId).getPrice());
updateViewListener.update(goodBean.isAllSelect(), allCount, allMoney);
}
goodBean.setAllmoney(allMoney);
notifyDataSetChanged();
break;*/
case R.id.iv_Delete:
Toast.makeText(context, "删除", Toast.LENGTH_SHORT).show();
break;
}
}
};
public void setChangedListener(UpdateView listener) {
if (updateViewListener == null) {
this.updateViewListener = listener;
}
}
private String addCount(String var2) {
Integer inte = Integer.valueOf(var2);
inte++;
return inte + "";
}
private String reduceCount(String var) {
Integer integer = Integer.valueOf(var);
if (integer > 1) {
integer--;
}
return integer + "";
}
static class GroupViewHolder {
SmoothCheckBox cbGroupItem;
TextView tvPosition;
GroupViewHolder(View view) {
cbGroupItem = (SmoothCheckBox) view.findViewById(R.id.cb_GroupItem);
tvPosition = (TextView) view.findViewById(R.id.tv_Position);
}
}
static class ChildViewHolder {
SmoothCheckBox cbItem;
TextView tvPrice;
EditText etCount;
TextView tvReduce;
TextView tvAdd;
ImageView ivDelete;
ImageView ivIcon;
ChildViewHolder(View view) {
cbItem = (SmoothCheckBox) view.findViewById(R.id.cb_Item);
tvPrice = (TextView) view.findViewById(R.id.tv_Price);
etCount = (EditText) view.findViewById(R.id.et_Count);
tvReduce = (TextView) view.findViewById(R.id.tv_Reduce);
tvAdd = (TextView) view.findViewById(R.id.tv_Add);
ivDelete = (ImageView) view.findViewById(R.id.iv_Delete);
ivIcon = (ImageView) view.findViewById(R.id.iv_icon);
}
}
}
接口UpdateView
public interface UpdateView {
void update(boolean isAllSelected, int count, int price);
void callBackImg(ImageView goodsImg);
}
购物车布局,粘贴进去就行
<RelativeLayout
android:id="@+id/rl_curve"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ExpandableListView
android:id="@+id/expandableListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="49dp"
android:divider="@null"></ExpandableListView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="49dp"
android:layout_alignParentBottom="true"
android:background="@android:color/white"
android:gravity="center_vertical"
android:orientation="horizontal">
<com.powersen.myshoppingcar.SmoothCheckBox
android:id="@+id/cb_SelectAll"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginLeft="15dp" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_weight="0.69"
android:text="全选"
android:textColor="#333333"
android:textSize="15sp" />
<ImageView
android:id="@+id/iv_bezier_curve_shopping_cart"
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/menu_shop_car_selected" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="end"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="合计"
android:textColor="#333333"
android:textSize="15sp" />
<TextView
android:id="@+id/tv_AllMoney"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="¥0"
android:textColor="#FE3824"
android:textSize="15sp" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="运费:¥0"
android:textColor="#999999"
android:textSize="11sp" />
</LinearLayout>
<Button
android:id="@+id/btn_Settlement"
android:layout_width="95dp"
android:layout_height="match_parent"
android:layout_marginLeft="15dp"
android:background="#FE3824"
android:text="结算(0)"
android:textColor="@android:color/white"
android:textSize="16sp" />
</LinearLayout>
</RelativeLayout>
二级列表的父布局与子布局
item_shopingcarchild
<?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="wrap_content"
android:background="@android:color/white"
android:orientation="horizontal"
android:paddingBottom="15dp"
android:paddingRight="15dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:paddingLeft="15dp"
android:paddingRight="17dp">
<com.powersen.myshoppingcar.SmoothCheckBox
android:id="@+id/cb_Item"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/divide_line" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="78dp"
android:layout_height="78dp"
android:src="@drawable/agc" />
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginLeft="15dp"
android:layout_marginTop="8dp"
android:layout_weight="1">
<TextView
android:id="@+id/tv_Reduce"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginTop="7dp"
android:background="@drawable/selector_shopping_cart_subtract"
android:gravity="center"
android:text="-"
android:textColor="@color/text_666666"
android:textSize="15sp" />
<EditText
android:id="@+id/et_Count"
android:layout_width="49dp"
android:layout_height="30dp"
android:layout_alignTop="@+id/tv_Reduce"
android:layout_marginBottom="1dp"
android:layout_toRightOf="@+id/tv_Reduce"
android:background="@drawable/bg_input_box"
android:gravity="center"
android:inputType="number"
android:maxLength="6"
android:text="1"
android:textColor="@color/text_666666"
android:textCursorDrawable="@null"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_Add"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignTop="@+id/tv_Reduce"
android:layout_toRightOf="@id/et_Count"
android:background="@drawable/selector_shopping_cart_add"
android:gravity="center"
android:text="+"
android:textColor="@color/text_666666"
android:textSize="15sp" />
<TextView
android:id="@+id/tv_Price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:text="¥899"
android:textColor="#FE3824"
android:textSize="13sp" />
</RelativeLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="18dp"
android:gravity="end"
android:orientation="vertical">
</LinearLayout>
<ImageView
android:id="@+id/iv_Delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginTop="5dp"
android:src="@drawable/icon_delete" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
item_shopingcargroup
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white">
<View
android:layout_width="match_parent"
android:background="@color/divide_line"
android:layout_height="3dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:padding="15dp">
<com.powersen.myshoppingcar.SmoothCheckBox
android:id="@+id/cb_GroupItem"
android:layout_width="24dp"
android:layout_height="24dp"/>
<TextView
android:id="@+id/tv_Position"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="郑州保税仓发货"
android:textColor="#333333"
android:textSize="15sp"
android:layout_marginLeft="15dp"
android:drawableLeft="@drawable/icon_positionicon"
android:drawablePadding="3dp"/>
</LinearLayout>
</LinearLayout>
两个selector文件,在drawble文件夹下
selector_shopping_cart_subtract
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android = "http://schemas.android.com/apk/res/android" >
<item android:drawable = "@drawable/btn_shopping_cart_subtract_press" android:state_checked = "true" />
<item android:drawable = "@drawable/btn_shopping_cart_subtract_press" android:state_pressed = "true" />
<item android:drawable = "@drawable/btn_shopping_cart_subtract_press" android:state_selected = "true" />
<item android:drawable = "@drawable/btn_shopping_cart_subtract_normal" />
</selector >
selector_shopping_cart_add
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android = "http://schemas.android.com/apk/res/android" >
<item android:drawable = "@drawable/btn_shopping_cart_add_press" android:state_checked = "true" />
<item android:drawable = "@drawable/btn_shopping_cart_add_press" android:state_pressed = "true" />
<item android:drawable = "@drawable/btn_shopping_cart_add_press" android:state_selected = "true" />
<item android:drawable = "@drawable/btn_shopping_cart_add_normal" />
</selector >
各种资源文件
colors
<color name="colorhui2">#cac2c2</color>
<color name="colorhui3">#F3F5F7</color>
<color name="software_textColor_selected">#FF0000</color>
<color name="software_textColor_unselected">#838384</color>
<color name="divide_line">#eeeeee</color>
<color name = "text_666666" >#666666</color >
styles
<declare-styleable name="SmoothCheckBox">
<attr name="duration" format="integer"/>
<attr name="stroke_width" format="dimension"/>
<attr name="color_tick" format="color"/>
<attr name="color_checked" format="color"/>
<attr name="color_unchecked" format="color"/>
<attr name="color_unchecked_stroke" format="color"/>
</declare-styleable>
----布局里的SmoothCheckBox一定是自己的包名,注意