05、Android绘图机制

一、绘图基础

1.1、Canvas和Paint

系统提供Canvas对象来提供绘图方法,其中Paint常见的属性如下:

mPaint.setAntiAlias()            // 设置画笔的锯齿效果
mPaint.setColor()                // 设置画笔的颜色
mPaint.setARGB()                 // 设置画笔的A、R、G、B值
mPaint.setAlpha()                // 设置画笔的Alpha值
mPaint.setTextSize()             // 设置字体的尺寸
mPaint.setStyle()                // 设置画笔的风格(空心或实心)
mPaint.setStrokeWidth()          // 设置空心边框的宽度

1、基本绘制

// 1、绘制点
canvas.drawPoint(x, y, paint);
// 2、绘制直线 
canvas.drawLine(startX, startY, stopX, stopY, paint); 
// 3、绘制多条直线
float[] pts = {
    startX1, startY1, endX1, endY1,
    ......
    startXn, startYn, endXn, endYn};
canvas.drawLines(pts, paint);
// 4、绘制矩形
canvas.drawRect(left, top, right, bottom, paint);  
// 5、绘制圆角矩形
canvas.drawRoundRect(left, top, right, bottom, rx, ry, paint);  
// 6、绘制圆
canvas.drawCircle(cx, cy, radius, paint);
// 7、绘制弧形,这里需要注意绘制弧线和扇形的区分就是倒数第二个参数useCenter的值,true或false
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
// 8、绘制椭圆
canvas.drawOval(left, top, right, bottom, paint);
// 9、绘制文本
canvas.drawText(text, x, y, paint);
// 10、在指定位置绘制文本
canvas.drawPosText(text, 
        new float[]{
        X1, Y1,
        ......
        Xn, Yn}, paint);
// 11、绘制路径
Path path = new Path();
path.moveTo(50, 50);
path.lineTo(100, 100);
path.lineTo(100, 300);
canvas.drawPath(path, mPaint);

1.2、Shape绘图

1、xml控件配置属性

android:background="@drawable/shape"

image

3、shape制作圆角

image

<Button
    android:layout_width="160dp"
    android:layout_height="wrap_content"
    android:background="@drawable/button_shape"
    android:text="圆角按钮" />
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <solid android:color="#fff"/>
    <padding android:top="10px" android:bottom="10px"/>
    <corners android:radius="16px"/>
    <stroke android:width="1px" android:color="#000"/>
</shape>

4、shape制作虚线

7c2994a7-d2ae-445e-9fce-45b9e8d5c14f

没有dashGap属性则为实线

<View
    android:layout_width="match_parent"
    android:layout_height="5px"
    android:layout_marginTop="10dp"
    android:background="@drawable/line_shape" />
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="line" >
    <stroke
        android:dashGap="3dp"
        android:dashWidth="8dp"
        android:width="1dp"
        android:color="#63a219"/>
    <size android:height="1dp"/>
</shape>

5、shape制作渐变

image

<View
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:layout_marginTop="10dp"
    android:background="@drawable/gra_shape" />
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <gradient
        android:angle="270.0"
        android:startColor="#000000"
        android:endColor="#ffffff"/>
</shape>

1.3、Layer

Layer是在Photoshop中非常的功能。在Android中同样可以通过Layer来实现类似Photoshop中图层的概念。

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <!-- 图片  1-->
    <item android:drawable="@drawable/ic_launcher"></item>
    <!-- 图片 2 -->
    <item 
        android:drawable="@drawable/ic_launcher"
        android:left="10.0dip"
        android:top="10.0dip"
        android:right="10.0dip"
        android:bottom="10.0dip">
    </item>
</layer-list>
下面我们看一个实例:
a) 在drawable下建立add_layer.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:drawable="@drawable/a"></item>
 <item android:drawable="@drawable/b"></item>
</layer-list>  

引用:

<ImageView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:background="@drawable/add_layer" />  

+ =

1.4、Selector

1、创建xml文件

创建xml文件,位置:drawable/xxx.xml.同目录下记得放相关图片

image

<?xml version="1.0" encoding="utf-8"?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android"> 
       <!-- 没有焦点时的背景图片 --> 
       <item android:drawable="@drawable/handle_normal" android:state_enabled="true" android:state_window_focused="false"/> 
       <!-- 触摸模式按下时的背景图片 --> 
       <item android:drawable="@drawable/handle_pressed" android:state_pressed="true"/> 
       <item android:drawable="@drawable/handle_focused" android:state_enabled="true" android:state_focused="true"/> 
       <item android:drawable="@drawable/handle_normal" android:state_enabled="true"/> 
       <!-- 获得焦点时的图片背景 --> 
       <item android:drawable="@drawable/handle_focused" android:state_focused="true"/> 
       
       <!-- android:state_selected是选中 
            android:state_focused是获得焦点   
            android:state_pressed是点击 
            android:state_enabled是设置是否响应事件,指所有事件 --> 
</selector>

2、使用xml文件

   1.方法一:在listview中配置android:listSelector="@drawable/xxx或在listview的item中添加属性android:background="@drawable/xxx"

   2.方法二:

Drawable drawable = getResources().getDrawable(R.drawable.xxx);  
ListView.setSelector(drawable);

但是这样会出现列表有时候为黑的情况,需要加上:android:cacheColorHint="@android:color/transparent"使其透明。

3、Shape选择器

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <!-- 填充的颜色 -->
            <solid android:color="#33444444"/>
            <!-- 设置按钮的四个角为弧形 -->
            <corners android:radius="5dp"/>
            <!-- padding:Button里面的文字与Button的边界的间隔 -->
            <padding 
                android:bottom="10dp"
                android:left="10dp"
                android:right="10dp"
                android:top="10dp"/>
        </shape>
    </item>
    
    <item android:state_pressed="false">
        <shape android:shape="rectangle">
            <!-- 填充的颜色 -->
            <solid android:color="#FFFFFF"/>
            <!-- 设置按钮的四个角为弧形 -->
            <corners android:radius="5dp"/>
            <!-- padding:Button里面的文字与Button边界间隔 -->
            <padding 
                android:bottom="10dp"
                android:left="10dp"
                android:right="10dp"
                android:top="10dp"/>
        </shape>
    </item>
</selector>

使用方法:

android:focusable="true" 
android:background="@drawable/shape_select"

4、颜色选择器

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true"><color android:color="#999999" /></item>
    <item android:state_pressed="false"><color android:color="#ffffff" /></item>
</selector>

二、绘图进阶

1.1、Canvas

Canvas作为绘制图像的直接对象,提供以下几个非常有用的方法:

  • Canvas.save(): 保存画布,将之前所有已经绘制的图像保存起来,让后续操作在新的图层上操作。
  • Canvas.restore()   合并图层操作,它的作用是将save()之后绘制的所有图像与save()之前的图像进行合并。
  • Canvas.translate() 和 Canvas.rotate():画布的坐标系的翻转和偏移。

1、绘制仪表盘实例

  • 仪表盘 --- 外面的大圆盘
  • 刻度线 --- 包含四个长的刻度线和其他短的刻度线
  • 刻度值 --- 包含长刻度线对应的大的刻度值和其他小的刻度值
  • 指针   --- 中间的指针,一粗一细两根指针

image

public class KeDuPanView extends View {
    private int mWidth;
    private int mHeight;
    public KeDuPanView(Context context) {
        this(context, null);
    }
    public KeDuPanView(Context context, AttributeSet attrs) {
        super(context, attrs);
        WindowManager wManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        mWidth = wManager.getDefaultDisplay().getWidth();
        mHeight = wManager.getDefaultDisplay().getHeight();
    }
    
    @Override
    protected void onDraw(Canvas canvas) {      
        // 画外圆
        Paint paintCircle = new Paint();
        paintCircle.setStyle(Paint.Style.STROKE);
        paintCircle.setAntiAlias(true);
        paintCircle.setStrokeWidth(5);
        canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, paintCircle);
        
        // 画刻度
        Paint paintDegree = new Paint();
        paintDegree.setStrokeWidth(3);
        for (int i = 0; i < 24; i++) {
            // 区分整点和非整点
            if(i == 0 || i== 6 || i == 12 || i == 18){
                paintDegree.setStrokeWidth(5);
                paintDegree.setTextSize(18);
                // 画长刻度
                canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2, 
                        mWidth / 2, mHeight / 2 - mWidth / 2 + 30, paintDegree);
                // 画数字
                String degree = String.valueOf(i);
                canvas.drawText(degree, mWidth / 2 - paintDegree.measureText(degree) / 2,
                        mHeight / 2 - mWidth / 2 + 45, paintDegree);
            }else{
                // 画短刻度
                paintDegree.setStrokeWidth(3);
                paintDegree.setTextSize(15);
                canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2, mWidth / 2, 
                        mHeight / 2 - mWidth / 2 + 15, paintDegree);
                
                // 画数字
                String degree = String.valueOf(i);
                canvas.drawText(degree, mWidth / 2 - paintDegree.measureText(degree) / 2, 
                        mHeight / 2 - mWidth / 2 + 30, paintDegree);
            }
            // 通过旋转画布简化坐标运算
            canvas.rotate(15, mWidth / 2, mHeight / 2);
        }
        
        // 画中间指针,时针和分针
        Paint paintHour = new Paint();
        paintHour.setStrokeWidth(10);
        Paint paintMinute = new Paint();
        paintMinute.setStrokeWidth(5);
        canvas.save();
        // 开始位置移动到屏幕中心点
        canvas.translate(mWidth / 2, mHeight / 2);
        canvas.drawLine(0, 0, 50, 50, paintHour);
        canvas.drawLine(0, 0, 50, 100, paintMinute);
        canvas.restore();
    }
}

1.2、Layer图层

Android中使用saveLayer()方法创建一个图层,图层是基于栈的结构进行管理的。

通过调用saveLayer()、saveLayerAlpha()方法将一个图层入栈,使用restore()、restoreToCount()方法将一个图层出栈。

入栈的时候,后面所有操作都发生在该图层上,出栈的时候,则会把图像绘制到上层的Canvas上。

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawColor(Color.WHITE);
    mPaint.setColor(Color.BLUE);
    canvas.drawCircle(150, 150, 100, mPaint);
    
    canvas.saveLayerAlpha(0, 0, 400, 400, 127, LAYER_TYPE_NONE);
    mPaint.setColor(Color.RED);
    canvas.drawCircle(200, 200, 100, mPaint);
    canvas.restore(); 
}

image

图层透明度设置为0 - 255之间:

当透明度为127时,即半透明、当透明度为255时,即完全不透明、当透明度为0时,即完全透明。

三、色彩特效处理

1.1、色彩矩阵分析

在色彩处理中,通常使用以下三个角度来描述一个图像:

  • 色调 ----    物体传播的颜色
  • 饱和度  ----    颜色的纯度,从0(灰)到100%(饱和)来进行描述。
  • 亮度    ----    颜色的相对明暗程度。

在Android中,系统使用一个颜色矩阵--ColorMatrix,来处理图像的这些色彩效果。它是一个4 * 5 的数字矩阵,

它用来对图片的色彩进行处理。

对于图像中的任何一个像素点(由R、G、B、A组成),对该点应用颜色矩阵变换后,得到新的像素值。

image

其中我们不难发现其实颜色矩阵代表的就是红绿蓝和透明值,其中e、j、o、t称为偏移量。

  • a、b、c、d、e    --- 红色值
  • f、g、h、i、j    ---    绿色值
  • k、l、m、n、o    ---    蓝色值
  • p、q、r、s、t    ---    透明值

矩阵运算的乘法计算公式在线性代数中都学过,计算过程如下:

R1 = a x R + b x G + c x B + d x A + e;
G1 = f x R + g x G + h x B + i x A + j;
B1 = k x R + l x G + m x B + n x A + o;
A1 = p x R + q x G + r x B + s x A + i;

待续。。。。。。。

 

转载于:https://www.cnblogs.com/pengjingya/p/5505226.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值