安卓自定义view(全面)
Posted 春招进大厂的梦想家
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了安卓自定义view(全面)相关的知识,希望对你有一定的参考价值。
安卓自定义view
一、view的测量
1.测量的模式:
- EXACTLY :精确值模式,当把空间的layout_width属性或者layout_height的属性设置为具体的数值时,或者指定为match_parent时候,系统就是使用的EXACTLY 模式;
- AT_MOST: 最大值模式,当空间的layout_width属性或者layout_height属性指定为wrap_content时候,控件大小跟着控件的内容变化而变化,此时控件的尺寸只要不超过父控件允许的最大尺寸即可。
- UNSPECIFIED: 这个属性比较奇怪,不指定其测量大小模式,view想多大就多大,通常情况下只有在绘制自定义view的时候才会使用
2.简单演示如何进行view的测量
1.自定义一个类继承自View
public class one extends View {
public one(Context context) {
super(context);
}
public one(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public one(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
//重写onMeasure方法来进行测量
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureWidth(widthMeasureSpec),
measureHeight(heightMeasureSpec));
}
//测量高度
private int measureHeight(int heightMeasureSpec) {
//第一步,从MeasureSpec对象中提取出具体的测量模式和大小
int specMode = MeasureSpec.getMode(heightMeasureSpec);
int specSize = MeasureSpec.getSize(heightMeasureSpec);
int result = 0;
//检测是否是精确值模式
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
}else{
//如果不是就自己设定
result = 200;
if (specMode== MeasureSpec.AT_MOST) {
result = Math.min(result,specSize);
}
}
return result;
}
private int measureWidth(int widthMeasureSpec) {
int specMode = MeasureSpec.getMode(widthMeasureSpec);
int specSize = MeasureSpec.getSize(widthMeasureSpec);
int result = 0;
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
}else{
result = 200;
if (specMode== MeasureSpec.AT_MOST) {
result = Math.min(result,specSize);
}
}
return result;
}
}
2.新建一个xml文件来作为自定义view的载体
<?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">
<View
android:layout_width="400px"
android:layout_height="400px"
android:background="#00ff0f"/>
</LinearLayout>
3.在main活动的xml文件下添加自定义的控件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
tools:context=".MainActivity"
android:orientation="vertical">
<com.example.customize_learning.learning.one
android:layout_width="400px"
android:layout_height="400px"/>
</LinearLayout>
主要是进行测量,测量的主要步骤就是重写onMeasure方法,在代码中有很详细的注释
二、view的绘制
简单来说就是继承view之后再重写onDraw方法,并在Canvas对象上来绘制需要的图形
以绘制一个闪光的文字作为例子
1.新建一个类及其xml文件
public class MyTextView extends TextView {
private int mViewWidth;
private Paint mPaint;
private LinearGradient mLinearGradient;
private Matrix mGradientMatrix;
private int mTranslate;
public MyTextView(Context context) {
super(context);
}
public MyTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mPaint = new Paint();
if (mViewWidth == 0){
mViewWidth = getMeasuredWidth();
if (mViewWidth>0) {
mPaint = getPaint();
/**
* LinearGradient构造方法中的参数int[] color:
* 第一个元素:发光字体闪过后所显示的字体颜色,这里给定与第三个元素一样
* 第二个元素:字体发光的颜色
* 第三个元素:原字体显示的颜色
*
* mViewWidth:设置发光的宽度
* */
mLinearGradient = new LinearGradient(0,
0,
mViewWidth,
0,
new int[]{0x22ffffff, 0xffffffff, 0x22ffffff},
null,
Shader.TileMode.CLAMP);
mPaint.setShader(mLinearGradient);
//创建矩形
mGradientMatrix = new Matrix();
}
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mGradientMatrix != null) {
mTranslate += mViewWidth / 5;
if (mTranslate > mViewWidth * 2) {
mTranslate = -mViewWidth;
}
mGradientMatrix.setTranslate(mTranslate, 0);
mLinearGradient.setLocalMatrix(mGradientMatrix);
//控制闪过的时间
postInvalidateDelayed(80);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我是一个会闪烁的TextView"/>
</FrameLayout>
2.将自定义控件添加到主活动的xml文件下面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
tools:context=".MainActivity"
android:orientation="vertical">
<com.example.customize_learning.learning.MyTextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginTop="30dp"/>
</LinearLayout>
三、组合自定义控件
1.先建一个类,因为是组合控件,使其继承自RelativeLayout
2建一个xml文件
<?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">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginLeft="35dp">
<Button
android:id="@+id/plus_btn"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:textSize="18sp"
android:background="@drawable/selector_left"
android:text="+">
</Button>
<EditText
android:id="@+id/values_edt"
android:gravity="center"
android:layout_gravity="center"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="0"/>
<Button
android:id="@+id/minus_btn"
android:background="@drawable/selector_right"
android:layout_width="100dp"
android:text="-"
android:textSize="18sp"
android:layout_height="wrap_content">
</Button>
</LinearLayout>
</LinearLayout>
3.设置按钮按下和松开时候不同的效果
(1)设置左右两边按钮的自定义背景(按下时)
左边
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!--纯色填充-->
<solid android:color="#DFE8DF"/>
<!--设置圆角-->
<corners android:bottomLeftRadius="10dp"
android:topLeftRadius="10dp"/>
<!--渐变色-->
<gradient android:startColor="#EC1426"
android:angle="270"
android:centerColor="#C64B7C"
android:endColor="#71363D"
android:type="linear"/>
</shape>
右边
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#DFE8DF"/>
<corners android:bottomRightRadius="10dp"
android:topRightRadius="10dp"/>
<!--渐变色-->
<gradient android:startColor="#EC1426"
android:angle="270"
android:centerColor="#C64B7C"
android:endColor="#71363D"
android:type="linear"/>
</shape>
(2)设置不触碰时左右两边按钮的自定义背景
左边
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!--纯色填充-->
<solid android:color="#DFE8DF"/>
<!--设置圆角-->
<corners android:bottomLeftRadius="10dp"
android:topLeftRadius="10dp"/>
<!--渐变色-->
<gradient android:startColor="#14EC14"
android:angle="270"
android:centerColor="#4BC64B"
android:endColor="#367143"
android:type="linear"/>
</shape>>
右边
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#DFE8DF"/>
<corners android:bottomRightRadius="10dp"
android:topRightRadius="10dp"/>
<!--渐变色-->
<gradient android:startColor="#14EC14"
android:angle="270"
android:centerColor="#4BC64B"
android:endColor="#367143"
android:type="linear"/>
</shape>
(3)设置一个选择器,实现按下和松开展示不同的背景
左边
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/shape_number_btn_bg_left_presses"/>
<item android:drawable="@drawable/shape_number_btn_bg_left"/>
</selector>
右边
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/shape_number_btn_bg_right_pressed"/>
<item android:drawable="@drawable/shape_number_btn_bg_right"/>
</selector>
4.把自定义控件添加到主活动里边去
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
tools:context=".MainActivity"
android:orientation="vertical"安卓自定义view仿小米商城购物车动画
Android自定义View实战教程5??---Canvas详解及代码绘制安卓机器人