我们打开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显示更多操作效果的更多相关文章

  1. Android项目实战(十七):QQ空间实现(二)—— 分享功能 / 弹出PopupWindow

    这是一张QQ空间说说详情的截图. 分析: .点击右上角三个点的图标,在界面底部弹出一个区域,这个区域有一些按钮提供给我们操作 .当该区域出现的时候,详情界面便灰了,也说成透明度变化了 .当任意选了一个 ...

  2. (转载)Android项目实战(十七):QQ空间实现(二)—— 分享功能 / 弹出PopupWindow

    Android项目实战(十七):QQ空间实现(二)—— 分享功能 / 弹出PopupWindow   这是一张QQ空间说说详情的截图. 分析: 1.点击右上角三个点的图标,在界面底部弹出一个区域,这个 ...

  3. 【Android UI设计与开发】7.底部菜单栏(四)PopupWindow 实现显示仿腾讯新闻底部弹出菜单

    前一篇文章中有用到 PopupWindow 来实现弹窗的功能.简单介绍以下吧. 官方文档是这样解释的:这就是一个弹出窗口,可以用来显示一个任意视图.出现的弹出窗口是一个浮动容器的当前活动. 1.首先来 ...

  4. 仿iOS底部弹出popUpWindow

    上面为弹出来的效果 popUpWindow布局: <?xml version="1.0" encoding="utf-8"?> <Linear ...

  5. Fragment,仿QQ空间

    转载请注明出处:http://blog.csdn.net/yangyu20121224/article/details/9023451          在今天的这篇文章当中,我依然会以实战加理论结合 ...

  6. 仿QQ空间和微信朋友圈,高解耦高复用高灵活

    先看看效果: 用极少的代码实现了 动态详情 及 二级评论 的 数据获取与处理 和 UI显示与交互,并且高解耦.高复用.高灵活. 动态列表界面MomentListFragment支持 下拉刷新与上拉加载 ...

  7. 仿QQ空间动态界面分享

    先看看效果: 用极少的代码实现了 动态详情 及 二级评论 的 数据获取与处理 和 UI显示与交互,并且高解耦.高复用.高灵活. 动态列表界面MomentListFragment支持 下拉刷新与上拉加载 ...

  8. Android Animation动画实战(二):从屏幕底部弹出PopupWindow

    在这篇文章之前,我已经陆陆续续写了几篇博客,介绍了Android Animation是如何使用的,有还不明白的,可以点击查看: 1. Android Animation动画详解(一): 补间动画 2. ...

  9. JS仿QQ空间鼠标停在长图片时候图片自动上下滚动效果

    JS仿QQ空间鼠标停在长图片时候图片自动上下滚动效果 今天是2014年第一篇博客是关于类似于我们的qq空间长图片展示效果,因为一张很长的图片不可能全部把他展示出来,所以外层用了一个容器给他一个高度,超 ...

随机推荐

  1. 《CPU的工作过程》

    本文转载自inter官方网址:https://software.intel.com/zh-cn/articles/book-Processor-Architecture_CPU_work_proces ...

  2. Princeton Algorithms week3 Assignment

    这周编程作业是实现检测点共线的算法.和排序算法有关系的地方在于,对斜率排序后可以很快的检测出来哪些点是共线的,另外这个算法的瓶颈也在于排序的性能. 一点收获: java传参数时传递的是值,这很多人都知 ...

  3. CYQ.Data V5 分布式缓存Redis应用开发及实现算法原理介绍

    前言: 自从CYQ.Data框架出了数据库读写分离.分布式缓存MemCache.自动缓存等大功能之后,就进入了频繁的细节打磨优化阶段. 从以下的更新列表就可以看出来了,3个月更新了100条次功能: 3 ...

  4. linux下mono播放PCM音频

         测试环境: Ubuntu 14 MonoDevelop CodeBlocks 1.建立一个共享库(shared library) 这里用到了linux下的音频播放库,alsa-lib. al ...

  5. 使用CSS3的box-shadow实现双透明遮罩层对话框

    box-shadow介绍 在我之前的一篇文章<从天猫和支付宝身上学习opcity与rgba>中,介绍了实现双透明遮罩层效果的两种方法,分别是opacity和rgba.他们需要分别依赖于不同 ...

  6. 3D游戏中的画质与效率适配

      哪里来的需求? 众所周知,由于不同的设备配置不同.导致其CPU和GPU处理能力有高有低.同样的游戏想要在所有设备上运行流畅且画面精美,是不可能的.这就需要我们针对不同的设备能力进行画质调节,以保证 ...

  7. Android开发学习之路-关于Exception

    Exception在Java中是表示异常的一个类.它是Throwable的子类. 而Exception的子类RuntimeException是一个特殊的异常类,在代码中不需要对此类进行throw,而是 ...

  8. Java–cvc-complex-type.4:Attribut ‘version’ must appear on element ‘web-app’

    问题解析: 在web.xml中的以下代码中 <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi=" ...

  9. IOC的理解

    转载http://www.cnblogs.com/xdp-gacl/p/4249939.html 很不错的文章,虽说是java的,但是.net也通用,所以复制一分,拿来看看挺不错的. 1.1.IoC是 ...

  10. 04.移动先行之谁主沉浮----XAML的探索

    如果移动方向有任何问题请参考===> 异常处理汇总-移动系列(点) 移动先行之谁主沉浮? 带着你的Net飞奔吧! 链接======>(点) XMAL引入 XAML 类似于 HTML,是一种 ...