Android ShapeButton
来源:互联网 发布:通达信软件怎么用 编辑:程序博客网 时间:2024/06/08 02:40
写控件的初衷:
在日常的项目中,我们常常会用到一个按钮拥有两种点击状态,一种是pressed state,另外一种是unpressed state,通常我们会使用xml先写两个drawable xml文件:
(1)pressed state xml文件[android_shape_round_error_button_pressed.xml]:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="5dp"></corners>
<solid android:color="@color/error_button_pressed_color"></solid>
</shape>
(2)unpressed state xml文件[android_shape_round_error_button_unpressed.xml]:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="5dp"></corners>
<solid android:color="@color/error_button_unpressed_color"></solid>
</shape>
(3)利用上面两个xml最后写一个selctor xml 文件[android_error_button.xml]:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/android_shape_round_error_button_pressed" android:state_pressed="true"></item>
<item android:drawable="@drawable/android_shape_round_error_button_unpressed" android:state_pressed="false"></item>
</selector>
(4)在自己页面xml控件属性中应用此selector背景:
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/android_error_button"/>
在以上的两个xml文件中,我们看似是很简单的操作,一旦项目中冗杂的代码按钮,你会每个都要写这样的代码,如果你只是追求吧项目完工之类的,于是就直接用个普通背景
代替了,这样你也就没必要来写自定义View了吧,Coder是一个动脑的行业,因此我们选择这一行业,就应该在项目中吸取应有的教训,怎么把下一次的项目更好、更快地去完成,
这样的代码自己写着舒服,别人接管的人看着也舒服,后期维护一方便。
控件思路:
此类控件无非就是先加载的时候默认有一个颜色,在点击事件或者触摸事件的时候就换了一种加深的颜色,我们不可能只想到我们做到
能换颜色就行了,因为即使你把两种颜色传递给你控件,那么你还要想这个颜色对应加深的颜色是什么颜色,没有必要,既然我们要
自定义控件,那么就一次性搞定控件,总之一句话,那就是我们怎么方便使用、怎么简单就怎么设计View。那么看似简单的控件有这么
几个问题:
(1)动态设置2种背景颜色
(2)默认颜色和点击颜色相似但是点击颜色要身些。
第一个问题其实不算什么问题,我们只要是控件都可以设置颜色,只是有一个问题的是,颜色处置问题。目前颜色拥有色调、饱和度
、色值。这种颜色变暗就只能在饱和度上面下功夫。饱和度在android有没有方法呢,我们开始只能猜测。于是我们可以在Android中寻找对应的类和方法,当然第一次想到的是Color
类,你可以先看饱和度对应的English:saturation,这时候你可以在Color类中find this word.你将会看着下面这几个类:
/**
* Convert the argb color to its HSV components.
* hsv[0] is Hue [0 .. 360)
* hsv[1] is Saturation [0...1]
* hsv[2] is Value [0...1]
* @param color the argb color to convert. The alpha component is ignored.
* @param hsv 3 element array which holds the resulting HSV components.
*/
public static void colorToHSV(@ColorInt int color, @Size(3) float hsv[]) {
RGBToHSV((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF, hsv);
}
此方法是将ARGB颜色转成HSV组件,在HSV组件中可以设置hsv[1]的饱和度,当然看到这,我们的目的还是没达到的,我们的
目的是调颜色的饱和度,那么饱和度已经调整了,那么肯定需要HSV组件转换成颜色。我们先猜测是HSVto...类似的方法搜索,
结果是就是这个方法下面,所有有时候别先急着搜,先看看需要的方法的附近代码。下面就是HSV组件转换成颜色方法:
/**
* Convert HSV components to an ARGB color. Alpha set to 0xFF.
* hsv[0] is Hue [0 .. 360)
* hsv[1] is Saturation [0...1]
* hsv[2] is Value [0...1]
* If hsv values are out of range, they are pinned.
* @param hsv 3 element array which holds the input HSV components.
* @return the resulting argb color
*/
public static int HSVToColor(@Size(3) float hsv[]) {
return HSVToColor(0xFF, hsv);
}
好了以上问题现在都不是问题了,现在是可以着手写自己的自定义View,此处的思路只是一种,我只是利用原有的控件的
属性加上原有的方法构造新控件,不想再draw,个人认为再次渲染没有原控件来的性能优越。
控件代码[ShapeButton]:
(1)attr.xml:
<!--ShapeButton-->
<attr name="shape" format="enum">
<enum name="rectangle" value="0"></enum>
<enum name="oval" value="1"></enum>
</attr>
<declare-styleable name="ShapeButton">
<attr name="solid_color" format="color" />
<attr name="stroke_color" format="color"/>
<attr name="stroke_width" format="dimension"/>
<attr name="corner_radius" format="dimension"/>
<attr name="top_left_corner_radius" format="dimension"/>
<attr name="top_right_corner_radius" format="dimension"/>
<attr name="bottom_left_corner_radius" format="dimension"/>
<attr name="bottom_right_corner_radius" format="dimension"/>
<attr name="shape"/>
<attr name="saturation" format="float"/>
</declare-styleable>
(2)ShapeButton源码:
import android.content.Context;import android.content.res.TypedArray;import android.graphics.Color;import android.graphics.PorterDuff;import android.graphics.Rect;import android.graphics.drawable.Drawable;import android.graphics.drawable.GradientDrawable;import android.os.Build;import android.util.AttributeSet;import android.util.TypedValue;import android.view.KeyEvent;import android.view.MotionEvent;import android.view.View;import android.widget.Button;import android.widget.TextView;import com.android.R;/** * Created by Relin on 2017/11/22. * This class is ButtonView you can setting background,stroke color * stroke width ,stroke width,the kinds of corner in sample way. * button color is change auto when click it and the color is old * color's saturation 92% ,if you think isn't suit to you application * you can change it,saturation is bright deep. */public class ShapeButton extends TextView implements View.OnTouchListener{ private int solidColor = Color.parseColor("#B4B4B4"); private int strokeWidth = 0; private int strokeColor = Color.parseColor("#B4B4B4"); private int shape = 0; private float cornerRadius = 0; private float topLeftCornerRadius = 0; private float topRightCornerRadius = 0; private float bottomLeftCornerRadius = 0; private float bottomRightCornerRadius = 0; private float saturation = 0.90f; private Drawable normalDrawable; private Drawable pressedDrawable; public ShapeButton(Context context) { super(context); initAttrs(context,null); } public ShapeButton(Context context, AttributeSet attrs) { super(context, attrs); initAttrs(context,attrs); } @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: setDrawable(pressedDrawable); break; case MotionEvent.ACTION_UP: setDrawable(normalDrawable); break; } return false; } private void initAttrs(Context context, AttributeSet attrs) { setOnTouchListener(this); if (attrs!=null){ TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ShapeButton); solidColor = typedArray.getColor(R.styleable.ShapeButton_solid_color, Color.parseColor("#B4B4B4")); strokeWidth = (int) typedArray.getDimension(R.styleable.ShapeButton_stroke_width, 0); strokeColor = typedArray.getColor(R.styleable.ShapeButton_stroke_color, Color.parseColor("#B4B4B4")); if (typedArray.getString(R.styleable.ShapeButton_shape)!=null){ shape = Integer.parseInt(typedArray.getString(R.styleable.ShapeButton_shape)); } cornerRadius = typedArray.getDimension(R.styleable.ShapeButton_corner_radius, 0); topLeftCornerRadius = typedArray.getDimension(R.styleable.ShapeButton_top_left_corner_radius, 0); topRightCornerRadius = typedArray.getDimension(R.styleable.ShapeButton_top_right_corner_radius, 0); bottomLeftCornerRadius = typedArray.getDimension(R.styleable.ShapeButton_bottom_left_corner_radius, 0); bottomRightCornerRadius = typedArray.getDimension(R.styleable.ShapeButton_bottom_right_corner_radius, 0); saturation = typedArray.getFloat(R.styleable.ShapeButton_saturation,0.90f); typedArray.recycle(); } normalDrawable = createShape(shape,strokeWidth, strokeColor, solidColor, cornerRadius, topLeftCornerRadius, topRightCornerRadius, bottomLeftCornerRadius, bottomRightCornerRadius); pressedDrawable = createShape(shape, strokeWidth, createPressedColor(strokeColor), createPressedColor(solidColor), cornerRadius, topLeftCornerRadius, topRightCornerRadius, bottomLeftCornerRadius, bottomRightCornerRadius); setDrawable(normalDrawable); } /** * create pressed state color by HSV * hsv[2] :values is big - is deep or bright * @param color * @return */ private int createPressedColor(int color) { int alpha = Color.alpha(color); float[] hsv = new float[3]; Color.colorToHSV(color, hsv); hsv[2] *= saturation; return Color.HSVToColor(alpha, hsv); } /** * for all android api * set all kinds of background. * @param drawable */ private void setDrawable(Drawable drawable) { if (Build.VERSION.SDK_INT >= 16) { setBackground(drawable); } else { setBackgroundDrawable(drawable); } } /** * create shape drawable * this method create you self background drawable * by shape.the same as code in xml. * * @param shape GradientDrawable.RECTANGLE GradientDrawable.OVAL * @param strokeWidth button stroke width * @param strokeColor button stroke color * @param solidColor button background color * @param cornerRadius all corner is the same as is the radius * @param topLeftCornerRadius top left corner radius * @param topRightCornerRadius top right corner radius * @param bottomLeftCornerRadius bottom left corner radius * @param bottomRightCornerRadius bottom right corner radius * @return */ public Drawable createShape(int shape, int strokeWidth, int strokeColor, int solidColor, float cornerRadius, float topLeftCornerRadius, float topRightCornerRadius, float bottomLeftCornerRadius, float bottomRightCornerRadius) { GradientDrawable drawable = new GradientDrawable(); drawable.setShape(shape); drawable.setSize(10,10); drawable.setStroke(strokeWidth, strokeColor); drawable.setColor(solidColor); if (cornerRadius!=0){ drawable.setCornerRadius(cornerRadius); }else{ drawable.setCornerRadii(new float[]{topLeftCornerRadius, topLeftCornerRadius, topRightCornerRadius, topRightCornerRadius, bottomLeftCornerRadius, bottomLeftCornerRadius, bottomRightCornerRadius, bottomRightCornerRadius}); } return drawable; }}
(3)使用:
按钮类型可以是圆形、正方形、椭圆形,shape的选择+View自身的宽高设置就可以了。其中saturation设置点击后的饱和度的。
<com.android.widget.ShapeButton
android:id="@+id/elven_fbtn_reloading"
android:layout_width="160dp"
android:layout_height="35dp"
android:layout_marginTop="15dp"
android:text="重新加载"
app:corner_radius="8dp"
android:textColor="@android:color/white"
android:textSize="14sp"
app:shape="rectangle"
android:gravity="center" />
- Android ShapeButton
- Android
- android
- Android
- android
- android
- Android
- Android
- android
- android
- android
- Android
- Android
- android!!!
- android
- android
- android
- android
- javax.persistence.entitynotfoundexception怎么解决
- CIFAR-10和CIFAR-100数据集读取显示
- 内核中的kmalloc函数详解
- JSP内置对象request、response(四)
- 【java基础:net】基于TCP的客户端与服务端进行字母大小写转换的Demonstration
- Android ShapeButton
- 【MyBatis】mybatis快速入门(二)
- Sklearn-RandomForest随机森林参数及实例
- EAST: An Efficient and Accurate Scene Text Detector安装
- C++基类指针与派生成员
- Nexpose部署教程
- MiniUI的多表整合crud
- [bzoj1005]:[HNOI2008]明明的烦恼(prufer序列+质因数分解+高精乘)
- Solr:schema版本号区别(引发IK分词错误)