Android实现微博菜单弹出效果
发布时间 - 2026-01-11 02:24:05 点击率:次先上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
# 微博
# 菜单弹出
# Android 侧滑抽屉菜单的实现代码
# Android实现动画效果的自定义下拉菜单功能
# Android实现上下菜单双向滑动
# Android如何实现底部菜单固定到底部
# Android实现微信加号菜单模式
# Android实现卫星菜单效果
# Android自定义转盘菜单效果
# Android底部菜单栏(RadioGroup+Fragment)美化
# Android recyclerView横条指示器实现淘宝菜单模块
# android studio 的下拉菜单Spinner使用详解
# Android仿新浪微博发送菜单界面的实现
# 下载地址
# 是由
# 不是很
# 请大家
# 要注意
# 弹出
# 关闭窗口
# 可以下载
# 买个
# 大家多多
# 比前
# 高斯
# 插值
# 只能在
# top
# null
# void
# mBitmap
# metrics
# init
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
JS中页面与页面之间超链接跳转中文乱码问题的解决办法
Laravel怎么使用Collection集合方法_Laravel数组操作高级函数pluck与map【手册】
Laravel怎么解决跨域问题_Laravel配置CORS跨域访问
如何基于云服务器快速搭建个人网站?
如何快速搭建FTP站点实现文件共享?
电视网站制作tvbox接口,云海电视怎样自定义添加电视源?
Laravel Octane如何提升性能_使用Laravel Octane加速你的应用
C#如何调用原生C++ COM对象详解
Laravel如何实现密码重置功能_Laravel密码找回与重置流程
Android使用GridView实现日历的简单功能
文字头像制作网站推荐软件,醒图能自动配文字吗?
深圳网站制作的公司有哪些,dido官方网站?
b2c电商网站制作流程,b2c水平综合的电商平台?
详解CentOS6.5 安装 MySQL5.1.71的方法
php打包exe后无法访问网络共享_共享权限设置方法【教程】
Python文件流缓冲机制_IO性能解析【教程】
Laravel API资源类怎么用_Laravel API Resource数据转换
如何解决hover在ie6中的兼容性问题
Android滚轮选择时间控件使用详解
Laravel如何集成第三方登录_Laravel Socialite实现微信QQ微博登录
html文件怎么打开证书错误_https协议的html打开提示不安全【指南】
如何用低价快速搭建高质量网站?
香港服务器租用费用高吗?如何避免常见误区?
如何快速辨别茅台真假?关键步骤解析
Android实现代码画虚线边框背景效果
JavaScript Ajax实现异步通信
php做exe能调用系统命令吗_执行cmd指令实现方式【详解】
网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?
html5如何设置样式_HTML5样式设置方法与CSS应用技巧【教程】
香港服务器WordPress建站指南:SEO优化与高效部署策略
高防服务器如何保障网站安全无虞?
香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化
晋江文学城电脑版官网 晋江文学城网页版直接进入
清除minerd进程的简单方法
如何快速生成ASP一键建站模板并优化安全性?
如何在不使用负向后查找的情况下匹配特定条件前的换行符
Laravel Eloquent性能优化技巧_Laravel N+1查询问题解决
如何快速搭建高效WAP手机网站?
Laravel如何实现API资源集合?(Resource Collection教程)
如何快速查询网址的建站时间与历史轨迹?
历史网站制作软件,华为如何找回被删除的网站?
百度输入法ai组件怎么删除 百度输入法ai组件移除工具
Laravel怎么调用外部API_Laravel Http Client客户端使用
Win11怎样安装网易有道词典_Win11安装词典教程【步骤】
如何构建满足综合性能需求的优质建站方案?
Laravel Seeder填充数据教程_Laravel模型工厂Factory使用
微信小程序 wx.uploadFile无法上传解决办法
Laravel怎么处理异常_Laravel自定义异常处理与错误页面教程
如何在万网主机上快速搭建网站?
Laravel怎么实现搜索功能_Laravel使用Eloquent实现模糊查询与多条件搜索【实例】

