Android仿新浪微博首页加号弹出菜单效果
程序员文章站
2023-11-01 08:55:52
android仿新浪微博首页加号弹出菜单效果,最近公司项目需求要做一个类似微博的弹出动画,参照网上的资料和自己的修改实现了效果。
先上图:
一、实现思路:
1、截取当前窗口,对图片做高斯模糊处理,...
android仿新浪微博首页加号弹出菜单效果,最近公司项目需求要做一个类似微博的弹出动画,参照网上的资料和自己的修改实现了效果。
先上图:
一、实现思路:
1、截取当前窗口,对图片做高斯模糊处理,将处理后的图片做popupwindow的背景图片;
2、创建popupwindow,完成布局,view的移动范围是由父布局的大小决定的,就是只能在父布局的范围内移动;
3、给每个view添加进入动画,和退出动画,做延时;
4、为view的动画添加回弹插值器;
二、代码实现
弹出窗口代码:
package com.xp.weibopopupwindow; import android.animation.animator; import android.animation.animator.animatorlistener; import android.animation.objectanimator; import android.animation.valueanimator; import android.app.activity; import android.graphics.bitmap; import android.graphics.canvas; import android.graphics.paint; import android.graphics.rect; import android.graphics.drawable.bitmapdrawable; import android.os.handler; import android.util.displaymetrics; import android.util.log; import android.view.gravity; import android.view.layoutinflater; import android.view.view; import android.view.view.onclicklistener; import android.view.viewgroup; import android.widget.imageview; import android.widget.popupwindow; import android.widget.relativelayout; import android.widget.toast; public class morewindow extends popupwindow implements onclicklistener { private string tag = morewindow.class.getsimplename(); activity mcontext; private int mwidth; private int mheight; private int statusbarheight; private bitmap mbitmap = null; private bitmap overlay = null; private handler mhandler = new handler(); public morewindow(activity context) { mcontext = context; } public void init() { rect frame = new rect(); mcontext.getwindow().getdecorview().getwindowvisibledisplayframe(frame); statusbarheight = frame.top; displaymetrics metrics = new displaymetrics(); mcontext.getwindowmanager().getdefaultdisplay() .getmetrics(metrics); mwidth = metrics.widthpixels; mheight = metrics.heightpixels; setwidth(mwidth); setheight(mheight); } private bitmap blur() { if (null != overlay) { return overlay; } long startms = system.currenttimemillis(); view view = mcontext.getwindow().getdecorview(); view.setdrawingcacheenabled(true); view.builddrawingcache(true); mbitmap = view.getdrawingcache(); float scalefactor = 8;//图片缩放比例 float radius = 10;//模糊程度 int width = mbitmap.getwidth(); int height = mbitmap.getheight(); overlay = bitmap.createbitmap((int) (width / scalefactor), (int) (height / scalefactor), bitmap.config.argb_8888); canvas canvas = new canvas(overlay); canvas.scale(1 / scalefactor, 1 / scalefactor); paint paint = new paint(); paint.setflags(paint.filter_bitmap_flag); canvas.drawbitmap(mbitmap, 0, 0, paint); overlay = fastblur.doblur(overlay, (int) radius, true); log.i(tag, "blur time is:" + (system.currenttimemillis() - startms)); return overlay; } public void showmorewindow(view view) { final relativelayout layout = (relativelayout) layoutinflater.from(mcontext).inflate(r.layout.pop_more_window, null); setcontentview(layout); imageview imgclose = layout.findviewbyid(r.id.img_close); imgclose.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { if (isshowing()) { closeanimation(layout); } } }); showanimation(layout); setbackgrounddrawable(new bitmapdrawable(mcontext.getresources(), blur())); setoutsidetouchable(true); setfocusable(true); showatlocation(view, gravity.bottom, 0, statusbarheight); } private void showanimation(viewgroup layout) { for (int i = 0; i < layout.getchildcount(); i++) { final view child = layout.getchildat(i); if (child.getid() == r.id.img_close) { continue; } child.setonclicklistener(this); child.setvisibility(view.invisible); mhandler.postdelayed(new runnable() { @override public void run() { child.setvisibility(view.visible); valueanimator fadeanim = objectanimator.offloat(child, "translationy", 600, 0); fadeanim.setduration(300); kickbackanimator kickanimator = new kickbackanimator(); kickanimator.setduration(150); fadeanim.setevaluator(kickanimator); fadeanim.start(); } }, i * 50); } } private void closeanimation(viewgroup layout) { for (int i = 0; i < layout.getchildcount(); i++) { final view child = layout.getchildat(i); if (child.getid() == r.id.img_close) { continue; } child.setonclicklistener(this); mhandler.postdelayed(new runnable() { @override public void run() { child.setvisibility(view.visible); valueanimator fadeanim = objectanimator.offloat(child, "translationy", 0, 600); fadeanim.setduration(200); kickbackanimator kickanimator = new kickbackanimator(); kickanimator.setduration(100); fadeanim.setevaluator(kickanimator); fadeanim.start(); fadeanim.addlistener(new animatorlistener() { @override public void onanimationstart(animator animation) { // todo auto-generated method stub } @override public void onanimationrepeat(animator animation) { // todo auto-generated method stub } @override public void onanimationend(animator animation) { child.setvisibility(view.invisible); } @override public void onanimationcancel(animator animation) { // todo auto-generated method stub } }); } }, (layout.getchildcount() - i - 1) * 30); if (child.getid() == r.id.tv_text) { mhandler.postdelayed(new runnable() { @override public void run() { dismiss(); } }, (layout.getchildcount() - i) * 30 + 80); } } } @override public void onclick(view v) { switch (v.getid()) { case r.id.tv_text: toast.maketext(mcontext,"点击了文字",toast.length_short).show(); break; case r.id.tv_lbs: toast.maketext(mcontext,"点击了签到",toast.length_short).show(); break; case r.id.tv_photo: toast.maketext(mcontext,"点击了相册",toast.length_short).show(); break; case r.id.tv_camera: toast.maketext(mcontext,"点击了拍摄",toast.length_short).show(); break; case r.id.tv_more: toast.maketext(mcontext,"点击了更多",toast.length_short).show(); break; case r.id.tv_review: toast.maketext(mcontext,"点击了点评",toast.length_short).show(); break; default: break; } } public void destroy() { if (null != overlay) { overlay.recycle(); overlay = null; system.gc(); } if (null != mbitmap) { mbitmap.recycle(); mbitmap = null; system.gc(); } } }
-
高斯模糊码:
package com.xp.weibopopupwindow; import android.graphics.bitmap; public class fastblur { public static bitmap doblur(bitmap sentbitmap, int radius, boolean canreuseinbitmap) { bitmap bitmap; if (canreuseinbitmap) { bitmap = sentbitmap; } else { bitmap = sentbitmap.copy(sentbitmap.getconfig(), true); } if (radius < 1) { return (null); } int w = bitmap.getwidth(); int h = bitmap.getheight(); int[] pix = new int[w * h]; bitmap.getpixels(pix, 0, w, 0, 0, w, h); int wm = w - 1; int hm = h - 1; int wh = w * h; int p = radius + radius + 1; int r[] = new int[wh]; int g[] = new int[wh]; int b[] = new int[wh]; int rsum, gsum, bsum, x, y, i, p, yp, yi, yw; int vmin[] = new int[math.max(w, h)]; int psum = (p + 1) >> 1; psum *= psum; int dv[] = new int[256 * psum]; for (i = 0; i < 256 * psum; i++) { dv[i] = (i / psum); } yw = yi = 0; int[][] stack = new int[p][3]; int stackpointer; int stackstart; int[] sir; int rbs; int r1 = radius + 1; int routsum, goutsum, boutsum; int rinsum, ginsum, binsum; for (y = 0; y < h; y++) { rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; for (i = -radius; i <= radius; i++) { p = pix[yi + math.min(wm, math.max(i, 0))]; sir = stack[i + radius]; sir[0] = (p & 0xff0000) >> 16; sir[1] = (p & 0x00ff00) >> 8; sir[2] = (p & 0x0000ff); rbs = r1 - math.abs(i); rsum += sir[0] * rbs; gsum += sir[1] * rbs; bsum += sir[2] * rbs; if (i > 0) { rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; } else { routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; } } stackpointer = radius; for (x = 0; x < w; x++) { r[yi] = dv[rsum]; g[yi] = dv[gsum]; b[yi] = dv[bsum]; rsum -= routsum; gsum -= goutsum; bsum -= boutsum; stackstart = stackpointer - radius + p; sir = stack[stackstart % p]; routsum -= sir[0]; goutsum -= sir[1]; boutsum -= sir[2]; if (y == 0) { vmin[x] = math.min(x + radius + 1, wm); } p = pix[yw + vmin[x]]; sir[0] = (p & 0xff0000) >> 16; sir[1] = (p & 0x00ff00) >> 8; sir[2] = (p & 0x0000ff); rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; rsum += rinsum; gsum += ginsum; bsum += binsum; stackpointer = (stackpointer + 1) % p; sir = stack[(stackpointer) % p]; routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; rinsum -= sir[0]; ginsum -= sir[1]; binsum -= sir[2]; yi++; } yw += w; } for (x = 0; x < w; x++) { rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; yp = -radius * w; for (i = -radius; i <= radius; i++) { yi = math.max(0, yp) + x; sir = stack[i + radius]; sir[0] = r[yi]; sir[1] = g[yi]; sir[2] = b[yi]; rbs = r1 - math.abs(i); rsum += r[yi] * rbs; gsum += g[yi] * rbs; bsum += b[yi] * rbs; if (i > 0) { rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; } else { routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; } if (i < hm) { yp += w; } } yi = x; stackpointer = radius; for (y = 0; y < h; y++) { // preserve alpha channel: ( 0xff000000 & pix[yi] ) pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum]; rsum -= routsum; gsum -= goutsum; bsum -= boutsum; stackstart = stackpointer - radius + p; sir = stack[stackstart % p]; routsum -= sir[0]; goutsum -= sir[1]; boutsum -= sir[2]; if (x == 0) { vmin[y] = math.min(y + r1, hm) * w; } p = x + vmin[y]; sir[0] = r[p]; sir[1] = g[p]; sir[2] = b[p]; rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; rsum += rinsum; gsum += ginsum; bsum += binsum; stackpointer = (stackpointer + 1) % p; sir = stack[stackpointer]; routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; rinsum -= sir[0]; ginsum -= sir[1]; binsum -= sir[2]; yi += w; } } bitmap.setpixels(pix, 0, w, 0, 0, w, h); return (bitmap); } }
-
回弹效果:
package com.xp.weibopopupwindow; import android.animation.typeevaluator; public class kickbackanimator implements typeevaluator { private final float s = 1.70158f; float mduration = 0f; public void setduration(float duration) { mduration = duration; } public float evaluate(float fraction, float startvalue, float endvalue) { float t = mduration * fraction; float b = startvalue.floatvalue(); float c = endvalue.floatvalue() - startvalue.floatvalue(); float d = mduration; float result = calculate(t, b, c, d); return result; } public float calculate(float t, float b, float c, float d) { return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; } }
-