国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 系統(tǒng) > Android > 正文

android實(shí)現(xiàn)可自由移動(dòng)、監(jiān)聽(tīng)點(diǎn)擊事件的懸浮窗

2019-10-21 21:34:02
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

最近因?yàn)轫?xiàng)目需要,自己實(shí)現(xiàn)了個(gè)可以自由移動(dòng),并且長(zhǎng)按可以跳出一個(gè)控制播放的,大的懸浮窗

好,開(kāi)始吧。首先我們先聊權(quán)限,懸浮窗需要在manifest中聲明一個(gè)權(quán)限:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

然后呢,嗯,我們來(lái)講講關(guān)于懸浮窗實(shí)現(xiàn)的原理。

在Andriod中,所有的界面元素都要通過(guò)windowmanger來(lái)實(shí)現(xiàn),像Activity、Fragment等等這些也是在其上實(shí)現(xiàn)。因此,我們的懸浮窗自然要通過(guò)這個(gè)實(shí)現(xiàn)。

這個(gè)項(xiàng)目中,我們自定義了兩個(gè)懸浮窗view。我們以其中一個(gè)比較簡(jiǎn)單的為例: 

我們自定義一個(gè)管理可以統(tǒng)一管理懸浮窗的類(lèi)MyWindowManager,負(fù)責(zé)創(chuàng)建,刪除懸浮窗

/** * Created by shiwe on 2017/3/7. * 懸浮窗管理 * 創(chuàng)建,移除 * 單例模式 */public class MyWindowManager { private FloatNormalView normalView; private FloatControlView controlView; private static MyWindowManager instance; private MyWindowManager() { } public static MyWindowManager getInstance() {  if (instance == null)   instance = new MyWindowManager();  return instance; } /**  * 創(chuàng)建小型懸浮窗  */ public void createNormalView(Context context) {  if (normalView == null)   normalView = new FloatNormalView(context); } /**  * 移除懸浮窗  *  * @param context  */ public void removeNormalView(Context context) {  if (normalView != null) {   WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);   windowManager.removeView(normalView);   normalView = null;  } } /**  * 創(chuàng)建小型懸浮窗  */ public void createControlView(Context context) {  if (controlView == null)   controlView = new FloatControlView(context); } /**  * 移除懸浮窗  *  * @param context  */ public void removeControlView(Context context) {  if (controlView != null) {   WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);   windowManager.removeView(controlView);   controlView = null;  } }}

然后看看我們自定義的一個(gè)view,其繼承自L(fǎng)inearLayout,我們?cè)趇nitLayoutParams初始化這個(gè)控件的位置等其他參數(shù);在initEvent方法中定義隨手指移動(dòng)的監(jiān)聽(tīng)事件以及長(zhǎng)按的監(jiān)聽(tīng)事件。

public class FloatNormalView extends LinearLayout { private Context context = null; private View view = null; private ImageView ivShowControlView = null; private WindowManager.LayoutParams lp = new WindowManager.LayoutParams(); private static WindowManager windowManager; private float mTouchStartX; private float mTouchStartY; private float x; private float y; private boolean initViewPlace = false; private MyWindowManager myWindowManager; private boolean isControlViewShowing = false; public FloatNormalView(Context context) {  super(context);  this.context = context;  myWindowManager = MyWindowManager.getInstance();  LayoutInflater.from(context).inflate(R.layout.float_normal_view, this);  view = findViewById(R.id.ll_float_normal);  ivShowControlView = (ImageView) findViewById(R.id.iv_show_control_view);  windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);  initLayoutParams();  initEvent(); } /**  * 初始化參數(shù)  */ private void initLayoutParams() {  //屏幕寬高  int screenWidth = windowManager.getDefaultDisplay().getWidth();  int screenHeight = windowManager.getDefaultDisplay().getHeight();  //總是出現(xiàn)在應(yīng)用程序窗口之上。  lp.type = WindowManager.LayoutParams.TYPE_PHONE;  // FLAG_NOT_TOUCH_MODAL不阻塞事件傳遞到后面的窗口  // FLAG_NOT_FOCUSABLE 懸浮窗口較小時(shí),后面的應(yīng)用圖標(biāo)由不可長(zhǎng)按變?yōu)榭砷L(zhǎng)按,不設(shè)置這個(gè)flag的話(huà),home頁(yè)的劃屏?xí)袉?wèn)題  lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;  //懸浮窗默認(rèn)顯示的位置  lp.gravity = Gravity.START | Gravity.TOP;  //指定位置  lp.x = screenWidth - view.getLayoutParams().width * 2;  lp.y = screenHeight / 2 + view.getLayoutParams().height * 2;  //懸浮窗的寬高  lp.width = WindowManager.LayoutParams.WRAP_CONTENT;  lp.height = WindowManager.LayoutParams.WRAP_CONTENT;  lp.format = PixelFormat.TRANSPARENT;  windowManager.addView(this, lp); } /**  * 設(shè)置懸浮窗監(jiān)聽(tīng)事件  */ private void initEvent() {  ivShowControlView.setOnLongClickListener(new OnLongClickListener() {   @Override   public boolean onLongClick(View view) {    if (!isControlViewShowing) {     myWindowManager.createControlView(context);     isControlViewShowing = true;    } else {     myWindowManager.removeControlView(context);     isControlViewShowing = false;    }    return true;   }  });  view.setOnTouchListener(new OnTouchListener() {   @Override   public boolean onTouch(View v, MotionEvent event) {    switch (event.getAction()) {     case MotionEvent.ACTION_DOWN:      if (!initViewPlace) {       initViewPlace = true;       //獲取初始位置       mTouchStartX += (event.getRawX() - lp.x);       mTouchStartY += (event.getRawY() - lp.y);      } else {       //根據(jù)上次手指離開(kāi)的位置與此次點(diǎn)擊的位置進(jìn)行初始位置微調(diào)       mTouchStartX += (event.getRawX() - x);       mTouchStartY += (event.getRawY() - y);      }      break;     case MotionEvent.ACTION_MOVE:      // 獲取相對(duì)屏幕的坐標(biāo),以屏幕左上角為原點(diǎn)      x = event.getRawX();      y = event.getRawY();      updateViewPosition();      break;     case MotionEvent.ACTION_UP:      break;    }    return true;   }  }); } /**  * 更新浮動(dòng)窗口位置  */ private void updateViewPosition() {  lp.x = (int) (x - mTouchStartX);  lp.y = (int) (y - mTouchStartY);  windowManager.updateViewLayout(this, lp); }

最后,只需要在Activity中調(diào)用mywindowManager中調(diào)用createxxx方法就可以。

public class MainActivity extends AppCompatActivity { MyWindowManager myWindowManager; @Override protected void onCreate(@Nullable Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);  myWindowManager = MyWindowManager.getInstance();  myWindowManager.createNormalView(this.getApplicationContext()); }}

最后,附上demo項(xiàng)目的下載地址: android實(shí)現(xiàn)懸浮窗

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到Android開(kāi)發(fā)頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 四子王旗| 商水县| 平罗县| 临夏县| 沁源县| 平定县| 白朗县| 将乐县| 湘乡市| 保山市| 册亨县| 凉山| 五河县| 永康市| 胶南市| 安陆市| 望城县| 岱山县| 双牌县| 商都县| 德钦县| 辉南县| 五大连池市| 北安市| 嘉祥县| 井陉县| 响水县| 长沙市| 石柱| 徐水县| 无极县| 黔西县| 京山县| 瑞金市| 淅川县| 江源县| 锡林浩特市| 玉树县| 玉龙| 盐边县| 庄浪县|