先上效果图,这个截图不是很流畅,大家可以下载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窗口
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下载地址:
- 大小: 388.8 KB
分享到:
相关推荐
在Android开发中,实现微博菜单弹出效果是一个常见的需求,它可以增强应用的用户体验,使得功能操作更加直观且吸引人。以下将详细介绍如何在Android中实现这一功能。 首先,我们需要了解实现这一效果的基本步骤: ...
Android 仿新浪微博加号弹出界面动画。
在Android应用开发中,设计一个类似新浪微博首页加号弹出菜单的效果是一项常见的需求,它可以提供丰富的功能选项,增强用户体验。这个效果通常涉及到自定义View、PopupWindow、动画以及触摸事件的处理等多个Android...
仿微博、酷安点击加号揭露动画弹出菜单 背景模糊效果 截图 没有像酷安那样扩展到导航栏,以后有机会可以再研究吧。 使用的PopupWindow实现的,主要部分有 背景揭露动画;+ 旋转动画;菜单项弹出动画;背景模糊...
在Android开发中,"高仿新浪微博弹框菜单"是一个常见的用户界面组件,它提供了一种类似于新浪微博应用中的交互式弹出菜单。这种菜单通常在用户点击某个按钮或执行特定操作时从屏幕边缘滑出,展示一系列可选的操作或...
在这个项目中,"TPCSpringMenu-master"可能是一个开源库或者示例代码,用于实现类似微博中的弹出菜单效果。"TPC"可能是开发者或者团队的缩写,"SpringMenu"暗示了这个菜单可能采用了弹簧动画,即在展开或收起时有...
6:弹出菜单的使用,简单的弹出框,包含list的弹出框. 7:webview嵌入腾讯第三方授权页面的使用 8:最常用的ListView的使用 9:Tab布局的应用 10:listView的分页。 11:万能适配器BaseAdapter以及ArrayAdapter等...
在Android开发中,`PopupWindow` 是一个非常实用的组件,它可以用来创建弹出式窗口,比如下拉菜单、快捷操作等。在这个“Android用PopupWindow实现新浪微博的分组信息”示例中,我们将深入探讨如何利用`PopupWindow`...
综上所述,实现Android底部缓慢弹出菜单的过程包括创建菜单布局、定义动画效果、处理点击事件以及可能的第三方库集成。通过这种方式,可以为用户提供一个直观且有趣的交互方式,提升应用的易用性。
这个微博客户端中用到得一些知识点。...6:弹出菜单的使用,简单的弹出框,包含list的弹出框. 7:webview嵌入腾讯第三方授权页面的使用 8:最常用的ListView的使用 9:Tab布局的应用 10:listView的分页。 11:
仿最新版QQ空间,新浪微博底部菜单(Menu)源码,该效果是Fragment+FragmentTabHost实现仿新浪微博底部菜单栏,Fragment+PopupWindow仿QQ空间最新版底部菜单栏等,仿QQ空间的底部菜单栏效果为主,仿新浪微博底部菜单栏...
Android自定义View之实现流行的新浪微博底部菜单:高仿“咸鱼APP”的底部菜单动画效果。 - 对应的详细解答博客地址:1、前几天在手机看到了很好看的动画效果,于是,扬起袖子就是干:上图的是咸鱼App效果,下图是俺...
为了提供更好的用户体验,我们还可以弹出一个Toast提示用户复制成功: ```java Toast.makeText(this, "内容已复制", Toast.LENGTH_SHORT).show(); ``` 在实际开发中,考虑到多语言环境和特殊字符,可能还需要对...
【仿微博发布弹起动画】这表明项目试图复制微博应用中的某个特定功能,即当用户点击发布按钮时,出现的弹出菜单或对话框伴随着一种上升动画。这种动画不仅增加了视觉吸引力,还能帮助用户理解操作的结果。在Android...
BottomDialog 一个自定义的从底部弹出的dialog,仿照微博的分享弹框.支持横向、纵向、网格等布局导入compile 'top.zibin:BottomDialog:1.0.4'使用BottomDialog 只需要一句代码即可轻松显示底部弹框创建Menu<?xml...
模仿android新浪微博客户端菜单弹出效果 如图所示" 描述进一步明确了这个项目的目标,即模仿Android版新浪微博应用的菜单弹出交互。通常,这样的功能会涉及自定义对话框的实现,以及触摸事件的处理。"如图所示"暗示...