在使用了Panit画笔之后,可以对其进行渲染,从而达到更加人性化的方式

渲染分类

按常用渲染方式可以分为以下几种:

  • BimapShader位图的图像渲染器
  • LinearGradient线性渲染
  • RadialGradient环形渲染:水波纹效果,充电水波纹扩散效果、调色板
  • SweepGradient梯度渲染(扫描渲染):微信等雷达扫描效果,手机卫士垃圾扫描
  • ComposeShader组合渲染

BimapShader

首先来研究下BimapShader是怎么使用的

一般来说绘制位图使用这种方式

canvas.drawBitmap(bitmap, 0, 0, paint);

这样就直接将位图绘制在界面上,那么使用以后,可以设置三种系统模式,设置完以后画笔添加Shader,然后就可以使用位图渲染器了

这样的设置运用于图片宽高小于给定的宽高的处理方式

//CLAMP 拉伸最后一个像素填满
//MIRROR 镜像翻转填满
//REPEAT 重复图片平铺填满
bitmapShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
paint.setShader(bitmapShader);
//绘制边界
canvas.drawRect(new Rect(0, 0, 800, 800), paint);

其常用的场景其中一个就是绘制用户圆形头像,其中width为bitmap的宽

canvas.drawCircle(width / 2, width / 2, width / 2, paint);

这样的设置会以图片的中心点切出一个圆,那么如果图片方形,切出的图片效果还可以,那么如果为矩形,要么设置时候切为方形,要么继续处理,其思路就是对短边进行拉伸,但一般不建议那么做,那样做图片就变形了,其拉伸代码如下

float scale = (float) Math.max(width, height) / Math.min(width, height);
Matrix matrix = new Matrix();
matrix.setScale(scale, scale);
bitmapShader.setLocalMatrix(matrix);
paint.setShader(bitmapShader);
canvas.drawCircle(Math.min(width, height) / 2f, scale * Math.max(width, height) / 2f,
Math.max(width, height) / 2f, paint)

当然也可以绘制椭圆

canvas.drawOval(new RectF(0, 0, width, height), paint);

另外通过shapeDrawable也可以实现

ShapeDrawable shapeDrawable = new ShapeDrawable(new OvalShape());
shapeDrawable.getPaint().setShader(bitmapShader);
shapeDrawable.setBounds(0, 0, width, width);
shapeDrawable.draw(canvas);

LinearGradient

线性渲染,其实就是一种线性渐变,可以实现各种炫酷的过度效果

LinearGradient的参数:

x0, y0:起始点

x1, y1:结束点

int[] colors:中间依次要出现的几个颜色

float[] positions:数组大小跟colors数组一样大,中间依次摆放的几个颜色分别放置在那个位置上(参考比例从左往右)

TileMode tile:CLAMP,MIRROR和REPEAT

LinearGradient linearGradient = new LinearGradient(0, 0, 500, 0, colors, null, Shader.TileMode.CLAMP);
paint.setShader(linearGradient);
paint.setStrokeWidth(20);
canvas.drawLine(0, 0, 500, 0, paint);

其效果就是画出一条渐变色的彩带,和调色板类似

RadialGradient

环形渲染可以做出很多炫酷的效果,水波纹,充电波动等等,都是环形渲染做出来的

RadialGradient radialGradient = new RadialGradient(100, 100, 50, colors, null, Shader.TileMode.CLAMP);
paint.setShader(radialGradient);
canvas.drawCircle(100, 100, 50, paint);

SweepGradient

类似于色度盘

SweepGradient sweepGradient = new SweepGradient(100, 100, colors, null);
paint.setShader(sweepGradient);
canvas.drawCircle(100, 100, 50, paint);

ComposeShader

组合多个渲染方式,其参数为多个

ComposeShader composeShader = new ComposeShader(radialGradient, sweepGradient, PorterDuff.Mode.SRC_OVER);
paint.setShader(composeShader);
canvas.drawCircle(100, 100, 50, paint);

参数示例图如下



具体代码参阅Android示例源代码Xfermodes.java

参数意义为:

  • PorterDuff.Mode.CLEAR 所绘制不会提交到画布上
  • PorterDuff.Mode.SRC 显示上层绘制图片
  • PorterDuff.Mode.DST 显示下层绘制图片
  • PorterDuff.Mode.SRC_OVER 正常绘制显示,上下层绘制叠盖
  • PorterDuff.Mode.DST_OVER 上下层都显示。下层居上显示
  • PorterDuff.Mode.SRC_IN 取两层绘制交集。显示上层
  • PorterDuff.Mode.DST_IN 取两层绘制交集。显示下层
  • PorterDuff.Mode.SRC_OUT 取上层绘制非交集部分
  • PorterDuff.Mode.DST_OUT 取下层绘制非交集部分
  • PorterDuff.Mode.SRC_ATOP 取下层非交集部分与上层交集部分
  • PorterDuff.Mode.DST_ATOP 取上层非交集部分与下层交集部分
  • PorterDuff.Mode.XOR 异或:去除两图层交集部分
  • PorterDuff.Mode.DARKEN 取两图层全部区域,交集部分颜色加深
  • PorterDuff.Mode.LIGHTEN 取两图层全部,点亮交集部分颜色
  • PorterDuff.Mode.MULTIPLY 取两图层交集部分叠加后颜色
  • PorterDuff.Mode.SCREEN 取两图层全部区域,交集部分变为透明色

图像示例

//线性渲染
LinearGradient linearGradient = new LinearGradient(200, 100, 600, 100, colors, null, Shader.TileMode.CLAMP);
paint.setShader(linearGradient);
paint.setStrokeWidth(50);
canvas.drawLine(200, 100, 600, 100, paint); //环形渲染
RadialGradient radialGradient = new RadialGradient(400, 400, 200, colors, null, Shader.TileMode.CLAMP);
paint.setShader(radialGradient);
canvas.drawCircle(400, 400, 200, paint); //梯度渲染
SweepGradient sweepGradient = new SweepGradient(400, 1000, colors, null);
paint.setShader(sweepGradient);
canvas.drawCircle(400, 1000, 200, paint);

从上到下依次是线性渲染,环形渲染和梯度渲染

例子:歌词的显示效果

自定义一个TextView,然后在绘制时候通过矩阵变换,不断设置线性渐变的位置,从而达到效果

public class LinearGradientTextView extends TextView {
private TextPaint paint;
private float translateX;
private LinearGradient linearGradient;
private Matrix matrix;
private float textWidth;
private float deltaX = 10; public LinearGradientTextView(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);
paint = getPaint();
//获得文字宽度,即为渲染宽度
String text = getText().toString();
textWidth = paint.measureText(text);
int gradientSize = (int) (textWidth / text.length());
linearGradient = new LinearGradient(2 * gradientSize, 0, 0, 0,
new int[]{0x0FFFFFFF, 0xFFFFFFFF, 0x0FFFFFFF}, null, Shader.TileMode.CLAMP);
paint.setShader(linearGradient);
matrix = new Matrix();
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
translateX += deltaX;
if (translateX > textWidth + 1 || translateX < 1) {
deltaX = -deltaX;
}
//矩阵变换
matrix.setTranslate(translateX, 0);
linearGradient.setLocalMatrix(matrix);
postInvalidate();
}
}

布局

<?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"
android:background="@android:color/darker_gray"> <com.cj5785.shadertest.LinearGradientTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="这段文字用来测试线性渐变的效果"
android:textColor="@android:color/black"
android:textSize="24sp" /> </LinearLayout>

效果图如下

例子:放大镜

这里自定义一个View,用来承载图片以及局部放大

public class ZoomImageView extends View {
private Bitmap bitmap;
private ShapeDrawable drawable;
//缩放的倍数
private static final int FACTOR = 2;
//缩放的半径
private static final int RADIUS = 100;
private Matrix localM = new Matrix(); public ZoomImageView(Context context) {
super(context);
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test);
//缩放图片
Bitmap bmp = bitmap;
bmp = Bitmap.createScaledBitmap(bmp, bmp.getWidth() * FACTOR, bmp.getHeight() * FACTOR, true);
//切出矩形区域
drawable = new ShapeDrawable(new OvalShape());
BitmapShader shader = new BitmapShader(bmp, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
drawable.getPaint().setShader(shader);
drawable.setBounds(0, 0, RADIUS * 2, RADIUS * 2);
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(bitmap, 0, 0, null);
drawable.draw(canvas);
} @Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
//控制手指移动
localM.setTranslate(RADIUS - x * FACTOR, RADIUS - y * FACTOR);
drawable.getPaint().getShader().setLocalMatrix(localM);
drawable.setBounds(x - RADIUS, y - RADIUS, x + RADIUS, y + RADIUS);
invalidate();
return true;
}
}

调用的时候直接设置这个View

public class ZoomImageActivity extends AppCompatActivity {

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ZoomImageView zoomImageView = new ZoomImageView(this);
setContentView(zoomImageView);
// setContentView(R.layout.activity_zoom_image);
}
}

效果如下

高级UI-高级渲染的更多相关文章

  1. 高级UI晋升之View渲染机制(二)

    更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 优化性能一般从渲染,运算与内存,电量三个方面进行,今天开始说聊一聊Android ...

  2. firefox 扩展开发笔记(三):高级ui交互编程

    firefox 扩展开发笔记(三):高级ui交互编程 前言 前两篇链接 1:firefox 扩展开发笔记(一):jpm 使用实践以及调试 2:firefox 扩展开发笔记(二):进阶开发之移动设备模拟 ...

  3. Android 高级UI设计笔记07:RecyclerView 的详解

    1. 使用RecyclerView       在 Android 应用程序中列表是一个非常重要的控件,适用场合非常多,如新闻列表.应用列表.消息列表等等,但是从Android 一出生到现在并没有非常 ...

  4. 【Unity Shader】(九) ------ 高级纹理之渲染纹理及镜子与玻璃效果的实现

    笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题. [Unity Shader](三) ----- ...

  5. UI高级组件

    今天继续学习UI高级组件 网格视图 GridView 用GridView标签添加,显示网格视图,需要用到适配器,共有四种适配器 ArrayAdapter,SmipleAdapter,SmipleCou ...

  6. [Android]使用AdapterTypeRender对不同类型的item数据到UI的渲染

    以下内容为原创,转载请注明: 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/3992843.html 本文讲的工具均放在AndroidBucket开源 ...

  7. 使用AdapterTypeRender对不同类型的item数据到UI的渲染

    要实现聊天功能中的发送不同类型的信息,比如纯文本.图片.语音.图文混排多媒体的数据等(具体效果看微信). 这里使用AdapterTypeRender在BaseTypeAdapter(这个之后会讲到)中 ...

  8. 右键计算机->属性->高级系统设置->高级->环境变量,添加环境变量(推荐)

    (1)右键计算机->属性->高级系统设置->高级->环境变量,添加环境变量(推荐) QTDIR:D:\Software\Qt\Qt5.2.0\5.2.0\msvc2010_op ...

  9. iOS开发——高级UI&带你玩转UITableView

    带你玩装UITableView 在实际iOS开发中UITableView是使用最多,也是最重要的一个控件,如果你不会用它,那别说什么大神了,菜鸟都不如. 其实关于UItableView事非常简单的,实 ...

  10. 高级UI晋升之自定义View实战(六)

    更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680本篇文章将从Android 自定义属性动画&Camera动画来介绍自定义V ...

随机推荐

  1. *P3694 邦邦的大合唱站队[dp]

    题目描述 N个偶像排成一列,他们来自M个不同的乐队.每个团队至少有一个偶像. 现在要求重新安排队列,使来自同一乐队的偶像连续的站在一起.重新安排的办法是,让若干偶像出列(剩下的偶像不动),然后让出列的 ...

  2. HttpContext对象下的属性Application、Cache、Request、Response、Server、Session、User

    概述: HttpContext封装关于单个HTTP请求的所有HTTP特定信息. HttpContext基于HttpApplication的处理管道,由于HttpContext对象贯穿整个处理过程,所以 ...

  3. msdtc不可用

    在使用“经销商园地 网上订单处理程序”等程序时,如果程序报:服务器×××上的MSDTC不可用”,可以按照以下方法进行解决: 在windows控制面版-->管理工具-->服务-->Di ...

  4. OLED液晶屏幕(4)串口读取文字并分割,液晶屏幕显示

    ESP8266-07 0.93存 液晶屏 128*64  驱动芯片 ssd1306 接线 VCC-5v GND-GND SCL-D1(SCL) SDA-D2(SDA) 安装两个库 #include & ...

  5. MongoDB TTL集合与固定集合

    1.固定集合     MongoDB可以创建固定长度的集合,可以设置最大的集合空间或最大的集合数.创建集合的语法如下:     db.createCollection("collection ...

  6. B/S结构与C/S结构测试区别

    B/S结构与C/S结构 B/S结构是浏览器/服务器结构,应用软件的业务逻辑完全在服务器端实现,客户端只需要通过浏览器完成浏览.查询.输入等简单操作. C/S结构是客户端/浏览器结构,客户端具有一定的数 ...

  7. 不用VS调试.Net

    将来,任何开发人员都将需要调试应用程序,并且将无法访问Visual Studio,在某些情况下甚至无法访问源代码.例如,在生产web或应用服务器上调试问题时,我真的不想安装Visual Studio并 ...

  8. leetcode 一些算法题及答案

    1. 两数之和 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这 ...

  9. 一天一经典Efficient Estimation of Word Representations in Vector Space

    摘要 本文提出了两种从大规模数据集中计算连续向量表示(Continuous Vector Representation)的计算模型架构.这些表示的有效性是通过词相似度任务(Word Similarit ...

  10. D3.js的v5版本入门教程(第十章)

    在这一章我们干点有趣的事——让我们上一章绘制的图表动起来,这样岂不是很有意思 为了让图表动起来,我们还是需要以下新的知识点 .attr(xxx) .transition() .attr(xxx),tr ...