亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android 實(shí)現(xiàn)可任意拖動(dòng)的懸浮窗功能(類似懸浮球)

 更新時(shí)間:2020年05月28日 10:56:50   作者:愛(ài)碼士_yan  
這篇文章主要介紹了Android 可任意拖動(dòng)的懸浮窗(類似懸浮球),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

最近開(kāi)發(fā)項(xiàng)目中,有個(gè)在屏幕上任意拖動(dòng)的懸浮窗功能,其實(shí)就是利用 WindowManager的api來(lái)完成這個(gè)需求,具體的實(shí)現(xiàn)的功能如下:
1.自定義view

import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.widget.LinearLayout;
import com.xinrui.recordscreen.R;
import java.lang.reflect.Field;
/**
 *
 */
public class RecordScreenView extends LinearLayout implements View.OnClickListener{
  private WindowManager mWindowManager;
  private WindowManager.LayoutParams mLayoutParams;
  private long mLastDownTime;
  private float mLastDownX;
  private float mLastDownY;
  private boolean mIsLongTouch;
  private boolean mIsTouching;
  private float mTouchSlop;
  private final static long LONG_CLICK_LIMIT = 20;
  private final static int TIME_COUNT = 0;
  private int mStatusBarHeight;
  private int mCurrentMode,time=0;
  private final static int MODE_NONE = 0x000;
  private final static int MODE_MOVE = 0x001;
  private int mOffsetToParent;
  private int mOffsetToParentY;
  private Context mContext;
  public RecordScreenView(Context context) {
    super(context);
    this.mContext=context;
    mWindowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
    initView();
  }
  private void initView() {
    View view = inflate(getContext(), R.layout.layout_ball, this);
    mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
    mCurrentMode = MODE_NONE;
    recordtime(0);
    mStatusBarHeight = getStatusBarHeight();
    mOffsetToParent = dip2px(25);
    mOffsetToParentY = mStatusBarHeight + mOffsetToParent;
    view.setOnTouchListener(new OnTouchListener() {
      @Override
      public boolean onTouch(View v, final MotionEvent event) {
        switch (event.getAction()) {
          case MotionEvent.ACTION_DOWN:
            mIsTouching = true;
            mLastDownTime = System.currentTimeMillis();
            mLastDownX = event.getX();
            mLastDownY = event.getY();
            postDelayed(new Runnable() {
              @Override
              public void run() {
                if (isLongTouch()) {
                  mIsLongTouch = true;
                }
              }
            }, LONG_CLICK_LIMIT);
            break;
          case MotionEvent.ACTION_MOVE:
            if (!mIsLongTouch && isTouchSlop(event)) {
              return true;
            }
            if (mIsLongTouch && (mCurrentMode == MODE_NONE || mCurrentMode == MODE_MOVE)) {
              mLayoutParams.x = (int) (event.getRawX() - mOffsetToParent);
              mLayoutParams.y = (int) (event.getRawY() - mOffsetToParentY);
              mWindowManager.updateViewLayout(RecordScreenView.this, mLayoutParams);//不斷刷新懸浮窗的位置
              mCurrentMode = MODE_MOVE;
            }
            break;
          case MotionEvent.ACTION_CANCEL:
          case MotionEvent.ACTION_UP:
            mIsTouching = false;
            if (mIsLongTouch) {
              mIsLongTouch = false;
            }
            mCurrentMode = MODE_NONE;
            break;
        }
        return true;
      }
    });
  }
  private boolean isLongTouch() {
    long time = System.currentTimeMillis();
    if (mIsTouching && mCurrentMode == MODE_NONE && (time - mLastDownTime >= LONG_CLICK_LIMIT)) {
      return true;
    }
    return false;
  }
  /**
   * 判斷是否是輕微滑動(dòng)
   *
   * @param event
   * @return
   */
  private boolean isTouchSlop(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();
    if (Math.abs(x - mLastDownX) < mTouchSlop && Math.abs(y - mLastDownY) < mTouchSlop) {
      return true;
    }
    return false;
  }
  public void setLayoutParams(WindowManager.LayoutParams params) {
    mLayoutParams = params;
  }
  /**
   * 獲取通知欄高度
   *
   * @return
   */
  private int getStatusBarHeight() {
    int statusBarHeight = 0;
    try {
      Class<?> c = Class.forName("com.android.internal.R$dimen");
      Object o = c.newInstance();
      Field field = c.getField("status_bar_height");
      int x = (Integer) field.get(o);
      statusBarHeight = getResources().getDimensionPixelSize(x);
    } catch (Exception e) {
      e.printStackTrace();
    }
    return statusBarHeight;
  }
  public int dip2px(float dip) {
    return (int) TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP, dip, getContext().getResources().getDisplayMetrics()
    );
  }
}

2.添加windowManager添加view

import android.content.Context;
import android.graphics.PixelFormat;
import android.view.Gravity;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;

/**
 * Created by wangxiandeng on 2016/11/25.
 */

public class FloatWindowManager {
  private static RecordScreenView mBallView;

  private static WindowManager mWindowManager;


  public static void addBallView(Context context) {
    if (mBallView == null) {
      WindowManager windowManager = getWindowManager(context);
      int screenWidth = windowManager.getDefaultDisplay().getWidth();
      int screenHeight = windowManager.getDefaultDisplay().getHeight();
      mBallView = new RecordScreenView(context);
      LayoutParams params = new LayoutParams();
      params.x = screenWidth/2;
      params.y = screenHeight/2+150;
      params.width = LayoutParams.WRAP_CONTENT;
      params.height = LayoutParams.WRAP_CONTENT;
      params.gravity = Gravity.LEFT | Gravity.TOP;
      params.type = LayoutParams.TYPE_APPLICATION_OVERLAY;
      params.format = PixelFormat.RGBA_8888;
      params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
          | LayoutParams.FLAG_NOT_FOCUSABLE;
      mBallView.setLayoutParams(params);
      windowManager.addView(mBallView, params);
    }
  }

  public static void removeBallView(Context context) {
    if (mBallView != null) {
      WindowManager windowManager = getWindowManager(context);
      windowManager.removeView(mBallView);
      mBallView = null;
    }
  }

  private static WindowManager getWindowManager(Context context) {
    if (mWindowManager == null) {
      mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    }
    return mWindowManager;
  }
}

3.Acitivity中調(diào)用

import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;

import com.xinrui.recordscreen.view.FloatWindowManager;

public class MainActivity extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (Build.VERSION.SDK_INT >= 23) {
    //設(shè)置中請(qǐng)求開(kāi)啟懸浮窗權(quán)限
      if (!Settings.canDrawOverlays(this)) {
        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
        Toast.makeText(this, MainActivity.this.getResources().getString(R.string.open_float), Toast.LENGTH_SHORT).show();
      }else{
        initView();
      }
    }
  }

  private void initView() {
    FloatWindowManager.addBallView(MainActivity.this);
    finish();
  }
}

5.AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.xinrui.recordscreen">
  <uses-permission android:name="android.permission.INTERNET"/>
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>//懸浮窗權(quán)限
  <application
    android:allowBackup="true"
    android:icon="@drawable/recording_screen_nor"
    android:label="@string/app_name"
    android:supportsRtl="true">
    <activity android:name="com.xinrui.recordscreen.MainActivity">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
</manifest>

總結(jié)

到此這篇關(guān)于Android 實(shí)現(xiàn)可任意拖動(dòng)的懸浮窗功能(類似懸浮球)的文章就介紹到這了,更多相關(guān)Android任意拖動(dòng)的懸浮窗內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • ANDROID中自定義對(duì)話框AlertDialog使用示例

    ANDROID中自定義對(duì)話框AlertDialog使用示例

    這篇文章主要為大家詳細(xì)介紹了Android中自定義對(duì)話框AlertDialog使用示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • Android 彈出Dialog時(shí)隱藏狀態(tài)欄和底部導(dǎo)航欄的方法

    Android 彈出Dialog時(shí)隱藏狀態(tài)欄和底部導(dǎo)航欄的方法

    這篇文章主要介紹了Android 彈出Dialog時(shí)隱藏狀態(tài)欄和底部導(dǎo)航欄的實(shí)例代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-07-07
  • 詳解Android6.0運(yùn)行時(shí)權(quán)限管理

    詳解Android6.0運(yùn)行時(shí)權(quán)限管理

    自從Android6.0發(fā)布以來(lái),在權(quán)限上做出了很大的變動(dòng),不再是之前的只要在manifest設(shè)置就可以任意獲取權(quán)限,而是更加的注重用戶的隱私和體驗(yàn)。本文詳細(xì)介紹了Android6.0運(yùn)行時(shí)權(quán)限管理。需要的朋友一起來(lái)看下吧
    2016-12-12
  • Android自定義View仿支付寶輸入六位密碼功能

    Android自定義View仿支付寶輸入六位密碼功能

    跟選擇銀行卡界面類似,也是用一個(gè)PopupWindow,不過(guò)輸入密碼界面是一個(gè)自定義view,當(dāng)輸入六位密碼完成后用回調(diào)在Activity中獲取到輸入的密碼并以Toast顯示密碼。這篇文章主要介紹了Android自定義View仿支付寶輸入六位密碼功能的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • Android仿iOS側(cè)滑退出當(dāng)前界面功能

    Android仿iOS側(cè)滑退出當(dāng)前界面功能

    這篇文章主要為大家詳細(xì)介紹了Android仿iOS側(cè)滑退出當(dāng)前界面功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • js驗(yàn)證手機(jī)號(hào)碼

    js驗(yàn)證手機(jī)號(hào)碼

    本文主要分享了js驗(yàn)證手機(jī)號(hào)碼的示例代碼,具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-01-01
  • Android串口開(kāi)發(fā)之使用JNI實(shí)現(xiàn)ANDROID和串口通信詳解

    Android串口開(kāi)發(fā)之使用JNI實(shí)現(xiàn)ANDROID和串口通信詳解

    這篇文章主要給大家介紹了關(guān)于Android串口開(kāi)發(fā)之使用JNI實(shí)現(xiàn)ANDROID和串口通信的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01
  • 去掉RecycleView或者ListView上下滑動(dòng)陰影的方法

    去掉RecycleView或者ListView上下滑動(dòng)陰影的方法

    下面小編就為大家分享一篇去掉RecycleView或者ListView上下滑動(dòng)陰影的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • android9.0 默認(rèn)apk權(quán)限添加方法

    android9.0 默認(rèn)apk權(quán)限添加方法

    本文給大家分享android9.0 默認(rèn)apk權(quán)限添加方法,默認(rèn)賦予全部權(quán)限,根據(jù)包名賦予權(quán)限,通過(guò)default-permissions-google.xml的方式實(shí)現(xiàn),文中通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2021-06-06
  • Android采用GET方法進(jìn)行網(wǎng)絡(luò)傳值

    Android采用GET方法進(jìn)行網(wǎng)絡(luò)傳值

    這篇文章主要為大家詳細(xì)介紹了Android采用GET方法進(jìn)行網(wǎng)絡(luò)傳值的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12

最新評(píng)論