Android canvas (I)
•
Android
* onDraw()
* diapatchDraw()
* 通过Bitmap创建
* 通过SurfaceView的SurfaceHolder.lockCanvas()
GradientDrawable(GradientDrawable.Orientation orientation, int[] colors)
Eg: get the shape object and set it to fillet:
public class AndroidHuaBuActivity extends AppCompatActivity {
private Button button;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_android_hua_bu);
button = (Button)findViewById(R.id.add_shape_corner);
textView = (TextView)findViewById(R.id.shape_tv);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//通过textView的getBackground获得shape标签
GradientDrawable gradientDrawable = (GradientDrawable)textView.getBackground();
gradientDrawable.setCornerRadius(20);
}
});
}
}
通过textView的背景将下面的xml引入:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#ff0000"/>
<stroke android:width="2dp"
android:color="#00ff00"
android:dashGap="5dp"
android:dashWidth="5dp"/>
</shape>
ShapeDrawable()
ShapeDrawable(Shape shape)
public class ShapeView extends View {
private ShapeDrawable shapeDrawable;
public ShapeView(Context context) {
super(context);
init();
}
public ShapeView(Context context, AttributeSet attributeSet){
super(context, attributeSet);
init();
}
public ShapeView(Context context, AttributeSet attributeSet, int defStyle){
super(context, attributeSet, defStyle);
init();
}
private void init() {
setLayerType(LAYER_TYPE_SOFTWARE,null);
//生成一个ShapeDrawable,并将这个形状的定义为矩形
shapeDrawable = new ShapeDrawable(new RectShape());
//设置shapeDrawable在空间中的显示位置(在当前控件中的位置)
shapeDrawable.setBounds(new Rect(50, 50, 200, 100));
//获取画笔,并将整个Drawable填充为黄色
shapeDrawable.getPaint().setColor(Color.YELLOW);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//将shape实例画在画布上
shapeDrawable.draw(canvas);
}
}
<?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:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".AndroidHuabu.ShapeExample.ShapeActivity">
<com.example.adminstator.myviewdesign.AndroidHuabu.ShapeExample.ShapeView
android:layout_width="250px"
android:layout_height="150px"
android:layout_margin="100dp"
android:background="#ffffff"/>
</LinearLayout>
//startAngle:指的是开始的角度,扇形开始的0度在椭圆的X轴正方向上,即右中间的位置(顺时针方向)
//sweepAngle:指扇形所扫过的角度
public ArcShape(ffloat startAngle, float sweepAngle)
//outerRadii:外围矩形的各个角的角度大小,需要填充8个数字,每两个数字一组,分别对应(左上角,右上角, 右下角,左下角)4个角的角度组(x, y),每两个一组的数字构成一个椭圆。第一个数字代表椭圆的X轴半径,第二个数字代表椭圆的Y轴半径, 如果不需要指定外围矩形的各个角的角度,可以传入null
//RectF inset:表示内部矩形与 外部矩形各边的边距,RectF的4个值分别对应left,top, right, bottom, 如果不需要内部矩形的镂空效果,则可以传入null
//float[] innerRadii:表示内部矩形的各个角的角度大小,同样需要填充8个数字,其含义与outerRadii一样,如果不指定各个角的角度,则传入null即可
public RoundRectShape(float[] outerRadii, RectF inset, float[] innerRadii)
eg:
public class ShapeView extends View {
private ShapeDrawable shapeDrawable;
public ShapeView(Context context) {
super(context);
init();
}
public ShapeView(Context context, AttributeSet attributeSet){
super(context, attributeSet);
init();
}
public ShapeView(Context context, AttributeSet attributeSet, int defStyle){
super(context, attributeSet, defStyle);
init();
}
private void init() {
setLayerType(LAYER_TYPE_SOFTWARE,null);
// //生成一个ShapeDrawable,并将这个形状的定义为矩形
// shapeDrawable = new ShapeDrawable(new ArcShape(0, 300));
// //设置shapeDrawable在空间中的显示位置(在当前控件中的位置)
// shapeDrawable.setBounds(new Rect(50, 50, 200, 100));
// //获取画笔,并将整个Drawable填充为黄色
float[] outerRadii = new float[]{12, 12, 12, 12, 0, 0, 0, 0};
RectF inset = new RectF(6, 6, 6, 6);
float[] innerRadii = new float[]{50, 12, 0, 0, 12, 50, 0, 0};
shapeDrawable = new ShapeDrawable(new RoundRectShape(outerRadii, inset, innerRadii));
shapeDrawable.setBounds(50, 50, 200, 100);
shapeDrawable.getPaint().setColor(Color.BLUE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//将shape实例画在画布上
shapeDrawable.draw(canvas);
}
}
//path:所要画的路径
//stdWidth:表示标注宽度,即将整个ShapeDrawable的宽度分成多少份,Path中moveTo(x, y),lineTo(x, y)这些函数中的数值在这里起始都是以每一份的位置来计算的,当ShapeDrawable动态变大、变小时,每一份都会变小,而根据这些分的数值画出来的Path图形就是动态缩放
//stdHeight:表示标准高度,即将ShapeDrawable的高度分成多少份
public PathShape(Path path, float stdWidth, float stdHeight)
eg:
public class ShapeView extends View {
private ShapeDrawable shapeDrawable;
public ShapeView(Context context) {
super(context);
init();
}
public ShapeView(Context context, AttributeSet attributeSet){
super(context, attributeSet);
init();
}
public ShapeView(Context context, AttributeSet attributeSet, int defStyle){
super(context, attributeSet, defStyle);
init();
}
private void init() {
setLayerType(LAYER_TYPE_SOFTWARE,null);
Path path = new Path();
//注意这里此时的单位是份
path.moveTo(0, 0);
path.lineTo(100, 0);
path.lineTo(100, 100);
path.lineTo(0, 100);
path.close();
//首先我们要知道这里的单位是份的概念而不是px,所以为了对比,我们将shapeDrawable和画布大小设为一致
// 开始将shape 100, 100 可以发现它填满了控件如果使用的是px当然是不可能将其填满的,
// 将ShapeDrawable的高设置成200,则原来的只能占1/2,所以只能展示为控件的一半
shapeDrawable = new ShapeDrawable(new PathShape(path, 100, 200));
shapeDrawable.setBounds(new Rect(0, 0, 250, 150));
shapeDrawable.getPaint().setColor(Color.BLUE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//将shape实例画在画布上
shapeDrawable.draw(canvas);
}
}
public class PathShape extends Shape {
private final float mStdWidth;
private final float mStdHeight;
private Path mPath;
private float mScaleX; // cached from onResize
private float mScaleY; // cached from onResize
/**
* PathShape constructor.
*
* @param path a Path that defines the geometric paths for this shape
* @param stdWidth the standard width for the shape. Any changes to the
* width with resize() will result in a width scaled based
* on the new width divided by this width.
* @param stdHeight the standard height for the shape. Any changes to the
* height with resize() will result in a height scaled based
* on the new height divided by this height.
*/
public PathShape(@NonNull Path path, float stdWidth, float stdHeight) {
mPath = path;
mStdWidth = stdWidth;
mStdHeight = stdHeight;
}
@Override
public void draw(Canvas canvas, Paint paint) {
canvas.save();
canvas.scale(mScaleX, mScaleY);
canvas.drawPath(mPath, paint);
canvas.restore();
}
@Override
protected void onResize(float width, float height) {
mScaleX = width / mStdWidth;
mScaleY = height / mStdHeight;
}
@Override
public PathShape clone() throws CloneNotSupportedException {
final PathShape shape = (PathShape) super.clone();
shape.mPath = new Path(mPath);
return shape;
}
}
package com.example.adminstator.myviewdesign.AndroidHuabu.ShapeExample;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.RegionIterator;
import android.graphics.drawable.shapes.Shape;
/**
* Created with Android Studio.
* Description:
*
* @author: 王拣贤
* @date: 2019/06/27
* Time: 21:32
*/
public class OwnShapeView extends Shape {
private Region region;
public OwnShapeView(Region region){
if(region!=null){
this.region = region;
}
}
@Override
public void draw(Canvas canvas, Paint paint) {
RegionIterator iter = new RegionIterator(region);
Rect r = new Rect();
while (iter.next(r)){
canvas.drawRect(r, paint);
}
}
}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
二维码