Android实现微博菜单弹出效果
先上Android仿微博菜单弹出效果图,这个截图不是很流畅,大家可以下载apk试一下。
说一下实现思路:
1、截取当前窗口,对图片做高斯模糊处理,将处理后的图片做popupwindow的背景图片;
2、创建popupwindow,完成布局,这儿要注意:View的移动范围是由parent的大小决定的,就是只能在parent的范围内移动;
3、给买个View添加进入动画,每个比前一个延期50ms播放动画,关闭窗口时相反;
4、为View的动画添加回弹插值器;
MoreWindow.java窗口
package com.jerome.weibo; 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.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.AnimationSet; import android.view.animation.TranslateAnimation; import android.widget.ImageView; import android.widget.PopupWindow; import android.widget.RelativeLayout; import android.widget.RelativeLayout.LayoutParams; 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; } private Animation showAnimation1(final View view,int fromY ,int toY) { AnimationSet set = new AnimationSet(true); TranslateAnimation go = new TranslateAnimation(0, 0, fromY, toY); go.setDuration(300); TranslateAnimation go1 = new TranslateAnimation(0, 0, -10, 2); go1.setDuration(100); go1.setStartOffset(250); set.addAnimation(go1); set.addAnimation(go); set.setAnimationListener(new AnimationListener() { @Override public void onAnimationEnd(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationStart(Animation animation) { } }); return set; } public void showMoreWindow(View anchor,int bottomMargin) { final RelativeLayout layout = (RelativeLayout)LayoutInflater.from(mContext).inflate(R.layout.center_music_more_window, null); setContentView(layout); ImageView close= (ImageView)layout.findViewById(R.id.center_music_window_close); android.widget.RelativeLayout.LayoutParams params =new android.widget.RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT); params.bottomMargin = bottomMargin; params.addRule(RelativeLayout.BELOW, R.id.more_window_auto); params.addRule(RelativeLayout.RIGHT_OF, R.id.more_window_collect); params.topMargin = 200; params.leftMargin = 18; close.setLayoutParams(params); close.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(anchor, 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.center_music_window_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.center_music_window_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.more_window_local){ 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.more_window_local: break; case R.id.more_window_online: break; case R.id.more_window_delete: break; case R.id.more_window_collect: break; case R.id.more_window_auto: break; case R.id.more_window_external: break; default: break; } } public void destroy() { if (null != overlay) { overlay.recycle(); overlay = null; System.gc(); } if (null != mBitmap) { mBitmap.recycle(); mBitmap = null; System.gc(); } } }
KickBackAnimator.Java回弹效果:
package com.jerome.weibo; import android.animation.TypeEvaluator; public class KickBackAnimator implements TypeEvaluator<Float> { 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; } }
代码见github: https://github.com/gqdy365/WeiboPopupWindow
请大家star一下,我后面会持续更新;
下面是apk下载地址:WeiboPopupWindow
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
相关文章
android用java和c实现查找sd卡挂载路径(sd卡路径)的方法
这篇文章主要介绍了android用java和c实现查找sd卡挂载路径(sd卡路径)的方法,需要的朋友可以参考下2014-02-02Android Compose Column列表不自动刷新问题
这篇文章主要介绍了Android Compose Column列表数据更新列表不刷新的问题,总的来说这并不是一道难题,那为什么要拿出这道题介绍?拿出这道题真正想要传达的是解题的思路,以及不断优化探寻最优解的过程。希望通过这道题能给你带来一种解题优化的思路2023-01-01Android 进阶实现性能优化之OOM与Leakcanary详解原理
LeakCanary 是大名鼎鼎的 square 公司开源的内存泄漏检测工具。目前上大部分App在开发测试阶段都会接入此工具用于检测潜在的内存泄漏问题,做的好一点的可能会搭建一个服务器用于保存各个设备上的内存泄漏问题再集中处理2021-11-11关于OkHttp中response.body().string()的用法解析
这篇文章主要介绍了关于OkHttp中response.body().string()的用法解析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2023-06-06
最新评论