高级UI-高级渲染
在使用了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-高级渲染的更多相关文章
- 高级UI晋升之View渲染机制(二)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 优化性能一般从渲染,运算与内存,电量三个方面进行,今天开始说聊一聊Android ...
- firefox 扩展开发笔记(三):高级ui交互编程
firefox 扩展开发笔记(三):高级ui交互编程 前言 前两篇链接 1:firefox 扩展开发笔记(一):jpm 使用实践以及调试 2:firefox 扩展开发笔记(二):进阶开发之移动设备模拟 ...
- Android 高级UI设计笔记07:RecyclerView 的详解
1. 使用RecyclerView 在 Android 应用程序中列表是一个非常重要的控件,适用场合非常多,如新闻列表.应用列表.消息列表等等,但是从Android 一出生到现在并没有非常 ...
- 【Unity Shader】(九) ------ 高级纹理之渲染纹理及镜子与玻璃效果的实现
笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题. [Unity Shader](三) ----- ...
- UI高级组件
今天继续学习UI高级组件 网格视图 GridView 用GridView标签添加,显示网格视图,需要用到适配器,共有四种适配器 ArrayAdapter,SmipleAdapter,SmipleCou ...
- [Android]使用AdapterTypeRender对不同类型的item数据到UI的渲染
以下内容为原创,转载请注明: 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/3992843.html 本文讲的工具均放在AndroidBucket开源 ...
- 使用AdapterTypeRender对不同类型的item数据到UI的渲染
要实现聊天功能中的发送不同类型的信息,比如纯文本.图片.语音.图文混排多媒体的数据等(具体效果看微信). 这里使用AdapterTypeRender在BaseTypeAdapter(这个之后会讲到)中 ...
- 右键计算机->属性->高级系统设置->高级->环境变量,添加环境变量(推荐)
(1)右键计算机->属性->高级系统设置->高级->环境变量,添加环境变量(推荐) QTDIR:D:\Software\Qt\Qt5.2.0\5.2.0\msvc2010_op ...
- iOS开发——高级UI&带你玩转UITableView
带你玩装UITableView 在实际iOS开发中UITableView是使用最多,也是最重要的一个控件,如果你不会用它,那别说什么大神了,菜鸟都不如. 其实关于UItableView事非常简单的,实 ...
- 高级UI晋升之自定义View实战(六)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680本篇文章将从Android 自定义属性动画&Camera动画来介绍自定义V ...
随机推荐
- 《BUG创造队》第三次作业:团队项目原型设计与开发
项目 内容 这个作业属于哪个课程 2016级软件工程 这个作业的要求在哪里 实验六 团队作业3:团队项目原型设计与开发 团队名称 BUG创造队 作业学习目标 ①掌握软件原型开发技术:②学会使用软件原型 ...
- tcp中设置连接超时
直接上代码: 设置连接超时 //首先改成非阻塞套接字 unsigned ; int rm=ioctl(sConnect,FIONBIO,(unsigned long*)&ul); ) { pr ...
- phantomJS+Python 隐形浏览器
phantomjs解压后,把文件夹bin中的phantomjs.exe移到python文件夹中的Scripts中 实例: from selenium import webdriver driver = ...
- c#的参数调用
c#的参数传递有三种方式:值传递,和c一样,引用传递,类似与c++,但形式不一样输出参数,这种方式可以返回多个值,这种有点像c中的指针传递,但其实不太一样.值传递不细说,c中已经很详细了引用传递实例如 ...
- 3.Vue 实例
创建一个 Vue 实例 每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的: var vm = new Vue({ // 选项 }) 虽然没有完全遵循 MVVM 模型,但是 V ...
- shell脚本 基础应用
变量分为普通变量可只读变量 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ...
- linux patch 简单学习
使用patch 我们可以方便的进行软件补丁包处理,以下演示一个简单的c 项目补丁处理 原代码 app.c #include <stdio.h> int main(){ printf(&qu ...
- C语言博客06-结构体
1.本章学习总结 1.1 学习内容总结 结构体如何定义.成员如何赋值 1.结构体的一般形式为: struct 结构体名 { 数据类型 成员名1: 数据类型 成员名2: : 数据类型 成员名n: }: ...
- PHP 之循环创建文件夹
/** * 循环创建文件夹 * @param string $dir 需要创建的文件夹路径 * @param integer $mode 文件夹权限 * @return bool 返回创建是否成功 * ...
- dedecms 模板文件不存在,无法解析文档的终极各种解决办法
dedecms 模板文件不存在,无法解析文档"的终极各种解决办法 方法一:[此对应喜欢把模板文件使用".html"的格式,] /include/arc.archives. ...