Android绘图(一)

本文介绍了Android平台上的2D绘图基础知识,包括Paint的基本属性、Canvas的常用方法及XML绘图方法。同时,还提供了单位转换工具类,用于处理不同屏幕密度下的布局适配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(《群英传》)整理笔记:

基本知识点:

分辨率:手机屏幕的像素点个数。
PPI(DPI):对角线的像素点除以屏幕的大小。

系统屏幕密度:
Ldpi:240×320;
Mdpi:320×480;
Hdpi:480×800;
Xhdpi:720×1280;
Xxhdpi:1080×1920。

单位转换:

package com.android.utils;

import android.content.Context;

/**
 * 单位转换工具类(公式换算方法)
 * 
 * @author Administrator
 *
 */
public class UnitConversion {

    /**
     * 将px值转换为dip或dp值,保证尺寸不变。 density为换算比例
     * 
     * @param context
     * @param pxValue
     * @return
     */
    public static int px2dip(Context context, float pxValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

    /**
     * 将dip或dp转换为px值,保证尺寸大小不变
     * 
     * @param context
     * @param dipValue
     * @return
     */
    public static int dip2px(Context context, float dipValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }

    /**
     * 将px值转换为sp值,保证尺寸大小不变
     * 
     * @param context
     * @param pxValue
     * @return
     */
    public static int px2sp(Context context, float pxValue) {
        final float fontScale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / fontScale + 0.5f);
    }

    /**
     * 将sp值转换为px值,保证尺寸大小不变
     * 
     * @param context
     * @param spValue
     * @return
     */
    public static int sp2px(Context context, float spValue) {
        final float fontScale = context.getResources().getDisplayMetrics().density;
        return (int) (spValue * fontScale + 0.5f);
    }

}

2D绘图基础:

Paint的基本属性:
setAntiAlias(true); // 设置画笔的锯齿效果
setColor(); // 设置画笔的颜色
SetARGB(); // 设置画笔的A、R、G、B值
setAlpha(); // 设置画笔的Alpha(透明度)值
setTextSize() ; //设置字体的尺寸
setStyle(); // 设置画笔的风格(空心或实心)
setStrokeWidth(); // 设置空心边框的宽度

Canvas的常用方法:
DrawPoint:绘制点;
DrawLine:绘制直线;
DrawLines:绘制多条直线;

float[] pts = {
                startX1, startY1, endX1, endY1,
                …… ……
                startXn, startYn, endXn, endYn
        };
        canvas.drawLines(pts, paint);

DrawRect:绘制矩形;
DrawRoundRect:绘制圆角矩形;
DrawCircle:绘制圆;
DrawArc:绘制弧形、扇形。useCenter(true)为扇形;
DrawOval:绘制椭圆(外接矩形);
DrawText():绘制文本;
DrawPosText:在指定位置绘制文本;
DrawPath:绘制路径–>

Path patn = new Path();
path.moveTo(50, 50);
path.lineTo(100, 100);
path.lineTo(100, 300);
path.lineTo(300, 50);
canvas.drawPath(path,paint);

Android XML绘图:
1、Bitmap:可以将图片转换成Bitmap在程序中使用

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/ic_launcher" >

</bitmap>

2、Shape:可以在XML中绘制各种形状
(为了说明用法,格式并不准确)

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <!-- 绘制各种形状 -->

    <!-- 指定大小,一般用在imageview配合scaleType属性使用 -->
    <size 
        android:width="integer"
        android:height="integer"/>

    <!-- 渐变 -->
    <gradient
        android:angle="45"
        android:endColor="color"
        android:startColor="color"
        android:centerX="integer"
        android:centerY="integer"
        android:centerColor="color"
        android:gradientRadius="integer"
        android:type="linear"
        android:useLevel="true" />

    <padding 
        android:left="integer"
        android:top="integer"
        android:right="integer"
        android:bottom="integer"/>

    <!-- 填充颜色 -->
    <solid android:color="color"/>

    <!-- 指定边框 -->
    <stroke android:width="integer"
        android:color="color"
        // 虚线宽度
        android:dashWidth="integer"
        // 虚线间隔宽度
        android:dashGap="integer"/>

    <corners android:radius="integer"/>

</shape>

通过渐变实现的阴影效果

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >


    <!-- 阴影效果 -->

    <gradient
        android:angle="45"
        android:endColor="#805FBBFF"
        android:startColor="#FF5DA2FF" />

    <padding
        android:bottom="7dp"
        android:left="7dp"
        android:right="7dp"
        android:top="7dp" />

    <corners android:radius="8dp" />

</shape>

3、Layer图层:
图片会依次叠加

<?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:bottom="10.0dp"
        android:drawable="@drawable/ic_launcher"
        android:left="10.0dp"
        android:right="10.0dp"
        android:top="10.0dp">
    </item>

</layer-list>

4、Selector:
他的作用是帮助开发者实现静态绘图中的事件反馈,通过给不同的事件设置不同的图像,从而在程序中根据用户输入,返回不同的效果。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- 默认时的背景图片 -->
    <item android:drawable="@drawable/pic1"></item>
    <!-- 没有焦点时的背景图片 -->
    <item android:drawable="@drawable/pic2" android:state_window_focused="false"></item>
    <!-- 非触摸模式下获得焦点并单击时的背景图片 -->
    <item android:drawable="@drawable/pic3" android:state_focused="true" android:state_pressed="true"></item>
    <!-- 触摸模式下单击时的背景图片 -->
    <item android:drawable="@drawable/pic4" android:state_focused="false" android:state_pressed="true"></item>
    <!-- 选中时的背景图片 -->
    <item android:drawable="@drawable/pic5" android:state_selected="true"></item>
    <!-- 获得焦点时的背景图片 -->
    <item android:drawable="@drawable/pic6" android:state_focused="true"></item>

</selector>

5、上面方法的共同作用:

<?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 
                android:bottom="10dp"
                android:left="10dp"
                android:right="10dp"
                android:top="10dp"/>
        </shape>
    </item>

    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <solid android:color="#FFFFFF"/>
            <corners android:radius="5dp"/>
            <padding 
                android:bottom="10dp"
                android:left="10dp"
                android:right="10dp"
                android:top="10dp"/>
        </shape>
    </item>

</selector>

绘图技巧:
1、Canvas:
Canvas.save():将之前的所有已绘制图像保存起来;
Canvas.restore():合并图层;
Canvas.translate():坐标系的平移;
Canvas.rotate():坐标系的反转。

示例:时钟

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.WindowManager;

public class MyClock extends View {

    private int mWidth;
    private int mHeight;

    public MyClock(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context);
    }

    public MyClock(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView(context);
    }

    public MyClock(Context context) {
        super(context);
        initView(context);
    }

    // 获取屏幕的宽和高
    private void initView(Context context) {
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics dm = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(dm);
        mWidth = dm.widthPixels;
        mHeight = dm.heightPixels;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint panintCicle = new Paint();
        panintCicle.setStyle(Paint.Style.STROKE);
        panintCicle.setAntiAlias(true);
        panintCicle.setStrokeWidth(5);

        canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, panintCicle);

        Paint paintDegree = new Paint();
        panintCicle.setStrokeWidth(3);
        for (int i = 0; i < 12; i++) {
            // 区分整点与非整点
            if (i == 0 || i == 3 || i == 6 || i == 9) {

                paintDegree.setStrokeWidth(5);
                paintDegree.setTextSize(100);

                canvas.drawLine(
                        mWidth / 2,
                        mHeight / 2 - mWidth / 2 + 100,
                        mWidth / 2, mHeight / 2 - mWidth,
                        paintDegree);

                String degree = String.valueOf(i);
                canvas.drawText(
                        degree,
                        mWidth / 2 - paintDegree.measureText(degree) / 2,
                        mHeight / 2 - mWidth / 2 + 170,
                        paintDegree);
            } else {
                paintDegree.setStrokeWidth(3);
                paintDegree.setTextSize(50);
                canvas.drawLine(
                        mWidth / 2,
                        mHeight / 2 - mWidth / 2 + 60,
                        mWidth / 2,
                        mHeight / 2 - mWidth,
                        paintDegree);

                String degree = String.valueOf(i);
                canvas.drawText(
                        degree,
                        mWidth / 2 - paintDegree.measureText(degree) / 2,
                        mHeight / 2 - mWidth / 2 + 100,
                        paintDegree);
            }
            // 通过旋转画布简化坐标运算
            canvas.rotate(30, mWidth / 2, mHeight / 2);
        }

        // 画指针
        Paint paintHour = new Paint();
        paintHour.setStrokeWidth(20);
        Paint paintMinute = new Paint();
        paintMinute.setStrokeWidth(10);
        canvas.save();

        canvas.translate(mWidth / 2, mHeight / 2);
        canvas.drawLine(0, 0, 100, 100, paintHour);
        canvas.drawLine(0, 0, 100, 200, paintMinute);
        canvas.restore();

    }

}

2、Layer图层
使用saveLayer()方法来创建一个图层,图层是基于栈的结构进行管理。调用saveLayer()、saveLayerAlpha(),使用restore()、restoreToCount()将一个图层出栈。

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.WHITE);
        Paint mPaint = new Paint();
        mPaint.setColor(Color.BLUE);
        canvas.drawCircle(150, 150, 100, mPaint);

        // 入栈
        canvas.saveLayerAlpha(0, 0, 400, 400, 127, LAYER_FLAGS);
        mPaint.setColor(Color.RED);
        canvas.drawCircle(200, 200, 100, mPaint);

        // 出栈
        canvas.restore();
    }

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

资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在 IT 领域,文档格式转换是常见需求,尤其在处理多种文件类型时。本文将聚焦于利用 Java 技术栈,尤其是 Apache POI 和 iTextPDF 库,实现 doc、xls(涵盖 Excel 2003 及 Excel 2007+)以及 txt、图片等格式文件向 PDF 的转换,并实现在线浏览功能。 先从 Apache POI 说起,它是个强大的 Java 库,专注于处理 Microsoft Office 格式文件,比如 doc 和 xls。Apache POI 提供了 HSSF 和 XSSF 两个 API,其中 HSSF 用于读写老版本的 BIFF8 格式(Excel 97-2003),XSSF 则针对新的 XML 格式(Excel 2007+)。这两个 API 均具备读取和写入工作表、单元格、公式、样式等功能。读取 Excel 文件时,可通过创建 HSSFWorkbook 或 XSSFWorkbook 对象来打开相应格式的文件,进而遍历工作簿中的每个 Sheet,获取行和列数据。写入 Excel 文件时,创建新的 Workbook 对象,添加 Sheet、Row 和 Cell,即可构建新 Excel 文件。 再看 iTextPDF,它是个用于生成和修改 PDF 文档的 Java 库,拥有丰富的 API。创建 PDF 文档时,借助 Document 对象,可定义页面尺寸、边距等属性来定制 PDF 外观。添加内容方面,可使用 Paragraph、List、Table 等元素将文本、列表和表格加入 PDF,图片可通过 Image 类加载插入。iTextPDF 支持多种字体和样式,可设置文本颜色、大小、样式等。此外,iTextPDF 的 TextRenderer 类能将 HTML、
资源下载链接为: https://pan.quark.cn/s/1bfadf00ae14 VESA DSC(Display Stream Compression)是由视频电子标准协会(Video Electronics Standards Association)推出的种高效低延迟的图像数据压缩技术,主要用于缓解高分辨率、高刷新率显示系统中显示接口的数据传输压力。它在不降低画质的前提下,可显著降低带宽需求,从而提升显示系统性能。VESA DSC有多个版本,从 v1.1 到 v1.2b,每个版本都对前版本进行了改进和优化,比如修复错误、提升性能或增强兼容性。其中,v1.1 是基础版本,v1.2 系列则是对原始规范的逐步完善,v1.2a 和 v1.2b 通常是针对特定问题或新需求的微调版本。 DSC 压缩规格说明书详细介绍了 DSC 的工作原理、编码流程、解码算法以及与显示系统的接口规范,涵盖以下关键点:1. 压缩算法:DSC 结合了熵编码和预测编码,通过预测连续像素间的差异来减少传输信息量,其中熵编码单元(EEU)和熵解码单元(EDU)负责数据的编码和解码。2. 帧内和帧间预测:DSC 支持基于同帧内像素信息的帧内预测,以及利用前后帧像素关系的帧间预测,从而在保持画质的同时提高压缩效率。3. 带宽管理:DSC 标准可动态调整压缩比率,以适配显示设备的实际带宽需求,确保流畅显示。4. 实时性和低延迟:DSC 设计时注重实时应用,尽可能减少压缩和解压缩过程中的延迟,这对于游戏和专业图形应用至关重要。5. 兼容性和互操作性:作为 VESA 的标准,DSC 与其他显示接口标准(如 HDMI、DP 等)兼容,保证不同设备间的互操作性。6. C Model 源码:提供的 C 模型源码是 DSC 算法的参考实现,有助于开发者理解 DSC 工作机制,用于开发 DSC 兼容的硬件或软件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值