上下扫描以及扩散扫描
来源:互联网 发布:柳州市一职校淘宝地址 编辑:程序博客网 时间:2024/06/05 17:14
效果图
思路
显示图片,所以继承ImageView。
图片有两种状态:一种是正常状态,一种是有较暗状态。较暗状态是将按一定的透明度比例绘制正常的图片即可。
代码
public class DakaImageView extends ImageView { /** * 从上往下刷新 */ private static final int ANIM_UP_DOWN = 1; /** * 波纹扩散 */ private static final int ANIM_SPREAD = 2; /** * 没有动画执行 */ private static final int ANIM_NO = 3; private static final String TAG = DakaImageView.class.getSimpleName(); private int mCurrAnim = ANIM_NO; private ValueAnimator mUpdownAnim, mSpreadAnim; private Paint mUpdownPaint; private float mMaskOffsetY = 0, mMaskoffsetRadius = 0; private Bitmap mUpdownMaskBitmap, mSpreadMaskBitmap, mUnmaskBitmap; private static final float ALPHA = 0.3f; private Path path; public DakaImageView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { setLayerType(LAYER_TYPE_SOFTWARE, null); mUpdownPaint = new Paint(); mUpdownPaint.setAntiAlias(true); mUpdownPaint.setStyle(Paint.Style.FILL); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //设置死宽高 super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = MeasureSpec.makeMeasureSpec(getDrawable().getIntrinsicWidth(),MeasureSpec.EXACTLY); int height = MeasureSpec.makeMeasureSpec(getDrawable().getIntrinsicHeight(),MeasureSpec.EXACTLY); setMeasuredDimension(width,height); } @Override protected void onDetachedFromWindow() { //回收相应的资源文件 super.onDetachedFromWindow(); stopAndRecyclerAnim(mUpdownAnim); stopAndRecyclerAnim(mSpreadAnim); recyclerBitmap(mUpdownMaskBitmap); recyclerBitmap(mUnmaskBitmap); recyclerBitmap(mSpreadMaskBitmap); mUpdownPaint = null; } private void recyclerBitmap(Bitmap bitmap) { if (bitmap != null && !bitmap.isRecycled()) { bitmap.recycle(); } bitmap = null; } private void stopAndRecyclerAnim(ValueAnimator animator) { if (animator != null && animator.isRunning()) { animator.cancel(); } animator = null; if(mSpreadAnim == null && mUpdownAnim == null){//两个动画都停止后,恢复成正常状态 mCurrAnim = ANIM_NO; invalidate(); } } @Override protected void onDraw(Canvas canvas) { switch (mCurrAnim) { case ANIM_NO: drawUnmask(canvas); break; case ANIM_UP_DOWN: drawUpDown(canvas); break; case ANIM_SPREAD: drawSpread(canvas); break; } } private void drawUnmask(Canvas canvas) { Bitmap bitmap = getUnmaskBitmap(); canvas.drawBitmap(bitmap, 0, 0, null); recyclerBitmap(mUpdownMaskBitmap); recyclerBitmap(mSpreadMaskBitmap); } private void drawUpDown(Canvas canvas) { //绘制底图 Bitmap unmaskBitmap = getUnmaskBitmap(); canvas.drawBitmap(unmaskBitmap, 0, 0, null); //绘制阴影部分 Bitmap maskBitmap = getUpdownMaskBitmap(); mUpdownPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); int top = mMaskOffsetY - getHeight() < 0 ? 0 : (int) mMaskOffsetY - getHeight(); canvas.drawBitmap(maskBitmap, new Rect(0, top, unmaskBitmap.getWidth(), (int) mMaskOffsetY), new Rect(0, top, getWidth(), (int) mMaskOffsetY), mUpdownPaint); mUpdownPaint.setXfermode(null); } /** * 绘制水波纹 */ private void drawSpread(Canvas canvas) { //绘制水波纹 Bitmap maskBitmap = getSpreadMaskBitmap(); canvas.drawBitmap(maskBitmap, 0, 0, null); } private Bitmap getUnmaskBitmap() { //获取正常情况下的bitmap if (mUnmaskBitmap != null) return mUnmaskBitmap; int width = getWidth(); int height = getHeight(); mUnmaskBitmap = createBitmapAndGcIfNecessary(width, height); Canvas canvas = new Canvas(mUnmaskBitmap); Drawable drawable = getDrawable(); drawable.setAlpha(255); //正常情况下,不透明。用drawable绘制到自己指定的canvas上,就会将drawable转换成bitmap drawable.draw(canvas); return mUnmaskBitmap; } private Bitmap getUpdownMaskBitmap() { int width = getWidth(); int height = getHeight(); if (mUpdownMaskBitmap == null) mUpdownMaskBitmap = createBitmapAndGcIfNecessary(width, height); Canvas canvas = new Canvas(mUpdownMaskBitmap); canvas.drawColor(0, PorterDuff.Mode.CLEAR); canvas.clipRect(0, 0, width, mMaskOffsetY); //截取一部分区域,这样在绘制半透明的区域时就会只绘制截取到的部分 Drawable drawable = getDrawable(); drawable.setAlpha((int) (255 * ALPHA)); drawable.draw(canvas); return mUpdownMaskBitmap; } private Bitmap getSpreadMaskBitmap() { int width = getWidth(); int height = getHeight(); if (mSpreadMaskBitmap == null) { mSpreadMaskBitmap = createBitmapAndGcIfNecessary(width, height); } Canvas canvas = new Canvas(mSpreadMaskBitmap); canvas.drawColor(0, PorterDuff.Mode.CLEAR); //画原来未变暗的图 Drawable drawable = getDrawable(); drawable.setAlpha(255); drawable.draw(canvas); int max = Math.max(getWidth(), getHeight()) / 2; if(path == null) { path = new Path(); }else{ path.reset(); } if (mMaskoffsetRadius < max) { //从内往外扩散的是半透明的 path.addCircle(getWidth() / 2, getHeight() / 2, mMaskoffsetRadius, Path.Direction.CCW); canvas.clipPath(path); //截取一个圆环,然后用drawable绘制,这样绘制的drawable就是一个半透明的的圆环了。 canvas.drawColor(0, PorterDuff.Mode.CLEAR); drawable.setAlpha((int) (255 * ALPHA)); drawable.draw(canvas); } else {//从内往外扩散的是不透明的 //外圈阴影 。首先绘制外圈半透明的 path.reset(); path.addCircle(getWidth() / 2, getHeight() / 2, max, Path.Direction.CCW); canvas.clipPath(path); canvas.drawColor(0, PorterDuff.Mode.CLEAR); drawable.setAlpha((int) (255 * ALPHA)); drawable.draw(canvas); //内圈正常 path.reset(); path.addCircle(getWidth() / 2, getHeight() / 2, mMaskoffsetRadius - max, Path.Direction.CCW); canvas.clipPath(path); canvas.drawColor(0, PorterDuff.Mode.CLEAR); drawable.setAlpha(255); drawable.draw(canvas); } return mSpreadMaskBitmap; } private Bitmap createBitmapAndGcIfNecessary(int width, int height) { try { return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); } catch (OutOfMemoryError e) { System.gc(); return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); } } //----------------------------------------提供出去的方法--------------------------------- public void startUpDown() { mCurrAnim = ANIM_UP_DOWN; stopAndRecyclerAnim(mSpreadAnim); mUpdownAnim = ValueAnimator.ofInt(0, getHeight() * 2); mUpdownAnim.setDuration(2000); mUpdownAnim.setRepeatCount(ValueAnimator.INFINITE); mUpdownAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { mMaskOffsetY = (int) valueAnimator.getAnimatedValue(); invalidate(); } }); mUpdownAnim.start(); } public void stopUpDown() { if (null != mUpdownAnim) stopAndRecyclerAnim(mUpdownAnim); } public void startSpread() { stopAndRecyclerAnim(mUpdownAnim); mCurrAnim = ANIM_SPREAD; int radius = Math.max(getWidth(), getHeight()) / 2; mSpreadAnim = ValueAnimator.ofInt(0, radius * 2); mSpreadAnim.setDuration(1000); mSpreadAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { mMaskoffsetRadius = (int) valueAnimator.getAnimatedValue(); invalidate(); } }); mSpreadAnim.setRepeatCount(2); mSpreadAnim.start(); } public boolean isAnimming() { return mCurrAnim == ANIM_SPREAD || mCurrAnim == ANIM_UP_DOWN; }}
0 0
- 上下扫描以及扩散扫描
- iOS 自定义雷达 扫描/扩散动画 View
- 扫描
- 扫描
- 二维码的扫描以及生成
- 自定义二维码以及扫描二维码
- Android 扫描SDCard上的音乐文件以及监听扫描事件
- Android 扫描SDCard上的音乐文件以及监听扫描事件
- TCP扫描和UDP扫描以及它们的区别
- Android 扫描SDCard上的音乐文件以及监听扫描事件
- Android 扫描SDCard上的音乐文件以及监听扫描事件
- iOS原生二维码生成与扫描以及条形码的扫描
- iOS 二维码扫描-中间透明区域以及扫描区域设置
- HTML5利用Canvas模拟上下扫描动画实现
- iOS生成二维码,以及二维码扫描
- ios 原生二维码扫描以及需要注意事项
- 扫描台操作以及集合框架
- ios最简洁二维码扫描以及跳转
- 易飞8无销售报价的BOM成本参考
- redis -- 事务
- DOM操作 如何添加、移除、移动、复制、创建和查找节点等
- 简单-自定义ViewGroup实现标签云
- (4.2.37)Android 沉浸式状态栏的三种实现方式
- 上下扫描以及扩散扫描
- 截图分享
- ECharts画动态仪表盘+柱状图(ajax获取+循环画图)
- @Temporal
- MY FIRST CSDN DAY
- 第七周项目1-建立顺序环形队列算法库
- 虚拟机怎么设置u盘启动
- thinkphp连接多数据库 数据库切换
- iOS NSEnumerator的用法