屏幕适配
几个基本概念
屏幕尺寸:手机对角线的物理尺寸,1英寸=2.54cm,Android手机常见的尺寸有5寸、5.5寸、6寸等等
屏幕分辨率:手机在横向、纵向上的像素点数总和,eg:1080px X 1920px
屏幕像素密度DPI:每英寸的像素点数
dp:密度无关像素。dp最终也是转化为px,根据密度DPI来决定比例
sp:独立比例像素。sp最终也是转化为px,根据系统设置里大中小号字体来决定比例
布局匹配
- 禁用绝对布局(AbsoluteLayout)
- 布局文件夹
- res/layout/main.xml 正常单面屏布局
- res/layout-large/main.xml 大于7寸屏幕的双面屏布局,一般平板
- res/layout-sw600dp/main.xml 大于600dp屏幕的布局
- res/values-sw600dp-land/layouts.xml 横屏且大于600dp屏幕的布局
- res/values-large-land/layouts.xml 横屏且大于7寸屏幕的布局
图片资源适配
- 9png
- 一般做一套720x1280的图片放xhdpi 或 做一套1080x1920的图片放xxhdpi
- mipmap相对drawable加载性能会更好些
控件适配:别把控件宽高设死
- 使用”wrap_content”、”match_parent”和”weight“来控制视图组件的宽度和高度
- 使用padding、margin来控制控件
drawable
- BitmapDrawable
<bitmap>
android:antialias=["true" | "false"]//抗锯齿效果
android:dither=["true" | "false"]//抖动效果
android:filter=["true" | "false"]//是否允许对位图进行滤波。当图片被压缩或者拉伸时,使用滤波可以获得平滑的外观效果
android:gravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
"fill_vertical" | "center_horizontal" | "fill_horizontal" |
"center" | "fill" | "clip_vertical" | "clip_horizontal"]
android:tileMode=["disabled" | "clamp" | "repeat" | "mirror"]//平铺模式
- ShapeDrawable
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape=["rectangle" | "oval" | "line" | "ring"] >
<corners
android:radius="integer"
android:topLeftRadius="integer"
android:topRightRadius="integer"
android:bottomLeftRadius="integer"
android:bottomRightRadius="integer" />
<gradient
android:angle="integer"
android:centerX="integer"
android:centerY="integer"
android:centerColor="integer"
android:endColor="color"
android:gradientRadius="integer"
android:startColor="color"
android:type=["linear" | "radial" | "sweep"]
android:usesLevel=["true" | "false"] />
<padding
android:left="integer"
android:top="integer"
android:right="integer"
android:bottom="integer" />
<size
android:width="integer"
android:height="integer" />
<solid
android:color="color" />
<stroke
android:width="integer"
android:color="color"
android:dashWidth="integer"
android:dashGap="integer" />
</shape>
- android:shape=["rectangle" | "oval" | "line" | "ring"] 矩形、椭圆、横线、圆环
- ring圆环下的一些配置
- android:innerRadius 圆环半径
- android:innerRadiusRatio 内半径占整个Drawable宽度的比例
- android:thickness 圆环的厚度
- android:thicknessRatio 厚度占整个Drawable宽度比例
- android:useLevel 一般都应该使用false,否则可能无法达到预期显示效果,除非它被当做LevelListDrawable来使用
- corners 圆角
- android:radius 四个角的半径
- android:topLeftRadius 左上角的半径
- android:topRightRadius
- android:bottomLeftRadius
- android:bottomRightRadius
- gradient 渐变填充
- android:angle 渐变角度
- android:centerX android:centerY 渐变中心x、y
- android:startColor android:centerColor android:endColor 开始中间结束的颜色
- android:gradientRadius 渐变的半径,当android:type=”radial”有效
- android:useLevel 一般为false
- android:type 渐变类别,linear(线性)为默认值,radial(径内渐变),sweep(扫描渐变)
- solid 纯色填充
- android:color 填充色
- stroke 描边
- android:width 描述边框的宽度,数值越大,越边框越厚
- android:color 边框的颜色
- android:dashWidth 组成虚线的线段宽度
- android:dashGap 组成虚线的线段之间的间隔,间隔越大,虚线看起的间隙就越大
- padding 表示内容或子标签边距,4个属性top、bottom、left、right,需要注意的是这个标签的作用是为内容设置与当前应用此shape的View的边距,而不是设置当前View与父元素的边距
- size 设置背景大小,width和height俩属性。一般来说这个值不是shape的最终显示大小,因为shape作为背景时会根据View的大小而填充其背景,因此Shape的大小很多时候是View的大小决定的
- LayerDrawable多个drawable多层叠加
- < layer-list >
- < item >
- < layer-list >
- StateListDrawable状态集,定义不同状态时drawable的不同
- < selector >
- < item >
- < selector >
- LevelListDrawable与状态集类似,是一个等级集;ImageView可以通过setImageLevel来改变的等级
- < level-list >
- < item >
- < level-list >
- TransitionDrawable两个drawable之间的淡入淡出效果
- InsetDrawable内嵌其他drawable并可以撑开一定的空间
- ScaleDrawable根据等级 来缩放drawable
- ClipDrawable根据等级来裁剪drawable
eg:利用drawable来绘制圆角/圆形图片
public class RoundImageDrawable extends Drawable
{
private Paint mPaint;
private Bitmap mBitmap;
private RectF rectF;
public RoundImageDrawable(Bitmap bitmap)
{
mBitmap = bitmap;
BitmapShader bitmapShader = new BitmapShader(bitmap, TileMode.CLAMP,
TileMode.CLAMP);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setShader(bitmapShader);
}
@Override
public void setBounds(int left, int top, int right, int bottom)
{
super.setBounds(left, top, right, bottom);
rectF = new RectF(left, top, right, bottom);
}
@Override
public void draw(Canvas canvas)
{
canvas.drawRoundRect(rectF, 30, 30, mPaint); //画圆角
//也可以画圆
//canvas.drawCircle(mWidth / 2, mWidth / 2, mWidth / 2, mPaint);
}
@Override
public int getIntrinsicWidth()
{
return mBitmap.getWidth();
}
@Override
public int getIntrinsicHeight()
{
return mBitmap.getHeight();
}
@Override
public void setAlpha(int alpha)
{
mPaint.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter cf)
{
mPaint.setColorFilter(cf);
}
@Override
public int getOpacity()
{
return PixelFormat.TRANSLUCENT;
}
}
使用
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.mv);
ImageView iv = (ImageView) findViewById(R.id.id_one);
iv.setImageDrawable(new RoundImageDrawable(bitmap));
eg:自定义进度条
自定义旋转动画progress_rotate.xml,drawable可定义为任何自旋转可做进度条的视图
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/shape_drawable"
android:pivotX="50%"
android:pivotY="50%"
android:fromDegrees="0"
android:toDegrees="360"
>
</rotate>
设置style
<style name="CustomProgressStyle" >
<item name="android:indeterminateDrawable">@drawable/progress_rotate</item>
<item name="android:minWidth">72dp</item>
<item name="android:maxWidth">72dp</item>
<item name="android:minHeight">72dp</item>
<item name="android:maxHeight">72dp</item>
</style>
使用
<ProgressBar
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
style="@style/CustomProgressStyle"
android:indeterminateDuration="700"
/>
eg:圆形角标
设置shape
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval"
>
<solid android:color="#D90E0E" />
<size android:height="10dp" android:width="10dp" />
</shape>
TextView中使用
<TextView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_centerInParent="true"
android:gravity="center"
android:textColor="#fff"
android:text="99"
android:background="@drawable/shape_circle_number"
/>
eg:输入框效果
xml设置
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="@color/colorAccent" />
</shape>
</item>
<item android:bottom="6dp">
<shape android:shape="rectangle">
<solid android:color="#ffffff"/>
</shape>
</item>
<item android:bottom="2dp"
android:left="2dp"
android:right="2dp">
<shape android:shape="rectangle">
<solid android:color="#ffffff" />
</shape>
</item>
</layer-list>
使用
<EditText
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="@drawable/layer_drawable"
/>
帧动画
代码实现AnimationDrawable
xml实现
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/a_0"
android:duration="100" />
<item
android:drawable="@drawable/a_1"
android:duration="100" />
<item
android:drawable="@drawable/a_2"
android:duration="100" />
</animation-list>
补间动画
平移动画TranslateAnimation、缩放动画ScaleAnimation、旋转动画RotateAnimatioin、透明度动画AlphaAnimation
自定义动画:通过矩阵变换来实现,可用来做3D动画!继承Animation,实现initialize(初始化工作)、applyTransFormation(动画实现)即可。
常见属性
- < translate>
■ 表示x的起始值
■ 表示x的结束值
■ 表示y的起始值
■ 表示y的结束值 - < scale>
■ fromX 水平方向缩放起始值
■ toX 水平方向缩放结束值
■ fromY
■ toY
■ pivotX 缩放的轴点的x坐标
■ pivotY 缩放的轴点的y坐标
■ pivotXType x轴的所发模式,即中心点相对于哪个物体Animation.ABSOLUTE/RELATIVE_TO_SELF/RELATIVE_TO_PARENT
■ pivotYType y轴的所发模式 - < rotate>
■ fromeDegres旋转开始的角度
■ toDegrees
■ pivotX旋转的轴点的x坐标
■ pivotY - < alpha>
■ fromAlpha透明度起始值
■ toAlpha透明度结束值 - 共有属性
■duration动画持续时间
■ fillAfter动画结束后是否停留在结束位置
布局动画LayoutAnimation,为容器型控件里的子View设置动画
代码实现LayoutAnimationController
xml实现
android:delay子类动画时间间隔
android:animationOrder="random" 子类的显示方式 normal默认random随机reverse倒序
android:animation="@anim/slide_right" 表示孩子显示时的具体动画是什么
自定义补间动画
public class MyAnimation extends Animation
{
@Override
protected void applyTransformation(float interpolatedTime,Transformation transformation){
//interpolatedTime表示动画的时间进行比,transformation表示补间动画在不同时刻对View的变形程度
}
}
AnimationSet组合动画
属性动画
- ObjectAnimator
ObjectAnimator//
.ofFloat(view, "rotationX", 0.0F, 360.0F)//
.setDuration(500)//
.start();
一次性修改多个属性
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f,
0f, 1f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f,
0, 1f);
PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f,
0, 1f);
ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY,pvhZ).setDuration(1000).start();
- ValueAnimator
ValueAnimator animator = ValueAnimator.ofFloat(0, mScreenHeight
- mBlueBall.getHeight());
animator.setTarget(mBlueBall);
animator.setDuration(1000).start();
// animator.setInterpolator(value)
animator.addUpdateListener(new AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
mBlueBall.setTranslationY((Float) animation.getAnimatedValue());
}
});
常见属性
AnimatorSet 用于控制一组动画的执行:线性,一起,每个动画的先后执行等。
AnimatorInflater 用户加载属性动画的xml文件
- 过渡动画Transition
本质上过渡动画也还是属性动画,只不过做了一层封装,方便实现Activity和View的过渡效果
绘制辅助
Interpplator 插值器
- AccelerateDecelerateInterpolator:开始与结束时速度快,中间慢
- AccelerateInterpolator:开始慢然后加速
- CycleInterpolator:动画循环播放特定的次数,速率改变沿着正弦曲线
- DecelerateInterpolator:开始速度快然后减速
- LinearInterpolator:均匀的改变速度
TypeEvaluator 类型估值,主要用于设置动画操作属性的值。设置 属性值 从初始值过渡到结束值 的变化具体数值
- IntEvaluator Int类型估值器,返回int类型的属性改变
- FloatEvaluator Float类型估值器,返回Float类型属性改变
- ArgbEvaluator 颜色类型估值器
// 实现TypeEvaluator接口
public class PointEvaluator implements TypeEvaluator {
// 复写evaluate()在里面写入对象动画过渡的逻辑
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
//fraction为插值器getInterpolation()的返回值,startValue/endValue为初始值/结束值
// 将动画初始值startValue 和 动画结束值endValue 强制类型转换成Point对象
Point startPoint = (Point) startValue;
Point endPoint = (Point) endValue;
// 根据fraction来计算当前动画的x和y的值
float x = startPoint.getX() + fraction * (endPoint.getX() - startPoint.getX());
float y = startPoint.getY() + fraction * (endPoint.getY() - startPoint.getY());
// 将计算后的坐标封装到一个新的Point对象中并返回
Point point = new Point(x, y);
return point;
}
}
其他
overridePendingTransition Acitivity之间跳转动画
View位移的五种办法
- layout
- offsetTopAndBottom、offsetLeftAndRight
- scrollTo、scrollBy
- LayoutParams
- Scroller
invalidate最后也是通过调用rootView的performTraversals()来刷新视图的;而invalidate只会重新执行onDraw;requestLayout才会重新执行整个绘制过程
measure、layout、draw
自定义View的四种构造函数
// 如果View是在Java代码里面new的,则调用第一个构造函数
public CarsonView(Context context) {
super(context);
}
// 如果View是在.xml里声明的,则调用第二个构造函数
// 自定义属性是从AttributeSet参数传进来的
public CarsonView(Context context, AttributeSet attrs) {
super(context, attrs);
}
// 不会自动调用
// 一般是在第二个构造函数里主动调用
// 如View有style属性时
public CarsonView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
//API21之后才使用
// 不会自动调用
// 一般是在第二个构造函数里主动调用
// 如View有style属性时
public CarsonView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
View的一些常见函数
view.getTop() 子View左上角距父View顶部的距离
view.getBottom() 子View右下角距父View顶部的距离
view.getLeft() 子View左上角距父View左侧
view.getRight() 子View右下角距父View左侧
event.getX()/event.getY() 触摸点相对于其所在组件坐标系的坐标
event.getRawX()/event.getRawY() 触摸点相对于屏幕默认坐标系的坐标
颜色
Measure
LayoutParams(View 自身的布局参数)
MeasureSpecs 类(父视图对子视图的测量要求)
MeasureSpecs维护一个int型(32bit)数据,其中2bit表示mode,30bit表示size
size = MeasureSpec.getSize(measureSpec)
mode = MeasureSpec.getMode(measureSpec)
measureSpec = MeasureSpec.makeMeasureSpec(size, mode)
getDefaultSize(size,measureSpec)//根据View默认大小size和父类measureSpec来测量当前View的大小
mode
一个View的大小由父容器的MeasureSpecs和自身的LayoutParams来决定
setMeasureDimension()属于View类,保存最终的测试大小
View的测量过程
eg:修改ListView的onMeasure使得ListView完全展开
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//int widthMeasureSpec, int heightMeasureSpec是父容器的测量spec,现将父容器的高度测量spec修改成足够大,并且是AT_MOST模式,这样子容器即ListView认为父容器有足够大的空间就会将所有的内容完全展开了。
heightMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
layout
view的layout过程:layout(确定自身的位置)->onLayout(空实现)
ViewGroup的layout过程:layout(确定自身的位置)->onLayout(确定子控件的位置,这里实现具体布局,并且会遍历子控件的layout对子控件执行layout)
draw
注意点
- 支持padding & margin
padding需要在onDraw中获取在绘制过程中进行支持
final int paddingLeft = getPaddingLeft();
final int paddingRight = getPaddingRight();
final int paddingTop = getPaddingTop();
final int paddingBottom = getPaddingBottom();
- 支持自定义属性
在values目录下创建自定义属性的xml文件attrs_circle_view.xml
常用单位format:color boolean dimension float integer string fraction(百分比) enum(eg:orientation,单选) flag(eg:adjustResize|adjustPan,多选)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CircleView">
<attr name="circle_color" format="color"/>
</declare-styleable>
</resources>
在代码中解析获取
mColor = a.getColor(R.styleable.CircleView_circle_color,Color.RED);
在布局中使用
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<scut.carson_ho.diy_view.CircleView
app:circle_color="#FF4081"
/>
</RelativeLayout>
- 支持wrap_content
修改onMeasure
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 获取宽-测量规则的模式和大小
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
// 获取高-测量规则的模式和大小
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
// 设置wrap_content的默认宽 / 高值
// 默认宽/高的设定并无固定依据,根据需要灵活设置
// 类似TextView,ImageView等针对wrap_content均在onMeasure()对设置默认宽 / 高值有特殊处理,具体读者可以自行查看
int mWidth = 400;
int mHeight = 400;
// 当布局参数设置为wrap_content时,设置默认值
if (getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT && getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT) {
setMeasuredDimension(mWidth, mHeight);
// 宽 / 高任意一个布局参数为= wrap_content时,都设置默认值
} else if (getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT) {
setMeasuredDimension(mWidth, heightSize);
} else if (getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT) {
setMeasuredDimension(widthSize, mHeight);
}
- post替代handler,View的内部本身提供了post系列的方法,完全可以替代Handler的作用,使用起来更加方便、直接。
- onAttachedToWindow,调用的时机是当包含View的Activity启动的时刻,适合启动线程/动画/注册各种东东
- onDetachedFromWindow,调用的时机是当包含View的Activity退出或当前View被remove的时刻,适合结束线程/动画/注销各种东东
视图的状态
focused
表示当前视图是否获得到焦点。通常情况下有两种方法可以让视图获得焦点,即通过键盘的上下左右键切换视图,以及调用requestFocus()方法。而现在的Android手机几乎都没有键盘了,因此基本上只可以使用requestFocus()这个办法来让视图获得焦点了。而requestFocus()方法也不能保证一定可以让视图获得焦点,它会有一个布尔值的返回值,如果返回true说明获得焦点成功,返回false说明获得焦点失败。一般只有视图在focusable和focusable in touch mode同时成立的情况下才能成功获取焦点,比如说EditTextwindow_focused
表示当前视图是否处于正在交互的窗口中,这个值由系统自动决定,应用程序不能进行改变。selected
表示当前视图是否处于选中状态。一个界面当中可以有多个视图处于选中状态,调用setSelected()方法能够改变视图的选中状态,传入true表示选中,传入false表示未选中。pressed
表示当前视图是否处于按下状态。可以调用setPressed()方法来对这一状态进行改变,传入true表示按下,传入false表示未按下。通常情况下这个状态都是由系统自动赋值的,但开发者也可以自己调用这个方法来进行改变。
我们可以在项目的drawable目录下创建一个selector文件,在这里配置每种状态下视图对应的背景图片enabled
表示当前视图是否可用。可以调用setEnable()方法来改变视图的可用状态,传入true表示可用,传入false表示不可用。它们之间最大的区别在于,不可用的视图是无法响应onTouch事件的
Canvas
常用方法
注:
//addArc(Rect,startAngle,sweepAngle)startAngle:确定角度的起始位置 sweepAngle : 确定扫过的角度
//扫过的角度360为顺时针一圈,-360为逆时针一圈,但如果扫过的角度超过360则起点会变成0度而非startAngle百分比圆的时候特别注意,这时候一般设置为359
Paint
常见属性
//设置画笔的粗细
mPaint.setStrokeWidth(float width)
// 如设置画笔宽度为10px
mPaint.setStrokeWidth(10f);
// 设置Shader 即着色器,定义了图形的着色、外观 可以绘制出多彩的图形
Paint.setShader(Shader shader)
//设置画笔的a,r,p,g值
mPaint.setARGB(int a, int r, int g, int b)
//设置透明度
mPaint.setAlpha(int a)
//设置字体大小
mPaint.setTextSize(float textSize)
// 文字Style三种模式:
// 类型1:Paint.Style.FILLANDSTROKE(描边+填充)
// 类型2:Paint.Style.FILL(只填充不描边)
// 类型3:Paint.Style.STROKE(只描边不填充)
mPaint.setStyle(Style style);
// 设置对齐方式 LEFT:左对齐 CENTER:居中对齐 RIGHT:右对齐
setTextAlign()
//设置文本的下划线
setUnderlineText(boolean underlineText)
//设置文本的删除线
setStrikeThruText(boolean strikeThruText)
//设置文本粗体
setFakeBoldText(boolean fakeBoldText)
// 设置斜体
Paint.setTextSkewX(-0.5f);
// 设置文字阴影
Paint.setShadowLayer(5,5,5,Color.YELLOW);
path
- 基础路径设置:moveTo/setLastPoint设置当前位置即起始点(前者不受之前的操作影响,后者会)、lineTo连接到此点、close闭合路径
- 重置路径 reset、rewind(前者保留FillType不保留原始数据;后者不保留FillType保留原始数据)
- 常用方法
//圆弧路径 startAngle:确定角度的起始位置 sweepAngle : 确定扫过的角度
//扫过的角度360为顺时针一圈,-360为逆时针一圈,但如果扫过的角度超过360则起点会变成0度而非startAngle百分比圆的时候特别注意,这时候一般设置为359
addArc (RectF oval, float startAngle, float sweepAngle)
//与上面方法唯一不同的是:如果圆弧的起点和上次最后一个坐标点不相同,就连接两个点
arcTo (RectF oval, float startAngle, float sweepAngle)
//圆弧路径 forceMoveTo:是否将之前路径的结束点设置为圆弧起点
arcTo (RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
//圆形路径 dir:指定绘制时是顺时针还是逆时针:CW为顺时针,CCW为逆时针路径起点变为圆在X轴正方向最大的点
addCircle(float x, float y, float radius, Path.Direction dir)
// 椭圆形路径 oval作为椭圆的外切矩形区域
addOval(RectF oval, Path.Direction dir)
//矩形路径
addRect(RectF rect, Path.Direction dir)
//圆角矩形路径
addRoundRect(RectF rect, float rx, float ry, Path.Direction dir)
- addPath合并路径
- isEmpty()、 isRect()、isConvex()、 set() 和 offset()
- 设置填充规则path.setFillType()
// 1. EVEN_ODD:奇偶规则
// 2. INVERSE_EVEN_ODD:反奇偶规则
// 3. WINDING :非零环绕数规则
// 4. INVERSE_WINDING:反非零环绕数规则
路径间运算
newPath.op(path1, path2, Path.Op.DIFFERENCE)
PathMeasure
Layer
贝塞尔曲线
数据点:指路径的起始点和终止点;
控制点:决定了路径的弯曲轨迹;
n+1阶贝塞尔曲线 = 有n个控制点;
(1阶 = 一条直线,高阶可以拆解为多条低阶曲线)
// 绘制二阶贝塞尔曲线
// (x1,y1)为控制点,(x2,y2)为终点
quadTo(float x1, float y1, float x2, float y2)
// (x1,y1)为控制点距离起点的偏移量,(x2,y2)为终点距离起点的偏移量
rQuadTo(float x1, float y1, float x2, float y2)
// 绘制三阶贝塞尔曲线
// (x1,y1),(x2,y2)为控制点,(x3,y3)为终点
cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
// (x1,y1),(x2,y2)为控制点距离起点的偏移量,(x3,y3)为终点距离起点的偏移量
rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
Tencent OS录音机波形动http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=1180
函数模拟https://www.desmos.com/calculator
那些年我们用过的显示性能指标http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=936
其他
- 硬件加速 android:hardwareAccelerated=”false”
trasation?
scroller?
recyclerview.itemTouchHelper?