關於PopupWindow的showAsDropDown()和showAtLocation()使用方式,popupWindow的各種彈出
阿新 • • 發佈:2019-02-20
package com.example.lainanzhou.popupwindoewlocation; import android.app.Activity; import android.graphics.drawable.BitmapDrawable; import android.os.Bundle; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.Interpolator; import android.view.animation.ScaleAnimation; import android.widget.Button; import android.widget.PopupWindow; import android.widget.RelativeLayout; import android.widget.TextView; /** * Android的對話方塊有兩種:PopupWindow和AlertDialog。它們的不同點在於: * ?AlertDialog的位置固定,而PopupWindow的位置可以隨意 * ?AlertDialog是非阻塞執行緒的,而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等),可以設定偏移或無偏移 */ public class MainActivity extends Activity implements View.OnClickListener { private TextView mTv; private TextView mMainView; private RelativeLayout mRl_parent; private PopupWindow mPopupWindow; private int mWidth; private boolean mIsClick5; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTv = (TextView) findViewById(R.id.tv); mMainView = (TextView) findViewById(R.id.tv_mainView); mRl_parent = (RelativeLayout) findViewById(R.id.rl_parent); Button mButton01 = (Button) findViewById(R.id.button01); Button mButton02 = (Button) findViewById(R.id.button02); Button mButton03 = (Button) findViewById(R.id.button03); Button mButton04 = (Button) findViewById(R.id.button04); Button mButton05 = (Button) findViewById(R.id.button05); mButton01.setOnClickListener(this); mButton02.setOnClickListener(this); mButton03.setOnClickListener(this); mButton04.setOnClickListener(this); mButton05.setOnClickListener(this); } /** * 根據型別設定顯示的popupWindow方式 * * @param type 1.為直接顯示在某控制元件下方+點選外部不可關閉 * 2.顯示在某控制元件下方+點選外部可關閉 * 3.相對父容器中心顯示位置+點選外部可關閉 * 4.相對父容器腳部顯示位置+點選外部可關閉 * 5.預設點選外部可關閉 */ private void initPopupWindow(int type) { LayoutInflater layoutInflater = LayoutInflater.from(this); View popupWindow = layoutInflater.inflate(R.layout.popup_window, null); //mode共有三種情況,取值分別為MeasureSpec.UNSPECIFIED, MeasureSpec.EXACTLY, MeasureSpec.AT_MOST。 // MeasureSpec.EXACTLY是(完全)精確尺寸,父元素決定自元素的確切大小,子元素將被限定在給定的邊界裡而忽略它本身大小; // 當我們將控制元件的layout_width或layout_height指定為具體數值時 // 如andorid:layout_width="50dip",或者為FILL_PARENT是,都是控制元件大小已經確定的情況,都是精確尺寸。 // MeasureSpec.AT_MOST是(至多)最大尺寸,當控制元件的layout_width或layout_height指定為WRAP_CONTENT時, // 控制元件大小一般隨著控制元件的子空間或內容進行變化,此時控制元件尺寸只要不超過父控制元件允許的最大尺寸即可。 // 因此,此時的mode是AT_MOST,size給出了父控制元件允許的最大尺寸。 // MeasureSpec.UNSPECIFIED是未指定尺寸,父元素不對子元素施加任何束縛,子元素可以得到任意想要的大小; // 這種情況不多,一般都是父控制元件是AdapterView,通過measure方法傳入的模式。 //以下方式是為了在popupWindow還沒有彈出顯示之前就測量獲取其寬高(單位是px相熟)~只能UNSPECIFIED模式下測量 int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); TextView mTextView = (TextView) popupWindow.findViewById(R.id.tv_popupTv); mTextView.measure(w, h); mWidth = mTextView.getMeasuredWidth();//獲取測量寬度px int mHeight = mTextView.getMeasuredHeight();//獲取測量高度px //設定點選popupWindow裡面文字可以dismiss該popupWindow popupWindow.findViewById(R.id.tv_popupTv).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mPopupWindow != null && mPopupWindow.isShowing()) { mPopupWindow.dismiss(); } } }); // 建立一個PopupWindow // 引數1:contentView 指定PopupWindow的顯示View // 引數2:width 指定PopupWindow的width可以固定死某些數值: // 如果不想固定死可以設定為ViewGroup.LayoutParams.WRAP_CONTENT/MATCH_CONTENT // 引數3:height 指定PopupWindow的height mPopupWindow = new PopupWindow(popupWindow, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); //設定動畫兩種方式:動畫效果可以參考該網址 http://blog.csdn.net/xiaanming/article/details/8997260 //方式1:xml配置檔案 // mPopupWindow.setAnimationStyle(R.anim.popupwindow_enter); //方式2:直接設定該popupWindow中的View的動畫 // setPopupAnimation(popupWindow); mPopupWindow.setFocusable(true); //這裡很重要,設定該popupWindow可以獲取焦點,不然無法響應點選事件 switch (type) { case 1: //方式2:直接設定該popupWindow中的View的動畫 setPopupAnimation(popupWindow); //6.0無效 mPopupWindow.setOutsideTouchable(false);//設定點選外面不可以消失~注意該效果在設定背景的情況下是無效的 break; case 2: //方式1:xml配置檔案 mPopupWindow.setAnimationStyle(R.anim.popupwindow_enter); mPopupWindow.setBackgroundDrawable(new BitmapDrawable()); mPopupWindow.setOutsideTouchable(true);//設定點選外面可以消失~注意則必須要設定該popupWindow背景才有效 break; case 3: //方式2:直接設定該popupWindow中的View的動畫 setPopupAnimation(popupWindow); //6.0無效 mPopupWindow.setOutsideTouchable(false);//設定點選外面不可以消失~注意該效果在設定背景的情況下是無效的 break; case 4: //方式1:xml配置檔案 mPopupWindow.setAnimationStyle(R.anim.popupwindow_enter); mPopupWindow.setBackgroundDrawable(new BitmapDrawable()); mPopupWindow.setOutsideTouchable(true);//設定點選外面可以消失~注意則必須要設定該popupWindow背景才有效 break; case 5: mMainView.setVisibility(mIsClick5 ? View.VISIBLE : View.GONE); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, dip2px(48)); mMainView.measure(w, h); int mMainViewWidth = mMainView.getMeasuredWidth();//獲取測量寬度px int width = (mTv.getWidth() - mMainViewWidth) / 2;//獲取x軸偏移量px params.setMargins(mTv.getLeft() + width, mTv.getHeight(), 0, 0); mMainView.setLayoutParams(params);//設定位置 if (mIsClick5) mMainView.setAnimation(getAnimation());//設定動畫 break; default: //方式1:xml配置檔案 mPopupWindow.setAnimationStyle(R.anim.popupwindow_enter); mPopupWindow.setBackgroundDrawable(new BitmapDrawable()); mPopupWindow.setOutsideTouchable(true);//設定點選外面可以消失~注意則必須要設定該popupWindow背景才有效 break; } } /** * 動畫效果 * * @return */ public Animation getAnimation() { AlphaAnimation localAlphaAnimation = new AlphaAnimation(0.0F, 1.0F); localAlphaAnimation.setInterpolator(new Interpolator() { public float getInterpolation(float paramFloat) { return 10.0F * paramFloat; } }); localAlphaAnimation.setDuration(500L); ScaleAnimation localScaleAnimation = new ScaleAnimation(0.0F, 1.0F, 0.0F, 1.0F, 1, 0.5F, -1, 0.0F); localScaleAnimation.setDuration(500L); AnimationSet localAnimationSet = new AnimationSet(true); localAnimationSet.addAnimation(localScaleAnimation); localAnimationSet.addAnimation(localAlphaAnimation); return localAnimationSet; } /** * 設定組合動畫 * * @param paramView */ private void setPopupAnimation(View paramView) { //透明度動畫 AlphaAnimation localAlphaAnimation = new AlphaAnimation(0.0F, 1.0F); localAlphaAnimation.setInterpolator(new Interpolator() { public float getInterpolation(float paramFloat) { return 10.0F * paramFloat; } }); localAlphaAnimation.setDuration(800L);//動畫持續時長 //縮放動畫: // 引數: // 1.為x軸起始縮放度 2.為x結束縮放度 // 3.為y起始縮放度 4.為y結束縮放度 // 5.為相對x軸型別為頂部 6.為該型別上起始度(0.5f為中間位置) // 7.為相對y軸型別 8.為該型別起始位置(0F為原位置) ScaleAnimation localScaleAnimation = new ScaleAnimation(0F, 1.0F, 0F, 1.0F, Animation.ZORDER_TOP, 0.5F, Animation.ZORDER_TOP, 0F); localScaleAnimation.setDuration(500L);//動畫持續時長 AnimationSet localAnimationSet = new AnimationSet(true); localAnimationSet.addAnimation(localScaleAnimation); localAnimationSet.addAnimation(localAlphaAnimation); paramView.startAnimation(localAnimationSet); } /** * dip與px之間轉換 * * @param dipValue * @return */ private int dip2px(float dipValue) { final float scale = getResources().getDisplayMetrics().density; return (int) (dipValue * scale + 0.5f); } private int px2dip(float pxValue) { final float scale = getResources().getDisplayMetrics().density; return (int) (pxValue / scale + 0.5f); } @Override public void onClick(View v) { switch (v.getId()) { // 相對某個控制元件的位置(正左下方),無偏移 case R.id.button01: initPopupWindow(1); mPopupWindow.showAsDropDown(mTv); break; // 相對某個控制元件的位置(正左下方),有偏移 case R.id.button02: initPopupWindow(2); //以下為分步介紹控制元件獲取中間位置偏移量方式:(對應控制元件寬度-popup寬度)/2 int tv_width = mTv.getWidth();//獲取對應的控制元件view寬度px值 int popup_width = dip2px(120);//將popupWindow寬度轉為px值(這裡的popup寬度是寫死了的) int width = (tv_width - mWidth) / 2;//獲取x軸偏移量px mPopupWindow.showAsDropDown(mTv, width, 0);//設定x軸偏移量:注意單位為px break; // 相對於父控制元件的位置,無偏移~引數1為父容器~引數2為相對父容器相對型別~引數34為偏移量 case R.id.button03: initPopupWindow(3); //int[] locaitons = new int[2];//存放相應控制元件在螢幕的xy軸座標點;單位px //mTv.getLocationOnScreen(locaitons);//locaitons[0]為x軸 locaitons[1]為y軸 // X、Y方向偏移量:設定x軸偏移量為相應控制元件中心;y軸無偏移 mPopupWindow.showAtLocation(mRl_parent, Gravity.CENTER, 0, 0); break; // 相對於父控制元件的位置,有偏移~引數1為父容器~引數2為相對父容器相對型別~引數34為偏移量 case R.id.button04: initPopupWindow(4); mPopupWindow.showAtLocation(mRl_parent, Gravity.BOTTOM, 0, 0); break; case R.id.button05: mIsClick5 = !mIsClick5; initPopupWindow(5); break; default: break; } } }
2.activity_main.xml部分
<RelativeLayout android:id="@+id/rl_parent" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:gravity="center" android:text="popupwindow相對該view顯示位置"/> <TextView android:id="@+id/tv_mainView" android:layout_width="wrap_content" android:layout_height="48dp" android:gravity="center" android:text="我是MainView" android:textColor="#333333" android:background="#dddddd" android:visibility="gone"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="18dp" android:orientation="vertical"> <Button android:id="@+id/button01" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="直接顯示在某控制元件下方,不偏移且點選外面不可關閉"/> <Button android:id="@+id/button02" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="顯示在某控制元件下方,有偏移且點選外面可關閉"/> <Button android:id="@+id/button03" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="相對父容器中心顯示位置,不偏移且點選外面不可關閉"/> <Button android:id="@+id/button04" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="相對父容器腳部顯示位置,下方中間且點選外面可關閉"/> <Button android:id="@+id/button05" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="直接使用view顯示,隨便設定彈出位置"/> </LinearLayout> </RelativeLayout>
3.popup_window.xml部分
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#dddddd" android:orientation="vertical"> <TextView android:id="@+id/tv_popupTv" android:layout_width="wrap_content" android:layout_height="48dp" android:layout_centerInParent="true" android:gravity="center" android:text="我是PopupWindow" android:textColor="#333333"/> </RelativeLayout>
4.popupwindow_enter.xml動畫xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!--位移動畫:1為持續時長;2為X軸起始位置;3為X軸到達位置 ~看需求還可以新增設定Y軸位置-->
<!--X軸相對左右方向,Y軸相對上下方向-->
<translate
android:duration="500"
android:fromYDelta="-100"
android:toYDelta="0"/>
</set>
轉載至:http://www.bozhiyue.com/anroid/boke/2016/0421/32970.html
原始碼下載地址 http://download.csdn.net/detail/lnn368/9495250