Android仿微博菜单弹出效果


先上效果图,这个截图不是很流畅,大家可以下载apk试一下。 

 

说一下实现思路: 
1、截取当前窗口,对图片做高斯模糊处理,将处理后的图片做popupwindow的背景图片; 
2、创建popupwindow,完成布局,这儿要注意:View的移动范围是由parent的大小决定的,就是只能在parent的范围内移动; 
3、给买个View添加进入动画,每个比前一个延期50ms播放动画,关闭窗口时相反; 
4、为View的动画添加回弹插值器; 

关于动画说明参考:http://gqdy365.iteye.com/blog/2194297 
关于截屏并高斯模糊参考:http://gqdy365.iteye.com/blog/2193913 

MoreWindow.java窗口 
Java代码   收藏代码
  1. package com.jerome.weibo;  
  2.   
  3. import android.animation.Animator;  
  4. import android.animation.Animator.AnimatorListener;  
  5. import android.animation.ObjectAnimator;  
  6. import android.animation.ValueAnimator;  
  7. import android.app.Activity;  
  8. import android.graphics.Bitmap;  
  9. import android.graphics.Canvas;  
  10. import android.graphics.Paint;  
  11. import android.graphics.Rect;  
  12. import android.graphics.drawable.BitmapDrawable;  
  13. import android.os.Handler;  
  14. import android.util.DisplayMetrics;  
  15. import android.util.Log;  
  16. import android.view.Gravity;  
  17. import android.view.LayoutInflater;  
  18. import android.view.View;  
  19. import android.view.View.OnClickListener;  
  20. import android.view.ViewGroup;  
  21. import android.view.animation.Animation;  
  22. import android.view.animation.Animation.AnimationListener;  
  23. import android.view.animation.AnimationSet;  
  24. import android.view.animation.TranslateAnimation;  
  25. import android.widget.ImageView;  
  26. import android.widget.PopupWindow;  
  27. import android.widget.RelativeLayout;  
  28. import android.widget.RelativeLayout.LayoutParams;  
  29.   
  30. public class MoreWindow extends PopupWindow implements OnClickListener{  
  31.   
  32.     private String TAG = MoreWindow.class.getSimpleName();  
  33.     Activity mContext;  
  34.     private int mWidth;  
  35.     private int mHeight;  
  36.     private int statusBarHeight ;  
  37.     private Bitmap mBitmap= null;  
  38.     private Bitmap overlay = null;  
  39.       
  40.     private Handler mHandler = new Handler();  
  41.   
  42.     public MoreWindow(Activity context) {  
  43.         mContext = context;  
  44.     }  
  45.   
  46.     public void init() {  
  47.         Rect frame = new Rect();  
  48.         mContext.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);  
  49.         statusBarHeight = frame.top;  
  50.         DisplayMetrics metrics = new DisplayMetrics();  
  51.         mContext.getWindowManager().getDefaultDisplay()  
  52.                 .getMetrics(metrics);  
  53.         mWidth = metrics.widthPixels;  
  54.         mHeight = metrics.heightPixels;  
  55.           
  56.         setWidth(mWidth);  
  57.         setHeight(mHeight);  
  58.     }  
  59.       
  60.     private Bitmap blur() {  
  61.         if (null != overlay) {  
  62.             return overlay;  
  63.         }  
  64.         long startMs = System.currentTimeMillis();  
  65.   
  66.         View view = mContext.getWindow().getDecorView();  
  67.         view.setDrawingCacheEnabled(true);  
  68.         view.buildDrawingCache(true);  
  69.         mBitmap = view.getDrawingCache();  
  70.           
  71.         float scaleFactor = 8;//图片缩放比例;  
  72.         float radius = 10;//模糊程度  
  73.         int width = mBitmap.getWidth();  
  74.         int height =  mBitmap.getHeight();  
  75.   
  76.         overlay = Bitmap.createBitmap((int) (width / scaleFactor),(int) (height / scaleFactor),Bitmap.Config.ARGB_8888);  
  77.         Canvas canvas = new Canvas(overlay);  
  78.         canvas.scale(1 / scaleFactor, 1 / scaleFactor);  
  79.         Paint paint = new Paint();  
  80.         paint.setFlags(Paint.FILTER_BITMAP_FLAG);  
  81.         canvas.drawBitmap(mBitmap, 00, paint);  
  82.   
  83.         overlay = FastBlur.doBlur(overlay, (int) radius, true);  
  84.         Log.i(TAG, "blur time is:"+(System.currentTimeMillis() - startMs));  
  85.         return overlay;  
  86.     }  
  87.       
  88.     private Animation showAnimation1(final View view,int fromY ,int toY) {  
  89.         AnimationSet set = new AnimationSet(true);  
  90.         TranslateAnimation go = new TranslateAnimation(00, fromY, toY);  
  91.         go.setDuration(300);  
  92.         TranslateAnimation go1 = new TranslateAnimation(00, -102);  
  93.         go1.setDuration(100);  
  94.         go1.setStartOffset(250);  
  95.         set.addAnimation(go1);  
  96.         set.addAnimation(go);  
  97.   
  98.         set.setAnimationListener(new AnimationListener() {  
  99.   
  100.             @Override  
  101.             public void onAnimationEnd(Animation animation) {  
  102.             }  
  103.   
  104.             @Override  
  105.             public void onAnimationRepeat(Animation animation) {  
  106.   
  107.             }  
  108.   
  109.             @Override  
  110.             public void onAnimationStart(Animation animation) {  
  111.   
  112.             }  
  113.   
  114.         });  
  115.         return set;  
  116.     }  
  117.       
  118.   
  119.     public void showMoreWindow(View anchor,int bottomMargin) {  
  120.         final RelativeLayout layout = (RelativeLayout)LayoutInflater.from(mContext).inflate(R.layout.center_music_more_window, null);  
  121.         setContentView(layout);  
  122.           
  123.         ImageView close= (ImageView)layout.findViewById(R.id.center_music_window_close);  
  124.         android.widget.RelativeLayout.LayoutParams params =new android.widget.RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);  
  125.         params.bottomMargin = bottomMargin;  
  126.         params.addRule(RelativeLayout.BELOW, R.id.more_window_auto);  
  127.         params.addRule(RelativeLayout.RIGHT_OF, R.id.more_window_collect);  
  128.         params.topMargin = 200;  
  129.         params.leftMargin = 18;  
  130.         close.setLayoutParams(params);  
  131.           
  132.         close.setOnClickListener(new OnClickListener() {  
  133.   
  134.             @Override  
  135.             public void onClick(View v) {  
  136.                 if (isShowing()) {  
  137.                     closeAnimation(layout);  
  138.                 }  
  139.             }  
  140.   
  141.         });  
  142.           
  143.         showAnimation(layout);  
  144.         setBackgroundDrawable(new BitmapDrawable(mContext.getResources(), blur()));  
  145.         setOutsideTouchable(true);  
  146.         setFocusable(true);  
  147.         showAtLocation(anchor, Gravity.BOTTOM, 0, statusBarHeight);  
  148.     }  
  149.   
  150.     private void showAnimation(ViewGroup layout){  
  151.         for(int i=0;i<layout.getChildCount();i++){  
  152.             final View child = layout.getChildAt(i);  
  153.             if(child.getId() == R.id.center_music_window_close){  
  154.                 continue;  
  155.             }  
  156.             child.setOnClickListener(this);  
  157.             child.setVisibility(View.INVISIBLE);  
  158.             mHandler.postDelayed(new Runnable() {  
  159.                   
  160.                 @Override  
  161.                 public void run() {  
  162.                     child.setVisibility(View.VISIBLE);  
  163.                     ValueAnimator fadeAnim = ObjectAnimator.ofFloat(child, "translationY"6000);  
  164.                     fadeAnim.setDuration(300);  
  165.                     KickBackAnimator kickAnimator = new KickBackAnimator();  
  166.                     kickAnimator.setDuration(150);  
  167.                     fadeAnim.setEvaluator(kickAnimator);  
  168.                     fadeAnim.start();  
  169.                 }  
  170.             }, i * 50);  
  171.         }  
  172.           
  173.     }  
  174.   
  175.     private void closeAnimation(ViewGroup layout){  
  176.         for(int i=0;i<layout.getChildCount();i++){  
  177.             final View child = layout.getChildAt(i);  
  178.             if(child.getId() == R.id.center_music_window_close){  
  179.                 continue;  
  180.             }  
  181.             child.setOnClickListener(this);  
  182.             mHandler.postDelayed(new Runnable() {  
  183.                   
  184.                 @Override  
  185.                 public void run() {  
  186.                     child.setVisibility(View.VISIBLE);  
  187.                     ValueAnimator fadeAnim = ObjectAnimator.ofFloat(child, "translationY"0600);  
  188.                     fadeAnim.setDuration(200);  
  189.                     KickBackAnimator kickAnimator = new KickBackAnimator();  
  190.                     kickAnimator.setDuration(100);  
  191.                     fadeAnim.setEvaluator(kickAnimator);  
  192.                     fadeAnim.start();  
  193.                     fadeAnim.addListener(new AnimatorListener() {  
  194.                           
  195.                         @Override  
  196.                         public void onAnimationStart(Animator animation) {  
  197.                             // TODO Auto-generated method stub  
  198.                               
  199.                         }  
  200.                           
  201.                         @Override  
  202.                         public void onAnimationRepeat(Animator animation) {  
  203.                             // TODO Auto-generated method stub  
  204.                               
  205.                         }  
  206.                           
  207.                         @Override  
  208.                         public void onAnimationEnd(Animator animation) {  
  209.                             child.setVisibility(View.INVISIBLE);  
  210.                         }  
  211.                           
  212.                         @Override  
  213.                         public void onAnimationCancel(Animator animation) {  
  214.                             // TODO Auto-generated method stub  
  215.                               
  216.                         }  
  217.                     });  
  218.                 }  
  219.             }, (layout.getChildCount()-i-1) * 30);  
  220.               
  221.             if(child.getId() == R.id.more_window_local){  
  222.                 mHandler.postDelayed(new Runnable() {  
  223.                       
  224.                     @Override  
  225.                     public void run() {  
  226.                         dismiss();  
  227.                     }  
  228.                 }, (layout.getChildCount()-i) * 30 + 80);  
  229.             }  
  230.         }  
  231.           
  232.     }  
  233.   
  234.     @Override  
  235.     public void onClick(View v) {  
  236.         switch (v.getId()) {  
  237.         case R.id.more_window_local:  
  238.             break;  
  239.         case R.id.more_window_online:  
  240.             break;  
  241.         case R.id.more_window_delete:  
  242.             break;  
  243.         case R.id.more_window_collect:  
  244.             break;  
  245.         case R.id.more_window_auto:  
  246.             break;  
  247.         case R.id.more_window_external:  
  248.             break;  
  249.   
  250.         default:  
  251.             break;  
  252.         }  
  253.     }  
  254.       
  255.     public void destroy() {  
  256.         if (null != overlay) {  
  257.             overlay.recycle();  
  258.             overlay = null;  
  259.             System.gc();  
  260.         }  
  261.         if (null != mBitmap) {  
  262.             mBitmap.recycle();  
  263.             mBitmap = null;  
  264.             System.gc();  
  265.         }  
  266.     }  
  267.       
  268. }  



KickBackAnimator.Java回弹效果: 
Java代码   收藏代码
  1. package com.jerome.weibo;  
  2.   
  3. import android.animation.TypeEvaluator;  
  4.   
  5. public class KickBackAnimator implements TypeEvaluator<Float> {  
  6.     private final float s = 1.70158f;  
  7.     float mDuration = 0f;  
  8.   
  9.     public void setDuration(float duration) {  
  10.         mDuration = duration;  
  11.     }  
  12.   
  13.     public Float evaluate(float fraction, Float startValue, Float endValue) {  
  14.         float t = mDuration * fraction;  
  15.         float b = startValue.floatValue();  
  16.         float c = endValue.floatValue() - startValue.floatValue();  
  17.         float d = mDuration;  
  18.         float result = calculate(t, b, c, d);  
  19.         return result;  
  20.     }  
  21.   
  22.     public Float calculate(float t, float b, float c, float d) {  
  23.         return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;  
  24.     }  
  25. }  


代码见github: 
https://github.com/gqdy365/WeiboPopupWindow 
请大家star一下,我后面会持续更新; 
  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值