PopupWindow


官方文檔對(duì)該控件的描述是:“一個(gè)彈出窗口控件,可以用來(lái)顯示任意視圖(View),而且會(huì)浮動(dòng)在當(dāng)前活動(dòng)(activity)的頂部”。PopupWindow可以讓我們實(shí)現(xiàn)多種自定義控件,例如:menu、alertdialog等彈窗似的View。

  • 改變PopupWindow的視圖內(nèi)容
    可以通過(guò)setContentView來(lái)改變popup的顯示內(nèi)容,也可以用來(lái)初始化PopupWindow的View,比如使用構(gòu)造函數(shù)public PopupWindow (Context context)獲得的Popupwindow就只能用setContentView來(lái)設(shè)置內(nèi)容。
PopupWindow popupWindow = new PopupWindow(context);
popupWindow.setContentView(contentview);
  • 獲得PopupWindow的視圖內(nèi)容
public View getContentView()
  • 顯示PopupWindow

    • showAsDropDown(View anchor):相對(duì)某個(gè)控件的位置(正左下方),無(wú)偏移
    • showAsDropDown(View anchor, int xoff, int yoff):相對(duì)某個(gè)控件的位置,有偏移
    • showAtLocation(View parent, int gravity, int x, int y):相對(duì)于父控件的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以設(shè)置偏移或無(wú)偏移
  • 有兩種方法設(shè)置PopupWindow的大?。?/strong>

    • 調(diào)用有寬高參數(shù)的構(gòu)造函數(shù):
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View contentview = inflater.inflate(R.layout.popup_process, null);
PopupWindow popupWindow = new PopupWindow(contentview,LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
  • 通過(guò)setWidth和setHeight設(shè)置
PopupWindow popupWindow = new PopupWindow(contentview);
popupWindow.setWidth(LayoutParams.WRAP_CONTENT);           
popupWindow.setHeight(LayoutParams.WRAP_CONTENT);
  • PopUpWindow的焦點(diǎn):
    一般情況下setFocusable(true);
    其他任何事件的響應(yīng)都必須發(fā)生在PopupWindow消失之后, (home 等系統(tǒng)層面的事件除外)。比如這樣一個(gè)PopupWindow出現(xiàn)的時(shí)候,按back鍵首先是讓PopupWindow消失,第二次按才是退出activity,準(zhǔn)確的說(shuō)是想退出activity你得首先讓PopupWindow消失,因?yàn)椴徊⑹侨魏吻闆r下按back PopupWindow都會(huì)消失,必須在PopupWindow設(shè)置了背景的情況下 。

  • 點(diǎn)擊空白處的時(shí)候讓PopupWindow消失
    要讓點(diǎn)擊PopupWindow之外的地方PopupWindow消失你需要調(diào)用setBackgroundDrawable(new BitmapDrawable());
    設(shè)置背景,為了不影響樣式,這個(gè)背景是空的。還可以這樣寫,覺(jué)得這樣要保險(xiǎn)些:

setBackgroundDrawable(new ColorDrawable(0x00000000));

背景不為空但是完全透明。如此設(shè)置還能讓PopupWindow在點(diǎn)擊back的時(shí)候消失。


示例:
彈出框布局title_popupwindow.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="wrap_content"  
    android:layout_height="wrap_content">  
  
    <ListView  
        android:id="@+id/popupwindow"  
        android:background="@drawable/title_background"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:divider="@drawable/title_background_line"  
        android:listSelector="@drawable/title_background_pressed"  //選中的時(shí)候背景圖片
        android:cacheColorHint="@android:color/transparent">  //去除listview的拖動(dòng)背景色
    </ListView>  
</RelativeLayout>  

彈出框的item的布局popupwindow_item.xml

<?xml version="1.0" encoding="utf-8"?>  
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="fill_parent"  
    android:layout_height="wrap_content"  
    android:padding="8.0dip" >  
  
    <TextView  
        android:id="@+id/popup_item"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:textStyle="bold"  
        android:singleLine="true"  
        android:ellipsize="end"  
        android:textColor="#ffffffff"/>  
  
</RelativeLayout>  

寫一個(gè)PopupWindow的派生類MyPopupWindow

public class MyPopupWindow extends PopupWindow {  
    /** 
     * 上下文對(duì)象 
     */  
    private Context mContext;  
    /** 
     * 回調(diào)接口對(duì)象 
     */  
    private OnPopupWindowClickListener listener;  
    /** 
     * ArrayAdapter對(duì)象 
     */  
    private ArrayAdapter adapter;  
    /** 
     * ListView的數(shù)據(jù)源 
     */  
    private List<String> list = new ArrayList<String>();  
    /** 
     * PopupWindow的寬度 
     */  
    private int width = 0;  
  
    public MyPopupWindow(Context context){  
        super(context);   
        mContext = context;  
        initView();  
    }  
      
    private void initView(){  
        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
        View popupView = inflater.inflate(R.layout.title_popupwindow, null);  
        // 設(shè)置MyPopupWindow的View  
        this.setContentView(popupView);  
          
        //設(shè)置寬度,若沒(méi)有設(shè)置寬度為L(zhǎng)ayoutParams.WRAP_CONTENT  
        this.setWidth(250);    
        this.setHeight(LayoutParams.WRAP_CONTENT);  
          
        //設(shè)置動(dòng)畫  
        this.setAnimationStyle(R.style.popupwindow_animation);  
          
        //設(shè)置ListView點(diǎn)擊響應(yīng)
        this.setFocusable(true);  
        // 實(shí)例化一個(gè)ColorDrawable顏色為半透明,點(diǎn)back鍵和其他地方使其消失
        this.setBackgroundDrawable(new ColorDrawable(0x00000000));   
        this.setOutsideTouchable(true);  
              
        ListView listView = (ListView) popupView.findViewById(R.id.popupwindow);  
        adapter = new ArrayAdapter(mContext, R.layout.popupwindow_item, R.id.popup_item, list);  
        listView.setAdapter(adapter);  
          
        //ListView的點(diǎn)擊事件  
        listView.setOnItemClickListener(new OnItemClickListener() {  
  
            @Override  
            public void onItemClick(AdapterView<?> parent, View view,  
                    int position, long id) {  
                MyPopupWindow.this.dismiss();  //點(diǎn)擊選項(xiàng)后,popupwindow消失
                if(listener != null){  
                    listener.onPopupWindowItemClick(position);  
                }  
            }  
        });  
          
    }  
      
    /** 
     * 為MyPopupWindow設(shè)置回調(diào)接口 
     * @param listener 
     */  
    public void setOnPopupWindowClickListener(OnPopupWindowClickListener listener){  
        this.listener = listener;  
    }  
      
  
    /** 
     * 設(shè)置數(shù)據(jù)的方法,供外部調(diào)用 
     * @param mList 
     */  
    public void changeData(List<String> mList) {  
        //這里用addAll也很重要,如果用this.list = mList,調(diào)用notifyDataSetChanged()無(wú)效  
        //notifyDataSetChanged()數(shù)據(jù)源發(fā)生改變的時(shí)候調(diào)用的,this.list = mList,list并沒(méi)有發(fā)生改變  
        list.addAll(mList);  
        adapter.notifyDataSetChanged();  
    }  
      
      
    /** 
     * 回調(diào)接口.供外部調(diào)用 
     */  
    public interface OnPopupWindowClickListener{  
        /** 
         * 當(dāng)點(diǎn)擊PopupWindow的ListView 的item的時(shí)候調(diào)用此方法,用回調(diào)方法的好處就是降低耦合性 
         * @param position 位置 
         */  
        void onPopupWindowItemClick(int position);  
    }    
}  

用到了兩個(gè)動(dòng)畫,在res文件夾下創(chuàng)建anim文件夾,里面創(chuàng)建兩個(gè)動(dòng)畫xml
popupwindow_enter.xml

<?xml version="1.0" encoding="UTF-8"?>    
<set xmlns:android="http://schemas.android.com/apk/res/android">    
    <translate     
        android:fromXDelta="100%p"    
        android:toXDelta="0"    //這兩行是從右邊進(jìn)
        android:duration="500"/>    
</set>   

popupwindow_exit.xml

<?xml version="1.0" encoding="utf-8"?>  
<set xmlns:android="http://schemas.android.com/apk/res/android">  
    <translate   
        android:fromXDelta="0"  
        android:toXDelta="100%p"  //這兩行是往右邊消失
        android:duration="500"/>  
</set>  

在styles.xml里添加

 <style name="popupwindow_animation">  
        <item name="android:windowEnterAnimation">@anim/popupwindow_enter</item>  
        <item name="android:windowExitAnimation">@anim/popupwindow_exit</item>  
    </style>  

調(diào)用MyPopupWindow

public class PopupActivity extends AppcompatActivity {  
    MyPopupWindow mPopupWindow;  
    String [] items = {"刷新列表", "修改密碼", "系統(tǒng)設(shè)置", "添加用戶", "關(guān)于"};  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
          
        Button mButton = (Button) findViewById(R.id.button1);  
        mButton.setOnClickListener(new OnClickListener() {  
              
            @Override  
            public void onClick(View view) {  
                mPopupWindow.showAsDropDown(view);  
            }  
        });  
          
        mPopupWindow= new MyPopupWindow(this);  
        mPopupWindow.changeData(Arrays.asList(items));  
        mPopupWindow.setOnPopupWindowClickListener(new OnPopupWindowClickListener() {  
              
            @Override  
            public void onPopupWindowItemClick(int position) {  
                //需要實(shí)現(xiàn)的功能
                Toast.makeText(getApplication(), items[position], Toast.LENGTH_SHORT).show();  
            }  
        });  
    }  
  
  
}  

代碼中的回調(diào)機(jī)制:

回調(diào)機(jī)制.png

注:

android:fromXDelta="0" android:toXDelta="-100%p" 往左邊消失
android:fromXDelta="-100%p" android:toXDelta="0" 從左邊進(jìn)
android:fromXDelta="0" android:toXDelta="100%p" 往右邊消失
android:fromXDelta="100%p" android:toXDelta="0" 從右邊進(jìn)

fromXDelta,fromYDelta 起始時(shí)X,Y座標(biāo),屏幕右下角的座標(biāo)是X:320,Y:480
toXDelta, toYDelta 動(dòng)畫結(jié)束時(shí)X,Y的座標(biāo)
interpolator 指定動(dòng)畫插入器
常見(jiàn)的有加速減速插入器 accelerate_decelerate_interpolator
加速插入器 accelerate_interpolator,
減速插入器 decelerate_interpolator。
fromXScale,fromYScale, 動(dòng)畫開(kāi)始前X,Y的縮放,0.0為不顯示, 1.0為正常大小
toXScale,toYScale, 動(dòng)畫最終縮放的倍數(shù), 1.0為正常大小,大于1.0放大
pivotX, pivotY 動(dòng)畫起始位置,相對(duì)于屏幕的百分比,兩個(gè)都為50%表示動(dòng)畫從屏幕中間開(kāi)始
startOffset, 動(dòng)畫多次執(zhí)行的間隔時(shí)間,如果只執(zhí)行一次,執(zhí)行前會(huì)暫停這段時(shí)間,單位毫秒 duration,一次動(dòng)畫效果消耗的時(shí)間,單位毫秒,值越小動(dòng)畫速度越快 repeatCount,動(dòng)畫重復(fù)的計(jì)數(shù),動(dòng)畫將會(huì)執(zhí)行該值+1次
repeatMode,動(dòng)畫重復(fù)的模式,reverse為反向,當(dāng)?shù)谂即螆?zhí)行時(shí),動(dòng)畫方向會(huì)相反。
restart為重新執(zhí)行,方向不變

參考:
PopupWindow的使用以及ArrayAdatper.notifyDataSetChanged()無(wú)效詳解
Android-自定義PopupWindow

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容