开发中常常遇到下图需求,购物经常用到数量加减,这里封装的一个自定义控件实现该功能,以前我使用每个控件都在xml里面布局,activity或者adapter里面调用,回调实现,感觉代码有点冗杂,今日又遇到此需求,所以逗比的DishesView就此诞生了。
DishesView代码相对简单,通过自定义属性获取背景,动态的给LinearLayout添加自布局,绑定view的监听,动态更新EditText的值,同时回调给Activity.先来看看实体类:
public class Dishes {
private int id;
private float price;
private int count;
@SuppressWarnings("unused")
private float totalPrice;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public int getCount() {
return count <= 0 ? 0 : count;
}
public void setCount(int count) {
this.count = count <= 0 ? 0 : count;
}
public float getTotalPrice() {
return price * count;
}
public void setTotalPrice(float totalPrice) {
this.totalPrice = totalPrice <= 0 ? 0 : totalPrice;
}
public Dishes(int id, float price, int count, float totalPrice) {
super();
this.id = id;
this.price = price;
this.count = count;
this.totalPrice = totalPrice;
}
public Dishes(float price, int count, float totalPrice) {
super();
this.price = price;
this.count = count;
this.totalPrice = totalPrice;
}
public Dishes(float price, int count) {
super();
this.price = price;
this.count = count;
}
}
这里主要是对count值进行检测,总价格动态获取。DishesView的构造函数如下:
public DishesView(Context context) {
this(context,null);
}
public DishesView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
private DishesView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
final TypedArray a= context.obtainStyledAttributes(attrs,R.styleable.dishesStyleable);
updateBackgroundFromTypedArray(a);
a.recycle();
}
调用私有构造方法后获取自定义属性值Drawable:
private void updateBackgroundFromTypedArray(TypedArray a) {
addDrawable=a.getDrawable(R.styleable.dishesStyleable_AddBackground);
deleteDrawable=a.getDrawable(R.styleable.dishesStyleable_DeleteBackground);
editTextDrawable=a.getDrawable(R.styleable.dishesStyleable_EditTextBackground);
}
下面是onMeasure测量和SizeChange监听,同时绑定控件监听
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
Resources r = Resources.getSystem();
if(widthMode == MeasureSpec.UNSPECIFIED || widthMode == MeasureSpec.AT_MOST){
widthSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, r.getDisplayMetrics());
widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
}
if(heightMode == MeasureSpec.UNSPECIFIED || heightSize == MeasureSpec.AT_MOST){
heightSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30, r.getDisplayMetrics());
heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
super.onSizeChanged(w, h, oldw, oldh);
if(getChildCount()>0){
removeAllViews();
}
initialization();
mAddImageView.setOnClickListener(this);
mDeleteImageView.setOnClickListener(this);
mCountEditText.addTextChangedListener(this);
mCountEditText.setOnTouchListener(this);
mCountEditText.clearFocus();
mCountEditText.setCursorVisible(false);
}
private void initialization() {
// TODO Auto-generated method stub
setFocusable(false);
setFocusableInTouchMode(true);
setOrientation(LinearLayout.HORIZONTAL);
addView(getAddView());
addView(getEditTextView());
addView(getDeleteView());
}
通过setCursorVisible控制光标的显示,afterTextChanged该方法回调里面调用onCheck方法检测输入值的合法性和绑定Dishes的count,并执行onDishesListener回调,对外公开方法setAdapter如下:
public void setAdapter(Dishes mDishes,OnDishesListener onDishListener){
this.mDishes=mDishes;
this.onDishesListener=onDishListener;
if(onDishListener!=null){
onDishListener.onTextChanged(mDishes);
}
}
自定义属性:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- These are the standard attributes that make up a complete theme. -->
<declare-styleable name="dishStyleable">
<!-- ============= -->
<!-- DishView styles -->
<!-- ============= -->
<eat-comment />
<!-- Delete ImageView's background. -->
<attr name="DeleteBackground" format="reference" />
<!-- Add ImageView's background. -->
<attr name="AddBackground" format="reference" />
<!-- Editext's background. -->
<attr name="EditTextBackground" format="reference" />
</declare-styleable>
</resources>
测试xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
tools:context="com.lanyan.dish.MainActivity" >
<TextView
android:id="@+id/totalPrice"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentTop="true"
android:gravity="center"
android:padding="10dp"
android:text="" />
<com.lanyan.widget.DishesView
android:id="@+id/dishView1"
android:layout_width="180dp"
android:layout_height="40dp"
android:layout_below="@+id/totalPrice"
android:layout_centerHorizontal="true"
android:layout_margin="10dp"
app:AddBackground="@drawable/add"
app:DeleteBackground="@drawable/delete"
app:EditTextBackground="@drawable/edittext" />
<Button
android:id="@+id/sure"
android:layout_width="match_parent"
android:layout_height="45dp"
android:layout_centerHorizontal="true"
android:layout_centerInParent="true"
android:layout_margin="20dp"
android:background="@drawable/edittext"
android:text="确定" />
</RelativeLayout>
测试代码:
public class MainActivity extends Activity {
private TextView tv;
private DishesView dishesView;
private Button sure;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv=(TextView)findViewById(R.id.totalPrice);
dishesView=(DishesView)findViewById(R.id.dishView1);
sure=(Button)findViewById(R.id.sure);
sure.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
dishView.setCursorVisible(false);
}
});
dishesView.setAdapter(new Dishes(20, 1),new OnDishesListener() {
@Override
public void onTextChanged(Dishes bean) {
// TODO Auto-generated method stub
tv.setText("当前总价格为:"+bean.getTotalPrice()+" 元 ");
}
});
}
}
demo下载:http://download.youkuaiyun.com/detail/analyzesystem/8991845