仿QQ空间根据位置弹出PopupWindow显示更多操作效果
我们打开QQ空间的时候有个箭头按钮点击之后弹出PopupWindow会根据位置的变化显示在箭头的上方还是下方,比普通的PopupWindow弹在屏幕中间显示好看的多。
先看QQ空间效果图:
这个要实现这个效果可以分几步进行
1.第一步自定义PopupWindow,实现如图的样式,这个继承PopupWindow自定义布局很容易实现
2.得到点击按钮的位置,根据位置是否在屏幕的中间的上方还是下方,将PopupWindow显示在控件的上方或者下方
3.适配问题,因为PopupWindow上面的操作列表是动态的所以要自定义listView
4.动画效果+背景变暗
通过步骤分析,我们就很清晰的了解我们要做什么,话不多说,从第一步开始吧
下面自定义PopupWindow实现效果
1.重写listView,重新计算高度(一般也应用于解决ScrollView嵌套listView只显示一行的问题)
public class MyListView extends ListView {
public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
} public MyListView(Context context) {
super(context);
} public MyListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
} @Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST));
}
}
2.自定义PopupWindow的布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="right">
<ImageView
android:id="@+id/arrow_up"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="28dp"
android:src="@drawable/arrow_up_white"
android:visibility="visible"/>
<com.widget.MyListView
android:id="@+id/lv_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/normal_margin8"
android:layout_marginTop="-1dp"
android:layout_marginBottom="-1dp"
android:dividerHeight="0dp"
android:layout_marginLeft="@dimen/normal_margin8"
android:layout_marginRight="@dimen/normal_margin8"
android:scrollbars="none"
android:background="@drawable/custom_white"
android:divider="@null"></com.widget.MyListView>
<ImageView
android:id="@+id/arrow_down"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="28dp"
android:src="@drawable/arrow_down_white"
android:visibility="visible"/>
</LinearLayout>
2.PopupWindow弹出动画以及消失动画
popshow_operation_anim_down.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXScale="0.0"
android:toXScale="1.0"
android:fromYScale="0.0"
android:toYScale="1.0"
android:pivotX="90%"
android:pivotY="0%"
android:fillAfter="false"
android:duration="300" >
</scale>
</set>
popshow_operation_anim_up.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXScale="0.0"
android:toXScale="1.0"
android:fromYScale="0.0"
android:toYScale="1.0"
android:pivotX="90%"
android:pivotY="100%"
android:fillAfter="false"
android:duration="250" >
</scale>
</set>
消失动画是渐隐动画可以自己定义,同理。
3.重写PopupWindow了
public class CustomOperationPopWindow extends PopupWindow {
private Context context;
private View conentView;
private View backgroundView;
private Animation anim_backgroundView;
private MyListView listView;
private TypeSelectPopuAdapter selectAdapter;
ImageView arrow_up, arrow_down;
List<TypeSelect> typeSelectlist = new ArrayList<>();
int[] location = new int[2];
private OnItemListener onItemListener;
private AdapterView.OnItemClickListener onItemClickListener; public interface OnItemListener {
public void OnItemListener(int position, TypeSelect typeSelect);
} ; public void setOnItemMyListener(OnItemListener onItemListener) {
this.onItemListener = onItemListener;
} public CustomOperationPopWindow(Context context) {
this.context = context;
initView();
} public CustomOperationPopWindow(Context context, List<TypeSelect> typeSelectlist) {
this.context = context;
this.typeSelectlist = typeSelectlist;
initView();
} private void initView() {
this.anim_backgroundView = AnimationUtils.loadAnimation(context, R.anim.alpha_show_anim);
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.conentView = inflater.inflate(R.layout.view_operation_popupwindow, null);
// 设置SelectPicPopupWindow的View
this.setContentView(conentView);
// 设置SelectPicPopupWindow弹出窗体的宽
this.setWidth(LayoutParams.MATCH_PARENT);
// 设置SelectPicPopupWindow弹出窗体的高
this.setHeight(LayoutParams.WRAP_CONTENT);
// 设置SelectPicPopupWindow弹出窗体可点击
this.setFocusable(true);
this.setOutsideTouchable(true);
// 刷新状态
this.update();
// 实例化一个ColorDrawable颜色为半透明
ColorDrawable dw = new ColorDrawable(0000000000);
// 点back键和其他地方使其消失,设置了这个才能触发OnDismisslistener ,设置其他控件变化等操作
this.setBackgroundDrawable(dw);
// 设置SelectPicPopupWindow弹出窗体动画效果
this.setAnimationStyle(R.style.operation_popwindow_anim_style_up);
this.listView = (MyListView) conentView.findViewById(R.id.lv_list);
this.arrow_up = (ImageView) conentView.findViewById(R.id.arrow_up);
this.arrow_down = (ImageView) conentView.findViewById(R.id.arrow_down); //设置适配器
this.selectAdapter = new TypeSelectPopuAdapter(context, typeSelectlist,
R.layout.item_operation_popu);
this.listView.setAdapter(selectAdapter);
this.listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (isShowing()) {
dismiss();
}
onItemListener.OnItemListener(position, typeSelectlist.get(position));
}
});
this.setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss() {
if (backgroundView != null) {
backgroundView.setVisibility(View.GONE);
}
}
});
} //设置数据
public void setDataSource(List<TypeSelect> typeSelectlist) {
this.typeSelectlist = typeSelectlist;
this.selectAdapter.notifyDataSetChanged();
} /**
* 没有半透明背景 显示popupWindow
*
* @param
*/
public void showPopupWindow(View v) {
v.getLocationOnScreen(location); //获取控件的位置坐标
//获取自身的长宽高
conentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
if (location[1] > MainApplication.SCREEN_H / 2 + 100) { //MainApplication.SCREEN_H 为屏幕的高度,方法可以自己写
this.setAnimationStyle(R.style.operation_popwindow_anim_style_up);
arrow_up.setVisibility(View.GONE);
arrow_down.setVisibility(View.VISIBLE);
this.showAtLocation(v, Gravity.NO_GRAVITY, (location[0]), location[1] - conentView.getMeasuredHeight());
} else {
this.setAnimationStyle(R.style.operation_popwindow_anim_style_down);
arrow_up.setVisibility(View.VISIBLE);
arrow_down.setVisibility(View.GONE);
this.showAsDropDown(v, 0, 0);
}
} /**
* 携带半透明背景 显示popupWindow
*
* @param
*/
public void showPopupWindow(View v, View backgroundView) {
this.backgroundView = backgroundView;
v.getLocationOnScreen(location); //获取控件的位置坐标
//获取自身的长宽高
conentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
backgroundView.setVisibility(View.VISIBLE);
//对view执行动画
backgroundView.startAnimation(anim_backgroundView);
if (location[1] > MainApplication.SCREEN_H / 2 + 100) { //若是控件的y轴位置大于屏幕高度的一半,向上弹出
this.setAnimationStyle(R.style.operation_popwindow_anim_style_up);
arrow_up.setVisibility(View.GONE);
arrow_down.setVisibility(View.VISIBLE);
this.showAtLocation(v, Gravity.NO_GRAVITY, (location[0]), location[1] - conentView.getMeasuredHeight()); //显示指定控件的上方
} else {
this.setAnimationStyle(R.style.operation_popwindow_anim_style_down); //反之向下弹出
arrow_up.setVisibility(View.VISIBLE);
arrow_down.setVisibility(View.GONE);
this.showAsDropDown(v, 0, 0); //显示指定控件的下方
}
}
/**
* 显示popupWindow 根据特殊要求高度显示位置
*
* @param
*/
public void showPopupWindow(View v, View backgroundView,int hight) {
this.backgroundView = backgroundView;
v.getLocationOnScreen(location);
//获取自身的长宽高
conentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
backgroundView.setVisibility(View.VISIBLE);
//对view执行动画
backgroundView.startAnimation(anim_backgroundView);
if (location[1] > MainApplication.SCREEN_H / 2 + 100) {
this.setAnimationStyle(R.style.operation_popwindow_anim_style_up);
arrow_up.setVisibility(View.GONE);
arrow_down.setVisibility(View.VISIBLE);
this.showAtLocation(v, Gravity.NO_GRAVITY, (location[0]), location[1] - conentView.getMeasuredHeight()-hight);
} else {
this.setAnimationStyle(R.style.operation_popwindow_anim_style_down);
arrow_up.setVisibility(View.VISIBLE);
arrow_down.setVisibility(View.GONE);
this.showAsDropDown(v, 0, 0);
}
}
}
4.代码中的用法
1.
CustomOperationPopWindow customOperationPopWindow = new CustomOperationPopWindow(this, operationTypeSelectlist);
customOperationPopWindow.setOnItemMyListener(new CustomOperationPopWindow.OnItemListener() {
@Override
public void OnItemListener(int position, TypeSelect typeSelect) {
//此处实现列表点击所要进行的操作
}
});
2.
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
customOperationPopWindow.showPopupWindow(textView);//可以传个半透明view v_background过去根据业务需要显示隐藏
}
});
5.最终实际效果
以上代码为几乎主要全部代码,主要是PopupWindow的用法,思路清晰一步一步实现很简单。
仿QQ空间根据位置弹出PopupWindow显示更多操作效果的更多相关文章
- Android项目实战(十七):QQ空间实现(二)—— 分享功能 / 弹出PopupWindow
这是一张QQ空间说说详情的截图. 分析: .点击右上角三个点的图标,在界面底部弹出一个区域,这个区域有一些按钮提供给我们操作 .当该区域出现的时候,详情界面便灰了,也说成透明度变化了 .当任意选了一个 ...
- (转载)Android项目实战(十七):QQ空间实现(二)—— 分享功能 / 弹出PopupWindow
Android项目实战(十七):QQ空间实现(二)—— 分享功能 / 弹出PopupWindow 这是一张QQ空间说说详情的截图. 分析: 1.点击右上角三个点的图标,在界面底部弹出一个区域,这个 ...
- 【Android UI设计与开发】7.底部菜单栏(四)PopupWindow 实现显示仿腾讯新闻底部弹出菜单
前一篇文章中有用到 PopupWindow 来实现弹窗的功能.简单介绍以下吧. 官方文档是这样解释的:这就是一个弹出窗口,可以用来显示一个任意视图.出现的弹出窗口是一个浮动容器的当前活动. 1.首先来 ...
- 仿iOS底部弹出popUpWindow
上面为弹出来的效果 popUpWindow布局: <?xml version="1.0" encoding="utf-8"?> <Linear ...
- Fragment,仿QQ空间
转载请注明出处:http://blog.csdn.net/yangyu20121224/article/details/9023451 在今天的这篇文章当中,我依然会以实战加理论结合 ...
- 仿QQ空间和微信朋友圈,高解耦高复用高灵活
先看看效果: 用极少的代码实现了 动态详情 及 二级评论 的 数据获取与处理 和 UI显示与交互,并且高解耦.高复用.高灵活. 动态列表界面MomentListFragment支持 下拉刷新与上拉加载 ...
- 仿QQ空间动态界面分享
先看看效果: 用极少的代码实现了 动态详情 及 二级评论 的 数据获取与处理 和 UI显示与交互,并且高解耦.高复用.高灵活. 动态列表界面MomentListFragment支持 下拉刷新与上拉加载 ...
- Android Animation动画实战(二):从屏幕底部弹出PopupWindow
在这篇文章之前,我已经陆陆续续写了几篇博客,介绍了Android Animation是如何使用的,有还不明白的,可以点击查看: 1. Android Animation动画详解(一): 补间动画 2. ...
- JS仿QQ空间鼠标停在长图片时候图片自动上下滚动效果
JS仿QQ空间鼠标停在长图片时候图片自动上下滚动效果 今天是2014年第一篇博客是关于类似于我们的qq空间长图片展示效果,因为一张很长的图片不可能全部把他展示出来,所以外层用了一个容器给他一个高度,超 ...
随机推荐
- 编写一个通用的Makefile文件
1.1在这之前,我们需要了解程序的编译过程 a.预处理:检查语法错误,展开宏,包含头文件等 b.编译:*.c-->*.S c.汇编:*.S-->*.o d.链接:.o +库文件=*.exe ...
- iOS 方法修饰符
一.NS_DESIGNATED_INITIALIZER 用来修饰init方法,被修饰的方法称为designated initializer:没有被这个修饰的init方法称为convenience i ...
- win7,Mindmanager2012使用模板时弹出Runtime error R6025解决方法
Mindjet.MindManager2012.v10.0在应用个别模板时提示"参数错误",然后自动关闭. 解决办法: 如果是win7系统,可以进入C:\Users\(用户名)\A ...
- [转]Java常用工具类集合
转自:http://blog.csdn.net/justdb/article/details/8653166 数据库连接工具类——仅仅获得连接对象 ConnDB.java package com.ut ...
- [计算机网络]简易http server程序
好久没输出了,知识还是要写下总结才能让思路更加清晰.最近在学习计算机网络相关的知识,来聊聊如何编写一个建议的HTTP服务器. 这个http server的实现源代码我放在了我的github上,有兴趣的 ...
- chrome拓展开发实战:页面脚本的拦截注入
原文请访问个人博客:chrome拓展开发实战:页面脚本的拦截注入 目前公司产品的无线站点已经实现了业务平台组件化,所有业务组件的转场都是通过路由来完成,而各个模块是通过requirejs进行统一管理, ...
- iOS--碎片知识锦集
知识锦集day01 1.UIView的两个方法: sizeThatFits和 sizeToFit 官方文档上说: - (CGSize)sizeThatFits:(CGSize)size; // ...
- Android笔记——AsyncTask介绍
AsyncTask和Handler对比 1 ) AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操 ...
- 二、Redis基本操作——String(实战篇)
小喵万万没想到,上一篇博客,居然已经被阅读600次了!!!让小喵感觉压力颇大.万一有写错的地方,岂不是会误导很多筒子们.所以,恳请大家,如果看到小喵的博客有什么不对的地方,请尽快指正!谢谢! 小喵的唠 ...
- 解析大型.NET ERP系统 自动更新
C/S架构的应用程序需要支持自动更新功能,当新版本程序发布后,正在运行的客户端能检测到新版本的程序,通知用户是否下载更新.工作以来参与过几个自动更新模块的设计与维护,撰文总结自动更新模块设计与实现. ...