高级UI-高级渲染
在使用了Panit畫筆之后,可以對其進行渲染,從而達到更加人性化的方式
渲染分類
按常用渲染方式可以分為以下幾種:
- BimapShader位圖的圖像渲染器
- LinearGradient線性渲染
- RadialGradient環形渲染:水波紋效果,充電水波紋擴散效果、調色板
- SweepGradient梯度渲染(掃描渲染):微信等雷達掃描效果,手機衛士垃圾掃描
- ComposeShader組合渲染
BimapShader
首先來研究下BimapShader是怎么使用的
一般來說繪制位圖使用這種方式
這樣就直接將位圖繪制在界面上,那么使用以后,可以設置三種系統模式,設置完以后畫筆添加Shader,然后就可以使用位圖渲染器了
這樣的設置運用于圖片寬高小于給定的寬高的處理方式
其常用的場景其中一個就是繪制用戶圓形頭像,其中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
其效果就是畫出一條漸變色的彩帶,和調色板類似
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);}@Overrideprotected 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();}@Overrideprotected 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.LinearGradientTextViewandroid: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);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawBitmap(bitmap, 0, 0, null);drawable.draw(canvas);}@Overridepublic 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 {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);ZoomImageView zoomImageView = new ZoomImageView(this);setContentView(zoomImageView); // setContentView(R.layout.activity_zoom_image);} }效果如下
轉載于:https://www.cnblogs.com/cj5785/p/10664583.html
總結
- 上一篇: 带拦截器配置的 struts.xml文件
- 下一篇: 2018-2019-2 20165114