popupWindow 用法总结 控制位置

Posted 白乾涛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了popupWindow 用法总结 控制位置相关的知识,希望对你有一定的参考价值。

android中的dialog,以及activiy形式的dialog均是模态对话框,对话框不消失时,不能对其他页面进行操作,也就是其他页面不能获得焦点。PopupWindow是非模态对话框,对话框显示的时候,其他界面仍然可以获得焦点,仍然可以进行点击等操作,同时也可以对对话框进行点击等操作。 
很好的例子就是输入法,通过查看源码就可以看到,其界面是几个popupwindow组成的。

三个关键设置
// 如果不设置PopupWindow的背景,有些版本就会出现一个问题:无论是点击外部区域还是Back键都无法dismiss弹框
popupWindow.setBackgroundDrawable(new ColorDrawable());
// setOutsideTouchable设置生效的前提是setTouchable(true)和setFocusable(false)
popupWindow.setOutsideTouchable(true);
// 设置为true之后,PopupWindow内容区域 才可以响应点击事件
popupWindow.setTouchable(true);

Activity

public class MainActivity extends ListActivity {
    private PopupWindow pop;
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        String[] array = { "在指定view的正左下方,无偏移"//
                "相对指定view正左下方,有偏移",//
                "Gravity.NO_GRAVITY:相对屏幕左上角,注意包含状态栏区域",//
                "Gravity.TOP:相对屏幕正上方居中",//
                "pop不会偏移出屏幕,偏移值过大时取临界值",//
                "Gravity.BOTTOM:相对屏幕正下方居中,注意包含虚拟按键区域",//
                "Gravity.BOTTOM:此时yoff为正时表示向上偏移(而非向下偏移)",//
                "出现在View的任意位置"};
        setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1new ArrayList<String>(Arrays.asList(array))));
        pop = new PopupWindow(this);
        pop.setFocusable(true);//必备设置1
        pop.setBackgroundDrawable(new ColorDrawable(0x00ff0000));//必备设置2
        pop.setOutsideTouchable(true);//setFocusable(true)后这个设置就没用了
        pop.setAnimationStyle(R.style.popAniStyle);//设置动画所对应的style 
    }
    private boolean b;
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        b = !b;
        if (b) pop.setContentView(LayoutInflater.from(this).inflate(R.layout.view1null));
        else pop.setContentView(LayoutInflater.from(this).inflate(R.layout.view2null));
        switch (position) {
        case 0://在指定view的正左下方,无偏移
            pop.setWidth(LinearLayout.LayoutParams.WRAP_CONTENT);//必须设置宽和高
            pop.setHeight(LinearLayout.LayoutParams.WRAP_CONTENT);
            pop.showAsDropDown(v);
            break;
        case 1://相对指定view正左下方的位置,有偏移
            pop.setWidth(DensityUtils.getScreenWidth(this) - 20);
            pop.setHeight(LinearLayout.LayoutParams.WRAP_CONTENT);
            pop.showAsDropDown(v, 20, 10);
            break;
        case 2://相对于父控件的某个相对位置的偏移,默认的Gravity.NO_GRAVITY的参照物为【屏幕左上角】,注意包含状态栏区域
        case 3://若偏移值大于pop偏出屏幕的临界值,将取临界值。也即pop不可能会偏移出屏幕
        case 4://不管view设置的是哪一个,参照物都是整个屏幕的根布局
            pop.setWidth(DensityUtils.getScreenWidth(this) - 20);
            pop.setHeight(20);
            if (position == 2) pop.showAtLocation(v, Gravity.NO_GRAVITY, 20, DensityUtils.getStatusBarHeight(this) + 10);//Gravity.NO_GRAVITY:相对屏幕左上角
            else if (position == 3) pop.showAtLocation(v, Gravity.TOP, 10, DensityUtils.getStatusBarHeight(this) + 10);//Gravity.TOP:相对屏幕正上方居中
            else pop.showAtLocation(v, Gravity.TOP, 100, DensityUtils.getStatusBarHeight(this));//临界值为 20/2=10,偏移值大于10时仅偏移10
            break;
        case 5://Gravity.BOTTOM:相对屏幕正下方居中,注意包含虚拟按键区域,并且此时yoff为正时表示向上偏移(而非向下偏移)
        case 6://
            pop.setWidth(DensityUtils.getScreenWidth(this) - 20);
            pop.setHeight(LinearLayout.LayoutParams.WRAP_CONTENT);
            if (position == 5) pop.showAtLocation(v, Gravity.BOTTOM, 0, DensityUtils.getBottomBarHeight(this));//Gravity.BOTTOM:相对屏幕正下方居中
            else if (position == 6) pop.showAtLocation(v, Gravity.BOTTOM, -10, DensityUtils.getBottomBarHeight(this) + 10);//此时yoff为正时表示向上偏移
            break;
        case 7://
            startActivity(new Intent(this, SecondActivity.class));
            break;
        }
    }
}

Activity2

public class SecondActivity extends Activity {
    private int num = 0;
    private PopupWindow pop;
    private int[] location = new int[2];;
    private View contentView;
    @SuppressLint("InflateParams")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout);
        contentView = LayoutInflater.from(this).inflate(R.layout.view2null);
        pop = new PopupWindow(contentView, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        pop.setFocusable(true);//必备设置1
        pop.setBackgroundDrawable(new ColorDrawable(0x00ff0000));//必备设置2
        pop.setOutsideTouchable(true);//setFocusable(true)后这个设置就没用了
        pop.setAnimationStyle(R.style.popAniStyle);//设置动画所对应的style
    }
    public void onClick(View v) {
        v.getLocationOnScreen(location);// 获取锚点View在屏幕上的左上角坐标位置
        switch (num % 4) {
        case 0://右下
            pop.showAtLocation(v, Gravity.NO_GRAVITYlocation[0] + v.getWidth()location[1] + v.getHeight());
            break;
        case 1://右上
            pop.showAtLocation(v, Gravity.NO_GRAVITYlocation[0] + v.getWidth()location[1] - contentView.getHeight());
            break;
        case 2://左上
            pop.showAtLocation(v, Gravity.NO_GRAVITYlocation[0] - contentView.getWidth()location[1] - contentView.getHeight());
            break;
        default://左下
            pop.showAtLocation(v, Gravity.NO_GRAVITYlocation[0] - contentView.getWidth()location[1] + v.getHeight());
            break;
        }
        Toast.makeText(thisnum % 4 + "", Toast.LENGTH_SHORT).show();
        num++;
    }
}

工具类

public class DensityUtils {
    //******************************************************************************************
    //                                                                                    单位转换
    //******************************************************************************************
    /**像素密度*/
    public static float getDisplayMetrics(Context context) {
        return context.getResources().getDisplayMetrics().density;
    }
    /**  dp 转成为 px     */
    public static int dp2px(Context context, float dpValue) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, context.getResources().getDisplayMetrics());
    }
    /**  px 转成为 dp     */
    public static int px2dp(Context context, float pxValue) {
        return (int) (pxValue / getDisplayMetrics(context) + 0.5f);
    }
    /** sp转px */
    public static int sp2px(Context context, float spVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal, context.getResources().getDisplayMetrics());
    }
    /** px转sp */
    public static float px2sp(Context context, float pxVal) {
        return (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
    }
    //******************************************************************************************
    //                                                                                屏幕宽高
    //******************************************************************************************
    /**  获取屏幕宽  */
    public static int getScreenWidth(Context context) {
        DisplayMetrics metric = new DisplayMetrics();
        ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(metric);
        return metric.widthPixels;
    }
    /** 获取屏幕高,包含状态栏,但不包含虚拟按键,如1920屏幕只有1794  */
    public static int getScreenHeight(Context context) {
        DisplayMetrics metric = new DisplayMetrics();