购物车模板

mainlayout

<include layout="@layout/include_toolbar" />

<ExpandableListView
android:id="@+id/expandableListView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:scrollbars="none"
android:divider="@null"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/divide_line"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="49dp"
android:background="@android:color/white"
android:gravity="center_vertical"
android:orientation="horizontal">

<!--<com.xp.shoppingcart.SmoothCheckBox-->
<!--android:id="@+id/cb_select_all"-->
<!--android:layout_width="24dp"-->
<!--android:layout_height="24dp"-->
<!--android:layout_marginLeft="15dp" />-->
<com.example.administrator.fanggouwuche.SmoothCheckBox
android:id="@+id/cb_select_all"
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" />

<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_all_money"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="¥0"
android:textColor="#FE3824"
android:textSize="15sp" />
</LinearLayout>

<TextView
android:id="@+id/tv_transport"
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>

标题
<TextView
android:id="@+id/tv_toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="购物车"
android:textColor="@android:color/white"
android:textSize="19sp" />

子条目layout
<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:id="@+id/ll_check"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:paddingLeft="15dp"
android:paddingRight="17dp">

<!--<com.xp.shoppingcart.SmoothCheckBox-->
<!--android:id="@+id/cb_item"-->
<!--android:layout_width="24dp"-->
<!--android:layout_height="24dp"-->
<!--android:layout_gravity="center_vertical" />-->
<com.example.administrator.fanggouwuche.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/img_icon"
android:layout_width="78dp"
android:layout_height="78dp"
android:src="@mipmap/ic_phone" />

<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_good_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="" />

<TextView
android:id="@+id/tv_reduce"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_below="@id/tv_good_name"
android:layout_marginTop="6dp"
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/img_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginTop="5dp"
android:src="@mipmap/icon_delete" />

</LinearLayout>
</LinearLayout>

</LinearLayout>

grouplayout

<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="vertical">

<View
android:layout_width="match_parent"
android:layout_height="3dp"
android:background="@color/divide_line" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:padding="15dp">

<!--<com.xp.shoppingcart.SmoothCheckBox-->
<!--android:id="@+id/cb_group_item"-->
<!--android:layout_width="24dp"-->
<!--android:layout_height="24dp" />-->
<com.example.administrator.fanggouwuche.SmoothCheckBox
android:id="@+id/cb_group_item"
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_marginLeft="15dp"
android:layout_weight="1"
android:drawableLeft="@mipmap/ic_position"
android:drawablePadding="3dp"
android:text="京东旗舰店发货"
android:textColor="#333333"
android:textSize="15sp" />
</LinearLayout>
</LinearLayout>

import android.app.Activity;
import android.content.res.AssetManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.AbsListView;
import android.widget.Button;
import android.widget.ExpandableListView;
import android.widget.TextView;

import com.google.gson.Gson;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class MainActivity extends AppCompatActivity implements UpdateView, View.OnClickListener {

private ExpandableListView mExpandableListView;
private SmoothCheckBox mCbSelectAll;
private TextView mTvAllMoney;
private Button mBtnBuy;
StringBuffer stringBuffer;
GoodBean goodBean;
ExpandableListAdapter mAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();
initEvent();
}

private void initEvent() {
mCbSelectAll.setOnClickListener(this);
}

private void initData() {
//读取数据解析
AssetManager assetManager = getAssets();
try {
InputStream is = assetManager.open("data.json");
BufferedReader br = new BufferedReader(new InputStreamReader(is));
stringBuffer = new StringBuffer();
String str;
while ((str = br.readLine()) != null) {
stringBuffer.append(str);
}
} catch (IOException e) {
e.printStackTrace();
}
Gson gson = new Gson();
goodBean = gson.fromJson(stringBuffer.toString(), GoodBean.class);
mAdapter = new ExpandableListAdapter(this, goodBean);
mAdapter.setChangedListener(this);
mExpandableListView.setAdapter(mAdapter);
//展开所有的分组
for (int i = 0; i < goodBean.getContent().size(); i++) {
mExpandableListView.expandGroup(i);
}
}

private void initView() {
mExpandableListView = (ExpandableListView) findViewById(R.id.expandableListView);
mCbSelectAll = (SmoothCheckBox) findViewById(R.id.cb_select_all);
mTvAllMoney = (TextView) findViewById(R.id.tv_all_money);
mBtnBuy = (Button) findViewById(R.id.btn_settlement);
//去掉ExpandableListView 默认的箭头
mExpandableListView.setGroupIndicator(null);

//用于列表滑动时,EditText清除焦点,收起软键盘
mExpandableListView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView absListView, int scrollState) {
if (SCROLL_STATE_TOUCH_SCROLL == scrollState) {
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Activity
.INPUT_METHOD_SERVICE);
View focusView = getCurrentFocus();
if (focusView != null) {
inputMethodManager.hideSoftInputFromWindow(focusView.getWindowToken(), InputMethodManager
.HIDE_NOT_ALWAYS);
focusView.clearFocus();
}
}
}

@Override
public void onScroll(AbsListView absListView, int i, int i1, int i2) {

}
});

}

@Override
public void update(boolean isAllSelected, int count, int price) {
mBtnBuy.setText("结算(" + count + ")");
mTvAllMoney.setText("¥" + price);
mCbSelectAll.setChecked(isAllSelected);
}

@Override
public void onClick(View view) {
selectAll();
}

private void selectAll() {
int allCount = goodBean.getAllCount();
int allMoney = goodBean.getAllMoney();
if (!mCbSelectAll.isChecked()) {
goodBean.setAllSelect(true);
for (int i = 0; i < goodBean.getContent().size(); i++) {
goodBean.getContent().get(i).setIsSelected(true);
for (int n = 0; n < goodBean.getContent().get(i).getGoodDetail().size(); n++) {
if (!goodBean.getContent().get(i).getGoodDetail().get(n).isSelected()) {
allCount++;
allMoney += Integer.valueOf(goodBean.getContent().get(i).getGoodDetail().get(n).getCount())
* Integer.valueOf(goodBean.getContent().get(i).getGoodDetail().get(n).getPrice());
goodBean.getContent().get(i).getGoodDetail().get(n).setIsSelected(true);
}
}
}
} else {
goodBean.setAllSelect(false);
for (int i = 0; i < goodBean.getContent().size(); i++) {
goodBean.getContent().get(i).setIsSelected(false);
for (int n = 0; n < goodBean.getContent().get(i).getGoodDetail().size(); n++) {
goodBean.getContent().get(i).getGoodDetail().get(n).setIsSelected(false);
}
allCount = 0;
allMoney = 0;
}
}
goodBean.setAllMoney(allMoney);
goodBean.setAllCount(allCount);
update(goodBean.isAllSelect(), allCount, allMoney);
mAdapter.notifyDataSetChanged();
}
}
适配器
import android.content.Context;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;

public class ExpandableListAdapter extends BaseExpandableListAdapter {

private static final String TAG = "ExpandableListAdapter";
private Context mContext;
private GoodBean goodBean;
private UpdateView updateViewListener;
protected static final int KEY_DATA = 0xFFF11133;

public ExpandableListAdapter(Context context, GoodBean goodBean) {
this.mContext = 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;
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.item_shopingcart_group, 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).getAddress());
//根据获取的状态设置是否被选中
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;
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.item_shopingcart_child, 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.imgDelete.setTag(tag);
holder.imgIcon.setTag(tag);
holder.cbItem.setOnClickListener(listener);
holder.tvReduce.setOnClickListener(listener);
//添加商品数量
holder.tvAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String tag = view.getTag().toString();
String[] split;
int groupId = 0;
int childId = 0;
int allCount = goodBean.getAllCount();
int allMoney;
if (tag.contains(",")) {
split = tag.split(",");
groupId = Integer.parseInt(split[0]);
childId = Integer.parseInt(split[1]);
}
String goodCount = goodBean.getContent().get(groupId).getGoodDetail().get(childId).getCount();
goodBean.getContent().get(groupId).getGoodDetail().get(childId).setCount(addCount(goodCount));
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.imgDelete.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());
holder.tvGoodName.setText(goodBean.getContent().get(groupPosition).getGoodDetail().get(childPosition).getName());
//对商品数量的监听
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();//被选中的item数量
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_group_item:
checkBox = (SmoothCheckBox) v;
//根据父checkbox的选中状态设置存储数据里面商品是否被选中
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());
}
}
//父item选中的数量
int fCount = 0;
//判断是否所有的父item都被选中,决定全选按钮状态
for (int i = 0; i < goodBean.getContent().size(); i++) {
if (goodBean.getContent().get(i).isSelected()) {
fCount++;
}
}
if (fCount == 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 cCount = 0;//子item被选中的数量
int fcCount = 0;//父item被选中的数量
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()) {
cCount++;
}
}
//判断是否所有的子item都被选中,决定父item状态
if (cCount == 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()) {
fcCount++;
}
}
if (fcCount == 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 goodCount = goodBean.getContent().get(groupId).getGoodDetail().get(childId).getCount();
if (Integer.valueOf(goodCount) > 1) {
goodBean.getContent().get(groupId).getGoodDetail().get(childId).setCount(reduceCount(goodCount));
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.img_delete:
goodBean.getContent().get(groupId).getGoodDetail().remove(childId);
if (goodBean.getContent().get(groupId).getGoodDetail().size() == 0) {
goodBean.getContent().remove(groupId);
}
notifyDataSetChanged();
break;
}
}
};

public void setChangedListener(UpdateView listener) {
if (updateViewListener == null) {
this.updateViewListener = listener;
}
}

private String addCount(String var) {
Integer integer = Integer.valueOf(var);
integer++;
return integer + "";
}

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_group_item);
tvPosition = (TextView) view.findViewById(R.id.tv_position);
}
}

static class ChildViewHolder {
SmoothCheckBox cbItem;
TextView tvPrice,tvGoodName;
EditText etCount;
TextView tvReduce;
TextView tvAdd;
ImageView imgDelete;
ImageView imgIcon;

ChildViewHolder(View view) {
cbItem = (SmoothCheckBox) view.findViewById(R.id.cb_item);
tvPrice = (TextView) view.findViewById(R.id.tv_price);
tvGoodName = (TextView) view.findViewById(R.id.tv_good_name);
etCount = (EditText) view.findViewById(R.id.et_count);
tvReduce = (TextView) view.findViewById(R.id.tv_reduce);
tvAdd = (TextView) view.findViewById(R.id.tv_add);
imgDelete = (ImageView) view.findViewById(R.id.img_delete);
imgIcon = (ImageView) view.findViewById(R.id.img_icon);
}
}
}
自定义view
import android.animation.ValueAnimator;
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.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.Checkable;

/**
* 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);
}

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);
}
}
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);
}
}
/**
* 更新数据的回调接口
*/
public interface UpdateView {
void update(boolean isAllSelected, int count, int price);
}














猜你喜欢

转载自www.cnblogs.com/Nigeria/p/8970400.html