在案頭添加可拖動/點擊的懸浮視窗

來源:互聯網
上載者:User

用過新版本android 360手機小幫手都人都對 360中只在案頭顯示一個小小懸浮視窗羨慕不已吧?

其實實現這種功能,主要有兩步

1.判斷當前顯示的是為案頭。這個內容我在前面的文章裡面已經有過介紹,如果還沒看過的趕快穩步看一下哦。

           【Kris專題】判斷當前顯示是否為案頭

2.使用windowManager往最頂層添加一個View .這個知識點就是為本文主要講解的內容哦。在本文的講解中,我們還會講到下面的知識點:

  a.如果擷取到狀態列的高度

  b.懸浮視窗的拖動

  c.懸浮視窗的點擊事件

有開始之前,我們先來看一下:

接下來我們來看看FloatView的代碼:

/** *  * @author <a href="mailto:kris@krislq.com">Kris.lee</a> * @website <a href="\"http://www.krislq.com\"" target="\"_blank\"">www.krislq.com</a> * @date Nov 29, 2012 * @version 1.0.0 * */public class FloatView extends ImageView{        private float mTouchX;        private float mTouchY;        private float x;        private float y;        private float mStartX;        private float mStartY;        private OnClickListener mClickListener;         private WindowManager windowManager = (WindowManager) getContext()                        .getApplicationContext().getSystemService(Context.WINDOW_SERVICE);        // 此windowManagerParams變數為擷取的全域變數,用以儲存懸浮視窗的屬性        private WindowManager.LayoutParams windowManagerParams = ((FloatApplication) getContext()                        .getApplicationContext()).getWindowParams();         public FloatView(Context context) {                super(context);        }         @Override        public boolean onTouchEvent(MotionEvent event) {                //擷取到狀態列的高度                Rect frame =  new  Rect();                  getWindowVisibleDisplayFrame(frame);                int  statusBarHeight = frame.top;                 System.out.println("statusBarHeight:"+statusBarHeight);                // 擷取相對螢幕的座標,即以螢幕左上方為原點                x = event.getRawX();                y = event.getRawY() - statusBarHeight; // statusBarHeight是系統狀態列的高度                Log.i("tag", "currX" + x + "====currY" + y);                switch (event.getAction()) {                case MotionEvent.ACTION_DOWN: // 捕獲手指觸摸按下動作                        // 擷取相對View的座標,即以此View左上方為原點                        mTouchX = event.getX();                        mTouchY = event.getY();                        mStartX = x;                        mStartY = y;                        Log.i("tag", "startX" + mTouchX + "====startY"                                        + mTouchY);                        break;                 case MotionEvent.ACTION_MOVE: // 捕獲手指觸摸移動動作                        updateViewPosition();                        break;                 case MotionEvent.ACTION_UP: // 捕獲手指觸摸離開動作                        updateViewPosition();                        mTouchX = mTouchY = 0;                        if ((x - mStartX) < 5 && (y - mStartY) < 5) {                                if(mClickListener!=null) {                                        mClickListener.onClick(this);                                }                        }                        break;                }                return true;        }        @Override        public void setOnClickListener(OnClickListener l) {                this.mClickListener = l;        }        private void updateViewPosition() {                // 更新浮動視窗位置參數                windowManagerParams.x = (int) (x - mTouchX);                windowManagerParams.y = (int) (y - mTouchY);                windowManager.updateViewLayout(this, windowManagerParams); // 重新整理顯示        }}

代碼解釋:

  自訂application的目的是為了儲存windowParams的值 ,因為我們在拖動懸浮視窗的時候,如果每次都重新new一個layoutParams的話,在update 的時候會在異常發現。
  windowParams的值也不一定非得在自訂application裡面來儲存,只要是全域的都行。

最後我們再來看看Activity中的實現。

/** *  * @author <a href="mailto:kris@krislq.com">Kris.lee</a> * @website <a href="\"http://www.krislq.com\"" target="\"_blank\"">www.krislq.com</a> * @date Nov 29, 2012 * @version 1.0.0 * */public class MainActivity extends Activity  implements OnClickListener{        private WindowManager windowManager = null;        private WindowManager.LayoutParams windowManagerParams = null;        private FloatView floatView = null;         @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        requestWindowFeature(Window.FEATURE_NO_TITLE);//取消標題列        getWindow().setFlags(WindowManager.LayoutParams. FLAG_FULLSCREEN ,                      WindowManager.LayoutParams. FLAG_FULLSCREEN);//全屏        setContentView(R.layout.activity_main);               createView();     }         @Override        public boolean onCreateOptionsMenu(Menu menu) {                getMenuInflater().inflate(R.menu.activity_main, menu);                return true;        }         public void onDestroy() {                super.onDestroy();                // 在程式退出(Activity銷毀)時銷毀懸浮視窗                windowManager.removeView(floatView);        }         private void createView() {                floatView = new FloatView(getApplicationContext());                floatView.setOnClickListener(this);                floatView.setImageResource(R.drawable.ic_launcher); // 這裡簡單的用內建的icon來做示範                // 擷取WindowManager                windowManager = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);                // 設定LayoutParams(全域變數)相關參數                windowManagerParams = ((FloatApplication) getApplication()).getWindowParams();                 windowManagerParams.type = LayoutParams.TYPE_PHONE; // 設定window type                windowManagerParams.format = PixelFormat.RGBA_8888; // 設定圖片格式,效果為背景透明                // 設定Window flag                windowManagerParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL                                | LayoutParams.FLAG_NOT_FOCUSABLE;                /*                 * 注意,flag的值可以為:                 * LayoutParams.FLAG_NOT_TOUCH_MODAL 不影響後面的事件                 * LayoutParams.FLAG_NOT_FOCUSABLE  不可聚焦                 * LayoutParams.FLAG_NOT_TOUCHABLE 不可觸摸                 */                // 調整懸浮視窗至左上方,便於調整座標                windowManagerParams.gravity = Gravity.LEFT | Gravity.TOP;                 // 以螢幕左上方為原點,設定x、y初始值                windowManagerParams.x = 0;                windowManagerParams.y = 0;                // 設定懸浮視窗長寬資料                windowManagerParams.width = LayoutParams.WRAP_CONTENT;                windowManagerParams.height = LayoutParams.WRAP_CONTENT;                // 顯示myFloatView映像                windowManager.addView(floatView, windowManagerParams);        }         public void onClick(View v) {                Toast.makeText(this, "Clicked", Toast.LENGTH_SHORT).show();        }}

代碼解釋:

        在activity中我們主要是添加懸浮窗,並且設定他的位置。另外需要注意flags的應用:

                LayoutParams.FLAG_NOT_TOUCH_MODAL 不影響後面的事件

                LayoutParams.FLAG_NOT_FOCUSABLE  不可聚焦

                LayoutParams.FLAG_NOT_TOUCHABLE 不可觸摸

               

        最後我們在onDestroy()中移除到懸浮視窗。所以,我們測試的時候,記得按Home鍵來切換到案頭。

        

    最後千萬記得,在androidManifest.xml中來申明我們需要用到的android.permission.SYSTEM_ALERT_WINDOW許可權

並且記得申明我們自訂的application哦。

AndroidManifest.xml代碼如下:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.krislq.floating"    android:versionCode="1"    android:versionName="1.0" >     <uses-sdk        android:minSdkVersion="8"        android:targetSdkVersion="15" />        <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />    <application        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" android:name="FloatApplication">        <activity            android:name=".MainActivity"            android:label="@string/title_activity_main" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                 <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application></manifest>

原文:http://www.eoeandroid.com/thread-233373-1-1.html

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.