最近开发一款留言板手机客户端,需要到对话框来确认用户操作,但是系统自带的对话框很丑,不想用,所以就自定义PopWindow,想怎么显示就怎么显示,而且还方便添加显示动态,和背景图片。下面,我就来分享一下我的学习经验。
1、什么是popWindow?(1、2是博主网上找的)
popWindow就是对话框的一种方式!此文讲解的android中对话框的一种使用方式,它叫popWindow。
2、popWindow的特性
Android的对话框有两种:PopupWindow和Dialog。它们的不同点在于:
Dialog的位置固定,而PopupWindow的位置可以随意。
PopupWindow的位置按照有无偏移分,可以分为偏移和无偏移两种;按照参照物的不同,可以分为相对于某个控件(Anchor锚)和相对于父控件。具体如下
showAsDropDown(View anchor):相对某个控件的位置(正左下方),无偏移
showAsDropDown(View anchor, int xoff, int yoff):相对某个控件的位置,有偏移
showAtLocation(View parent, int gravity, int x, int y):相对于父控件的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以设置偏移或无偏移
3、PopWindow中控件的监听
PopWindow已经添加到布局中去了,那么问题来了,我要怎么通过自定义的控件来处理同级容器中的事件?其实很简单,博主在这里分享两种,第一种是通过接口:在PopWindow同级容器中实现自定义的相应接口,然后在传入到PopWindow对象中,在PopWindow对象中组件的监听事件中通过接口回调来实现控制;第二种方法就是:在继承于PopWindow的类中添加一个返回PopWindow布局的View的共有方法getPopWindowView(),在同级容器中定义PopWindow中控件的引用,然后将引用通过getPopWindowView().findViewById(R.id.xxx)指向相应的控件对象,最后在通过引用添加监听事件。
4、手机虚拟按键存在与否对底部滑出PopWindow的影响
当存在虚拟按键时候如果底部滑出相对于同级容器中的某个组件,则显示不完全,没有虚拟按键则不存在这种问题。怎么解决呢?其实很简单,只需要通过相对于父级容器位置来显示。即用showAtLocation(View parent, int gravity, int x, int y):相对于父控件的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等)。
5、点击PopWindow外部消失问题
在继承与PopWindow的类中必须实现setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT))这个方法来设置背景色才行,否则不行,当然我这里设置的全透明,只显示背景图片。
这里我就直接略过具体的PopWindow显示效果的xml文件了,直接上主要代码
一、MainActivity类:
package com.example.mypopwindowdemo;
import android.app.Activity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener{
private Button pop_under_button;
private Button bottom_popwindow;
private Button left,right;
private View buttonPopView;
private MyPopWindowBottomShow myPopWindowBottomShow;//屏幕底部popwindow
private MyButtonPopwindow myButtonPopwindow;//按钮下popwindow
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pop_under_button = (Button) findViewById(R.id.pop_under_button);
bottom_popwindow = (Button) findViewById(R.id.bottom_popwindow);
pop_under_button.setOnClickListener(this);
bottom_popwindow.setOnClickListener(this);
myPopWindowBottomShow = new MyPopWindowBottomShow(this, new BottomPopWindow());
myButtonPopwindow = new MyButtonPopwindow(this, R.layout.under_button_pop_window, new PoPUnderListener());
buttonPopView = myButtonPopwindow.getPopWindowView();
left = (Button) buttonPopView.findViewById(R.id.left);
right = (Button) buttonPopView.findViewById(R.id.right);
left.setOnClickListener(new OnClickListener() {//对象外部添加监听事件
@Override
public void onClick(View arg0) {
myButtonPopwindow.dismiss();
Toast.makeText(MainActivity.this, "左边测试", Toast.LENGTH_SHORT).show();
}
});
right.setOnClickListener(new OnClickListener() {//对象外部添加监听事件
@Override
public void onClick(View arg0) {
myButtonPopwindow.dismiss();
Toast.makeText(MainActivity.this, "右边测试", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onClick(View arg0) {
switch (arg0.getId()) {
case R.id.pop_under_button:
if(myButtonPopwindow.isShowing()){
myButtonPopwindow.dismiss();
}else{
myButtonPopwindow.showAsDropDown(pop_under_button);//popwindow放在pop_under_button下面
}
break;
case R.id.bottom_popwindow:
if(myPopWindowBottomShow.isShowing()){
myPopWindowBottomShow.dismiss();
}else{
// myPopWindowBottomShow.showAsDropDown(bottom_popwindow);//popwindow放在子控件bottom_popwindow下面Ps:如果手机有虚拟按键的话popwindow将显示不完全(这个问题困扰了博主很久很久,希望你不要走弯路)
myPopWindowBottomShow.showAtLocation(MainActivity.this.findViewById(R.id.main), Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL, 0, 0);//这种方式无论有虚拟按键还是没有都可完全显示,因为它显示的在整个父布局中
}
break;
}
}
class PoPUnderListener implements MyPopWindowListener{//实现按钮下的接口
@Override
public void firstItem() {
Toast.makeText(MainActivity.this, "左边按钮", Toast.LENGTH_SHORT).show();
}
@Override
public void secondItem() {
Toast.makeText(MainActivity.this, "右边按钮", Toast.LENGTH_SHORT).show();
}
}
class BottomPopWindow implements MyPopWindowListener{//实现底部弹出的接口
@Override
public void firstItem() {
Toast.makeText(MainActivity.this, "上边按钮", Toast.LENGTH_SHORT).show();
}
@Override
public void secondItem() {
Toast.makeText(MainActivity.this, "下边按钮", Toast.LENGTH_SHORT).show();
}
}
}
二、MyButtonPopwindow类实现按钮下显示PopWindow:
package com.example.mypopwindowdemo;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.PopupWindow;
/**
* Created by Administrator on 2015/8/12.
*/
public class MyButtonPopwindow extends PopupWindow implements View.OnClickListener{
private Button album;
private Button take_photo;
private LayoutInflater layoutInflater;
private int layoutId;
private Context context;
private View view;
private MyPopWindowListener popWindowChooseOnlyListener;
public MyButtonPopwindow(Context context,int layoutId,MyPopWindowListener popWindowChooseOnlyListener){
this.context = context;
layoutInflater = LayoutInflater.from(context);
this.layoutId = layoutId;
this.popWindowChooseOnlyListener = popWindowChooseOnlyListener;
init();
}
private void init() {
view = layoutInflater.inflate(layoutId,null);//加载布局文件
// album = (Button) view.findViewById(R.id.left);
// take_photo = (Button) view.findViewById(R.id.right);
setContentView(view);
DisplayMetrics dm=new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(dm);
setWidth(dm.widthPixels * 2 / 3);
setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
// album.setOnClickListener(this);
// take_photo.setOnClickListener(this);
setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
setFocusable(true);
setOutsideTouchable(true);
}
@Override
public void onClick(View v) {//注释掉,是因为想在该对象外面注册按钮监听器
// switch (v.getId()){
// case R.id.left:
// popWindowChooseOnlyListener.firstItem();
// dismiss();
// break;
// case R.id.right:
// popWindowChooseOnlyListener.secondItem();
// dismiss();
// break;
//
// }
}
public View getPopWindowView() {
// TODO Auto-generated method stub
return view;
}
}
三、MyPopWindowBottomShow类,实现底部显示的的PopWindow:
package com.example.mypopwindowdemo;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.PopupWindow;
public class MyPopWindowBottomShow extends PopupWindow implements OnClickListener{
private LayoutInflater layoutInflater;
private MyPopWindowListener myPopWindowListener;
private View popView;
private Button firstButton;
private Button secondButton;
public MyPopWindowBottomShow(Context context,MyPopWindowListener myPopWindowListener){
this.myPopWindowListener = myPopWindowListener;
this.layoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
init();
}
private void init(){
popView = layoutInflater.inflate(R.layout.bottom_pop_window, null);
firstButton = (Button) popView.findViewById(R.id.on);
secondButton = (Button) popView.findViewById(R.id.under);
firstButton.setOnClickListener(this);
secondButton.setOnClickListener(this);
//把View添加到PopWindow中
this.setContentView(popView);
//设置SelectPicPopupWindow弹出窗体的宽
this.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
//设置SelectPicPopupWindow弹出窗体的高
this.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
//设置SelectPicPopupWindow弹出窗体可点击
this.setFocusable(true);
//设置SelectPicPopupWindow弹出窗体动画效果
this.setAnimationStyle(R.style.BottomPopWindowAnimation);
// this.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));//实例化一个ColorDrawable颜色为透明
//实例化一个ColorDrawable颜色为半透明
ColorDrawable dw = new ColorDrawable(0xb0000000);
//设置SelectPicPopupWindow弹出窗体的背景
this.setBackgroundDrawable(dw);
popView.setOnTouchListener(new OnTouchListener() {//设置背景区域外为点击消失popwindow
public boolean onTouch(View v, MotionEvent event) {
int height = popView.findViewById(R.id.pop_layout).getTop();
int y=(int) event.getY();
if(event.getAction()==MotionEvent.ACTION_UP){
if(yreturn true;
}
});
}
@Override
public void onClick(View arg0) {
switch (arg0.getId()) {
case R.id.on:
myPopWindowListener.firstItem();
break;
case R.id.under:
dismiss();
myPopWindowListener.secondItem();
break;
}
}
}
四、MyPopWindowListener接口:
package com.example.mypopwindowdemo;
public interface MyPopWindowListener {
public void firstItem();//第一个按钮按下时
public void secondItem();//第二个按钮按下时
}
下面就来真机运行图:
3、无背景色的下滑出PopWindow(在代码中已经注释掉,要不要,看个人喜好):
好了主要代码和图片就这些。
更多博主文章分享:
继承与View在画布上画出贪吃蛇贪吃蛇android源码分享
手机弹幕实现
PopWindow源码下载