购物车商品数量的增加与减少与可以设置消息条数的TextView
用于简单的购物车商品数量的增加与减少
布局如下:
<?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:gravity="center"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/bg_button_number" android:orientation="horizontal" android:weightSum="4"> <TextView android:id="@+id/button_sub" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@drawable/bg_button_left" android:gravity="center" android:text="—" android:textColor="#000" android:minWidth="30dp" android:textSize="18sp"/> <EditText android:id="@+id/text_count" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="2" android:background="@null" android:cursorVisible="true" android:digits="0123456789" android:gravity="center" android:singleLine="true" android:inputType="number" android:minWidth="60dp" android:paddingBottom="3dp" android:paddingLeft="5dp" android:paddingRight="5dp" android:paddingTop="3dp" android:text="555" android:textColor="#000" android:textCursorDrawable="@null" android:focusable="false"/> <TextView android:id="@+id/button_add" android:layout_width="0dp" android:minWidth="30dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@drawable/bg_button_right" android:gravity="center" android:text="+" android:textColor="#000" android:textSize="18sp"/> </LinearLayout> </LinearLayout>
整个布局背景: bg_button_number.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <stroke android:width="1dp" android:color="#999"/> <solid android:color="#ffffff"/> <corners android:radius="3dp"/> </shape>
左边"—"的背景
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <solid android:color="#ffffff"/> <stroke android:width="1dp" android:color="#999"/> <corners android:topLeftRadius="3dp" android:bottomLeftRadius="3dp"/> </shape>
右边"+"的背景
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <solid android:color="#ffffff"/> <stroke android:width="1dp" android:color="#999"/> <corners android:topRightRadius="3dp" android:bottomRightRadius="3dp"/> </shape>
效果图:
可以设置消息条数的TextView并且可以用于需要圆角矩形框背景的TextView的情况,减少直接使用TextView时引入的shape资源文件
1.可设置背景为弧形矩形、圆形、可设置消息条数与显示消息红点的TextView

import android.content.Context; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.StateListDrawable; import android.os.Build; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; /** 用于需要圆角矩形框背景的TextView的情况,减少直接使用TextView时引入的shape资源文件 */ public class MsgView extends TextView { private Context context; private GradientDrawable gd_background = new GradientDrawable(); private int backgroundColor; private int cornerRadius; private int strokeWidth; private int strokeColor; private boolean isRadiusHalfHeight; private boolean isWidthHeightEqual; public MsgView(Context context) { this(context, null); } public MsgView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MsgView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.context = context; obtainAttributes(context, attrs); } private void obtainAttributes(Context context, AttributeSet attrs) { TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MsgView); backgroundColor = ta.getColor(R.styleable.MsgView_mv_backgroundColor, Color.TRANSPARENT); cornerRadius = ta.getDimensionPixelSize(R.styleable.MsgView_mv_cornerRadius, 0); strokeWidth = ta.getDimensionPixelSize(R.styleable.MsgView_mv_strokeWidth, 0); strokeColor = ta.getColor(R.styleable.MsgView_mv_strokeColor, Color.TRANSPARENT); isRadiusHalfHeight = ta.getBoolean(R.styleable.MsgView_mv_isRadiusHalfHeight, false); isWidthHeightEqual = ta.getBoolean(R.styleable.MsgView_mv_isWidthHeightEqual, false); ta.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (isWidthHeightEqual() && getWidth() > 0 && getHeight() > 0) { int max = Math.max(getWidth(), getHeight()); int measureSpec = MeasureSpec.makeMeasureSpec(max, MeasureSpec.EXACTLY); super.onMeasure(measureSpec, measureSpec); return; } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (isRadiusHalfHeight()) { setCornerRadius(getHeight() / 2); } else { setBgSelector(); } } public void setBackgroundColor(int backgroundColor) { this.backgroundColor = backgroundColor; setBgSelector(); } public void setCornerRadius(int cornerRadius) { this.cornerRadius = dp2px(cornerRadius); setBgSelector(); } public void setStrokeWidth(int strokeWidth) { this.strokeWidth = dp2px(strokeWidth); setBgSelector(); } public void setStrokeColor(int strokeColor) { this.strokeColor = strokeColor; setBgSelector(); } public void setIsRadiusHalfHeight(boolean isRadiusHalfHeight) { this.isRadiusHalfHeight = isRadiusHalfHeight; setBgSelector(); } public void setIsWidthHeightEqual(boolean isWidthHeightEqual) { this.isWidthHeightEqual = isWidthHeightEqual; setBgSelector(); } public int getBackgroundColor() { return backgroundColor; } public int getCornerRadius() { return cornerRadius; } public int getStrokeWidth() { return strokeWidth; } public int getStrokeColor() { return strokeColor; } public boolean isRadiusHalfHeight() { return isRadiusHalfHeight; } public boolean isWidthHeightEqual() { return isWidthHeightEqual; } protected int dp2px(float dp) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dp * scale + 0.5f); } protected int sp2px(float sp) { final float scale = this.context.getResources().getDisplayMetrics().scaledDensity; return (int) (sp * scale + 0.5f); } private void setDrawable(GradientDrawable gd, int color, int strokeColor) { gd.setColor(color); gd.setCornerRadius(cornerRadius); gd.setStroke(strokeWidth, strokeColor); } public void setBgSelector() { StateListDrawable bg = new StateListDrawable(); setDrawable(gd_background, backgroundColor, strokeColor); bg.addState(new int[]{-android.R.attr.state_pressed}, gd_background); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {//16 setBackground(bg); } else { //noinspection deprecation setBackgroundDrawable(bg); } } /** * 设置消息条数 * @param num */ public void show(int num) { ViewGroup.LayoutParams lp = this.getLayoutParams(); DisplayMetrics dm = this.getResources().getDisplayMetrics(); this.setVisibility(View.VISIBLE); if (num <= 0) {// 圆点,设置默认宽高 this.setStrokeWidth(0); this.setText(""); lp.width = (int) (5 * dm.density); lp.height = (int) (5 * dm.density); this.setLayoutParams(lp); } else { lp.height = (int) (18 * dm.density); if (num > 0 && num < 10) {// 圆 lp.width = (int) (18 * dm.density); //this.setPadding((int) (5 * dm.density), 0, (int) (5 * dm.density), 0); this.setPadding(0, 0, 0, 0); this.setText(num + ""); } else if (num > 9 && num < 100) {// 圆角矩形,圆角是高度的一半,设置默认padding lp.width = ViewGroup.LayoutParams.WRAP_CONTENT; this.setPadding((int) (6 * dm.density), 0, (int) (6 * dm.density), 0); this.setText(num + ""); } else {// 数字超过两位,显示99+ lp.width = ViewGroup.LayoutParams.WRAP_CONTENT; this.setPadding((int) (6 * dm.density), 0, (int) (6 * dm.density), 0); this.setText("99+"); } this.setLayoutParams(lp); } } }
2.自定义属性值
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- 用于需要圆角矩形框背景的TextView的情况,减少直接使用TextView时引入的shape资源文件 --> <declare-styleable name="MsgView"> <!-- 圆角背景色 --> <attr name="mv_backgroundColor" format="color" /> <!-- 圆角弧度,单位dp --> <attr name="mv_cornerRadius" format="dimension" /> <!-- 圆角边框弧度,单位dp --> <attr name="mv_strokeWidth" format="dimension" /> <!-- 圆角边框颜色 --> <attr name="mv_strokeColor" format="color" /> <!-- 圆角弧度是高度的一半 --> <attr name="mv_isRadiusHalfHeight" format="boolean" /> <!-- 圆角矩形宽高相等,取较宽高中大值--> <attr name="mv_isWidthHeightEqual" format="boolean" /> </declare-styleable> </resources>
使用-布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ffcccc" android:orientation="vertical" android:gravity="center" tools:context="com.robusttest.MainActivity"> <com.robusttest.MsgView xmlns:mv="http://schemas.android.com/apk/res-auto" android:id="@+id/msg1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:textColor="#ffffff" android:textSize="13sp" android:padding="8dp" android:text="我是可以设置消息条数的TextView" mv:mv_backgroundColor="#FD481F" mv:mv_isRadiusHalfHeight="false" mv:mv_isWidthHeightEqual="true" mv:mv_cornerRadius="20dp" mv:mv_strokeColor="#ffffff" mv:mv_strokeWidth="1dp" /> <com.robusttest.MsgView xmlns:mv="http://schemas.android.com/apk/res-auto" android:id="@+id/msg2" android:layout_marginTop="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:textColor="#ffffff" android:textSize="13sp" android:padding="8dp" android:text="我是可以设置消息条数的TextView" mv:mv_backgroundColor="#FD481F" mv:mv_isRadiusHalfHeight="true" mv:mv_isWidthHeightEqual="true" mv:mv_cornerRadius="20dp" mv:mv_strokeColor="#ffffff" mv:mv_strokeWidth="1dp" /> <com.robusttest.MsgView xmlns:mv="http://schemas.android.com/apk/res-auto" android:id="@+id/msg3" android:layout_marginTop="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:textColor="#ffffff" android:textSize="13sp" android:padding="8dp" android:text="我是可以设置消息条数的TextView" mv:mv_backgroundColor="#FD481F" mv:mv_isRadiusHalfHeight="false" mv:mv_isWidthHeightEqual="false" mv:mv_cornerRadius="20dp" mv:mv_strokeColor="#ffffff" mv:mv_strokeWidth="1dp" /> </LinearLayout>
效果图:
设置消息条数:
msgView1 = (MsgView) findViewById(R.id.msg1); msgView2 = (MsgView) findViewById(R.id.msg2); msgView3 = (MsgView) findViewById(R.id.msg3); //设置消息条数 msgView1.show(0); msgView2.show(5); msgView3.show(55);
效果图:分别对应着消息条数为0(未读消息),一位,两位数,三位数时的效果