欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android仿新浪微博首页加号弹出菜单效果

程序员文章站 2023-11-01 08:55:52
android仿新浪微博首页加号弹出菜单效果,最近公司项目需求要做一个类似微博的弹出动画,参照网上的资料和自己的修改实现了效果。 先上图: 一、实现思路: 1、截取当前窗口,对图片做高斯模糊处理,...

android仿新浪微博首页加号弹出菜单效果,最近公司项目需求要做一个类似微博的弹出动画,参照网上的资料和自己的修改实现了效果。

先上图:
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;
          }
      }