Android 仿Morning routine 窗帘打开界面
来源:互联网 发布:cydia网络错误 编辑:程序博客网 时间:2024/04/27 15:36
先想大家推荐一个app叫做Morning routine,是最美应用推荐的,非常好看的一款闹钟工具(可能根据个人喜好而不相同)。这一篇是实现的一个小功能,窗帘样式的View
按照国际惯例,代码如下
import android.annotation.SuppressLint;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.LinearGradient;import android.graphics.Paint;import android.graphics.Shader;import android.os.Build;import android.os.Handler;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.view.animation.AccelerateInterpolator;public class BitmapMeshView extends View { private Bitmap bitmap; private Bitmap shadowMask; private Paint paint; private Shader maskShader; private int maxAlpha = 0xFF; private int width, height;private int bitmapWidth = 30; private int bitmapHeight = 10; private int touchX; private int touchY;private boolean newApiFlag; private int delayOffsetX; private AccelerateInterpolator interpolator; private Handler handler = new Handler(); private Runnable delayRunnable = new Runnable() { @Override public void run() { delayOffsetX += (touchX - delayOffsetX) * 0.5F; handler.postDelayed(this, 20); invalidate(); } }; public BitmapMeshView(Context context) { this(context, null); } public BitmapMeshView(Context context, AttributeSet attrs) { this(context, attrs, 0); } @SuppressLint("NewApi") public BitmapMeshView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.snipper); paint = new Paint(Paint.ANTI_ALIAS_FLAG); handler.post(delayRunnable); newApiFlag = Build.VERSION.SDK_INT >= 18; interpolator = new AccelerateInterpolator(); if (!newApiFlag) { // 硬件加速不支持drawBitmapMesh的colors绘制的情况下,在原bitmap的上层覆盖一个半透明带阴影的bitmap以实现阴影功能 shadowMask = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); Canvas maskCanvas = new Canvas(shadowMask); float singleWave = bitmap.getWidth() / bitmapWidth * 6.28F; int blockPerWave = (int) (singleWave / (bitmap.getWidth() / bitmapWidth)); if (blockPerWave % 2 == 0) blockPerWave++; float offset = (float) ((bitmap.getWidth() / singleWave - Math.floor(bitmap.getWidth() / singleWave)) * singleWave); int[] colors = new int[blockPerWave]; float[] offsets = new float[blockPerWave]; Log.d("singleWave:" + singleWave, "blockPerWave:" + blockPerWave); float perOffset = 1.0F / blockPerWave; int halfWave = (int) Math.floor((float) blockPerWave / 2.0F); int perAlpha = maxAlpha / (halfWave - 1); for (int i = -halfWave; i < halfWave + 1; i++) { int ii = halfWave - Math.abs(i); int iii = i + halfWave; colors[iii] = (int) (perAlpha * Math.sin((float) ii / (float) blockPerWave * 3.14F)) << 24; offsets[iii] = perOffset * iii; Log.d("index:" + i, "colors:0x" + Integer.toHexString(colors[iii]) + ", offset:" + offsets[iii]); } maskShader = new LinearGradient(offset, 0, singleWave + offset, 0, colors, offsets, Shader.TileMode.REPEAT); paint.setShader(maskShader); maskCanvas.drawRect(0, 0, bitmap.getWidth(), bitmap.getHeight(), paint); paint.setShader(null); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = MeasureSpec.getSize(widthMeasureSpec); height = MeasureSpec.getSize(heightMeasureSpec); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: touchX = (int) event.getX(); touchY = (int) event.getY(); break; case MotionEvent.ACTION_MOVE: touchX = (int) event.getX(); touchY = (int) event.getY(); break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: break; } invalidate(); return true; } @Override public void onDraw(Canvas canvas) { float[] verts = new float[(bitmapWidth + 1) * (bitmapHeight + 1) * 2]; int[] colors = new int[(bitmapWidth + 1) * (bitmapHeight + 1)]; int index = 0; float ratio = (float) touchX / (float) width; int alpha = 0; for (int y = 0; y <= bitmapHeight; y++) { float fy = height / bitmapHeight * y; float longDisSide = touchY > height - touchY ? touchY : height - touchY; float longRatio = Math.abs(fy - touchY) / longDisSide; longRatio = interpolator.getInterpolation(longRatio); float realWidth = longRatio * (touchX - delayOffsetX); for (int x = 0; x <= bitmapWidth; x++) { verts[index * 2 + 0] = (width * ratio - (realWidth)) / bitmapWidth * x; float gap = 60.0F * (1.0F - ratio); float realHeight = height - ((float) Math.sin((x * 2) * 0.5F) * gap + gap); float offsetY = realHeight / bitmapHeight * y; verts[index * 2 + 1] = (height - realHeight) / 2 + offsetY; int px = (int) verts[index * 2 + 0]; int py = (int) verts[index * 2 + 1]; px = px < 0 ? 0 : px; py = py < 0 ? 0 : py; px = px > bitmap.getWidth() ? bitmap.getWidth() : px; py = py > bitmap.getHeight() ? bitmap.getHeight() : py; int color; int channel = 255 - (int) (height - realHeight) * 2; if (channel < 255) { alpha = (int) ((255 - channel) / 120.0F * maxAlpha) * 4; } if (newApiFlag) { channel = channel < 0 ? 0 : channel; channel = channel > 255 ? 255 : channel; color = 0xFF000000 | channel << 16 | channel << 8 | channel; colors[index] = color; } index += 1; } } canvas.drawBitmapMesh(bitmap, bitmapWidth, bitmapHeight, verts, 0, colors, 0, null); if (!newApiFlag) { alpha = alpha > 255 ? 255 : alpha; alpha = alpha < 0 ? 0 : alpha; paint.setAlpha(alpha); canvas.drawBitmapMesh(shadowMask, bitmapWidth, bitmapHeight, verts, 0, null, 0, paint); paint.setAlpha(255); } }}然后是布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.bitmapmesh.MainActivity" > <com.example.bitmapmesh.BitmapMeshView android:id="@+id/bitmapmesh" android:layout_width="match_parent" android:layout_height="match_parent" /></RelativeLayout>
import android.app.Activity;import android.os.Bundle;public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }}
OK 附上下载地址
http://download.csdn.net/detail/u010107250/8433023
0 0
- Android 仿Morning routine 窗帘打开界面
- Android 仿 窗帘效果 和 登录界面拖动效果 (Scroller类的应用)
- Android 仿 窗帘效果 和 登录界面拖动效果 (Scroller类的应用) 附 2个DEMO及源码
- Android 仿 窗帘效果 和 登录界面拖动效果 (Scroller类的应用) 附 2个DEMO及源码
- Android 仿 窗帘效果 和 登录界面拖动效果 (Scroller类的应用) 附 2个DEMO及源码
- Android 仿 窗帘效果 和 登录界面拖动效果 (Scroller类的应用) 附 2个DEMO及源码
- Android 仿 窗帘效果 和 登录界面拖动效果 (Scroller类的应用) 附 2个DEMO及源码
- Android 仿 窗帘效果 和 登录界面拖动效果 (Scroller类的应用) 附 2个DEMO及源码
- Android 仿 窗帘效果 和 登录界面拖动效果 (Scroller类的应用) 附 2个DEMO及源码
- Android 仿 窗帘效果 和 登录界面拖动效果 (Scroller类的应用) 附 2个DEMO及源码
- Android 仿 窗帘效果 和 登录界面拖动效果 (Scroller类的应用) 附 2个DEMO及源码
- Android 仿 窗帘效果 和 登录界面拖动效果 (Scroller类的应用) 附 2个DEMO及源码
- android-仿UC界面
- android仿淘宝界面
- android 仿QQ界面
- 窗帘
- android-仿QQ界面布局
- android仿新浪引导界面
- 115 藥圃 鄭琢
- 如何用EA生成代码并将生成的代码放在VS搭建好的框架中
- 图片滑动组件iSlider
- Sync Object in OpenGL (about GPU Fence)
- 在Windows 7上搭建 Ruby环境
- Android 仿Morning routine 窗帘打开界面
- python decorator心得体会
- Java泛型
- 116 栢谷 鄭崑壽
- 平行四边形的效果实现
- EF6.0 学习(一)
- hihoCoder:#1039 字符消除
- 关机充电如何实现短按pwrkey灭屏
- 欢迎使用CSDN-markdown编辑器