android 下拉窗帘,Android 窗帘(Curtain)效果二之波浪式动态扭曲效果
上一篇文章已經(jīng)實(shí)現(xiàn)了如何把一張圖片扭曲成波浪效果,那么這一篇文章我們介紹如何動態(tài)調(diào)整系數(shù),去改變波浪圖片的皺褶成度。我們自一次觀察下圖morning routine的效果:
仔細(xì)觀察我們發(fā)現(xiàn),當(dāng)往右滑動時(shí),頭部的溝壑(也就是正弦曲線)是從0遞增到最大的;如果具體到一條水平像素直線的話,這其實(shí)就是一條直線扭曲成正弦曲線的一個過程。直線如何扭曲成正弦曲線、正弦曲線如何恢復(fù)成直線其實(shí)就是系數(shù)WAVE_HEIGHT(波峰波谷距離)從0~MAX_WAVE_HEIGHT、MAX_WAVE_HEIGHT~0的動態(tài)變化過程,因此我們只要在前一篇文章正弦曲線的公式代碼加入滑動的滑動百分比progress(1>=progress>=0)就可以了:
float yOffset = WAVE_HEIGHT / 2 * progress + WAVE_HEIGHT / 2 * progress * (float) Math.sin((float) j / WIDTH * 5 * Math.PI + k);
上面已經(jīng)介紹了動態(tài)滑動扭曲時(shí)如何計(jì)算每條水平直線上每個像素的y軸偏移量,但是根據(jù)上圖效果其實(shí)每個像素的x坐標(biāo)也是變化的;折疊菜單的最左邊的像素點(diǎn)x坐標(biāo)等于菜單向左滑動的距離,折疊菜單的最右邊的像素點(diǎn)x坐標(biāo)緊緊的擠壓邊緣不移動,所以當(dāng)滑動時(shí)每個像素的x坐標(biāo)是偏移量是從左往右衰減成0的,由此我們可以推導(dǎo)出滑動時(shí)計(jì)算的每個像素x坐標(biāo)的公式:
//bitmapwidth 原圖寬度
//origsX 原圖時(shí)像素的X坐標(biāo)
//progress當(dāng)前滑動百分比
//xPostion 像素的新x坐標(biāo)
//這個公式計(jì)算出的xPostion 越往右跟origsX 的差距越小,最后一像素差距為0
float xPostion = origsX + (bitmapwidth - origsX ) * progress;
原理我們已經(jīng)理解的差不多了,那么最終的效果如下圖:
全部代碼如下:
public class CurtainView extends View {
private Bitmap mbitmap;
private static int WIDTH = 30;
private static int HEIGHT = 30;
//最大水平的波形高度
private float WAVE_HEIGHT = 50;
//小格相交的總的點(diǎn)數(shù)
private int COUNT = (WIDTH + 1) * (HEIGHT + 1);
private float[] verts = new float[COUNT * 2];
private float[] origs = new float[COUNT * 2];
private float k;
private float progress;
public CurtainView(Context context) {
super(context);
init();
}
public CurtainView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public CurtainView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public void setProgress(float progress){
this.progress = progress;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < HEIGHT + 1; i++) {
for (int j = 0; j < WIDTH + 1; j++) {
//把每一個水平像素通過正弦公式轉(zhuǎn)換成正弦曲線
//WAVE_HEIGHT表示波峰跟波低的垂直距離,皺褶后會王桑超過水平線,所以往下偏移WAVE_HEIGHT / 2
//5表示波浪的密集度,表示波峰波谷總共有五個,對應(yīng)上面左圖的1,2,3,4,5
//j就是水平像的X軸坐標(biāo)
//K決定正弦曲線起始點(diǎn)(x=0)點(diǎn)的Y坐標(biāo),k=0就是從波峰波谷的中間開始左->右繪制曲線
float yOffset = WAVE_HEIGHT / 2 * progress + WAVE_HEIGHT / 2 * progress * (float) Math.sin((float) j / WIDTH * 5 * Math.PI + k);
//每個像素扭曲后的x坐標(biāo)
//origs[(i*(WIDTH+1)+j)*2+0] 原圖x坐標(biāo)
verts[(i * (WIDTH + 1) + j) * 2 + 0] = origs[(i*(WIDTH+1)+j)*2+0] + (bitmapwidth - origs[(i*(WIDTH+1)+j)*2+0]) * progress;
//每個像素扭曲后的Y坐標(biāo)
//origs[(i*(WIDTH+1)+j)*2+1] 原圖y坐標(biāo)
verts[(i * (WIDTH + 1) + j) * 2 + 1] = origs[(i * (WIDTH + 1) + j) * 2 + 1] + yOffset;//
}
}
canvas.drawBitmapMesh(mbitmap, WIDTH, HEIGHT, verts, 0, null, 0, null);
}
int bitmapwidth;
int bitmapheight;
public void init() {
mbitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.timg);
bitmapwidth = mbitmap.getWidth();
bitmapheight = mbitmap.getHeight();
COUNT = (WIDTH + 1) * (HEIGHT + 1);
verts = new float[COUNT * 2];
origs = new float[COUNT * 2];
int index = 0;
for (int i = 0; i < HEIGHT + 1; i++) {
float fy = bitmapheight / (float) HEIGHT * i;
for (int j = 0; j < WIDTH + 1; j++) {
float fx = bitmapwidth / (float) WIDTH * j;
//偶數(shù)位記錄x坐標(biāo) 奇數(shù)位記錄Y坐標(biāo)
origs[index * 2 + 0] = verts[index * 2 + 0] = fx;
origs[index * 2 + 1] = verts[index * 2 + 1] = fy;
index++;
}
}
}
}
Android 窗簾(Curtain)效果三之波浪式扭曲效果優(yōu)化提升
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的android 下拉窗帘,Android 窗帘(Curtain)效果二之波浪式动态扭曲效果的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android 8 esp8266,ES
- 下一篇: 华为最新系统鸿蒙的意思,EMUI官微正式