۱ پوریا شفیعی
<پنجره شناور و قابل حرکت بر روی برنامه (آموزش ویژه)/>
جامعه جاوا (اندروید) ایجاد شده در ۱۸ فروردین ۱۳۹۹

رفقا سلام وقت بخیر

خیلی خوشحالم دارین این اموزشو میخونین چون به یقین پیشرفت برای شما مهمه 

امروز میخام اموزش پنجره شناور رو که در یکی سایت‌ها پیدا کردم و گفتم به اشتراک بذارمش براتون بذارم 

خیلی مواقع هست که نیاز به یک پنجره شناور در برنامه مون داریم ، این پنجره میتونه ویجت سفارشی شما یا منوی یک بازی ساده باشه که در Canvas ساخته شده

برای استفاده از این کار بدون لایبرری:

ابتدا کلاس مربوطه رو بسازید و کد‌های زیر رو داخلش قرار بدید

package com.example.YourProject
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.graphics.PixelFormat;
import android.os.Build;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import static android.content.Context.WINDOW_SERVICE;
public class FloatViewManager {
  private static boolean mIsFloatViewShowing;
  private Activity mActivity;
  private WindowManager mWindowManager;
  private View mFloatView;
  private WindowManager.LayoutParams mFloatViewLayoutParams;
  private boolean mFloatViewTouchConsumedByMove = false;
  private int mFloatViewLastX;
  private int mFloatViewLastY;
  private int mFloatViewFirstX;
  private int mFloatViewFirstY;
  @SuppressLint("InflateParams")
  public FloatViewManager(Activity activity) {
    mActivity = activity;
    LayoutInflater inflater = LayoutInflater.from(activity);
    mFloatView = inflater.inflate(R.layout.float_view_layout, null);
    TextView textView = mFloatView.findViewById(R.id.textView);
    textView.setText("I'm a float view!");
    ImageButton imageButton = mFloatView.findViewById(R.id.imageButton);
    imageButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        dismissFloatView();
      }
    });
    mFloatView.setOnClickListener(mFloatViewOnClickListener);
    mFloatView.setOnTouchListener(mFloatViewOnTouchListener);
    mFloatViewLayoutParams = new WindowManager.LayoutParams();
    mFloatViewLayoutParams.format = PixelFormat.TRANSLUCENT;
    mFloatViewLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
    mFloatViewLayoutParams.type = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
      ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
      : WindowManager.LayoutParams.TYPE_TOAST;
    mFloatViewLayoutParams.gravity = Gravity.CENTER;
    mFloatViewLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
    mFloatViewLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
  }
  public void dismissFloatView() {
    if (mIsFloatViewShowing) {
      mIsFloatViewShowing = false;
      mActivity.runOnUiThread(new Runnable() {
        @Override
        public void run() {
          if (mWindowManager != null) {
            mWindowManager.removeViewImmediate(mFloatView);
          }
        }
      });
    }
  }
  public void showFloatView() {
    if (!mIsFloatViewShowing) {
      mIsFloatViewShowing = true;
      mActivity.runOnUiThread(new Runnable() {
        @Override
        public void run() {
          if (!mActivity.isFinishing()) {
            mWindowManager = (WindowManager) mActivity.getSystemService(WINDOW_SERVICE);
            if (mWindowManager != null) {
              mWindowManager.addView(mFloatView, mFloatViewLayoutParams);
            }
          }
        }
      });
    }
  }
  @SuppressWarnings("FieldCanBeLocal")
  private View.OnClickListener mFloatViewOnClickListener = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      mActivity.runOnUiThread(new Runnable() {
        @Override
        public void run() {
          Toast.makeText(mActivity, "Float view is clicked!", Toast.LENGTH_SHORT).show();
        }
      });
    }
  };
  @SuppressWarnings("FieldCanBeLocal")
  private View.OnTouchListener mFloatViewOnTouchListener = new View.OnTouchListener() {
    @Override
    @SuppressLint("ClickableViewAccessibility")
    @TargetApi(Build.VERSION_CODES.FROYO)
    public boolean onTouch(View v, MotionEvent event) {
      WindowManager.LayoutParams prm = mFloatViewLayoutParams;
      int totalDeltaX = mFloatViewLastX - mFloatViewFirstX;
      int totalDeltaY = mFloatViewLastY - mFloatViewFirstY;
      switch (event.getActionMasked()) {
        case MotionEvent.ACTION_DOWN:
          mFloatViewLastX = (int) event.getRawX();
          mFloatViewLastY = (int) event.getRawY();
          mFloatViewFirstX = mFloatViewLastX;
          mFloatViewFirstY = mFloatViewLastY;
          break;
        case MotionEvent.ACTION_UP:
          break;
        case MotionEvent.ACTION_MOVE:
          int deltaX = (int) event.getRawX() - mFloatViewLastX;
          int deltaY = (int) event.getRawY() - mFloatViewLastY;
          mFloatViewLastX = (int) event.getRawX();
          mFloatViewLastY = (int) event.getRawY();
          if (Math.abs(totalDeltaX) >= 5 || Math.abs(totalDeltaY) >= 5) {
            if (event.getPointerCount() == 1) {
              prm.x += deltaX;
              prm.y += deltaY;
              mFloatViewTouchConsumedByMove = true;
              if (mWindowManager != null) {
                mWindowManager.updateViewLayout(mFloatView, prm);
              }
            } else {
              mFloatViewTouchConsumedByMove = false;
            }
          } else {
            mFloatViewTouchConsumedByMove = false;
          }
          break;
        default:
          break;
      }
      return mFloatViewTouchConsumedByMove;
    }
  };
}

سپس این کد‌ها رو به لیوت اضافه کنید 

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content">
    <android.support.v7.widget.AppCompatTextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#ff4444"
        android:padding="32dp"
        android:text="text"
        android:textColor="#ffffff"
        android:textSize="24sp" />
    <android.support.v7.widget.AppCompatImageButton
        android:id="@+id/imageButton"
        style="@style/Base.Widget.AppCompat.Button.Borderless"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_gravity="top|right"
        android:src="@drawable/ic_launcher_background" />
</FrameLayout>

و سپس در کلاس اکتیویتی مربوطه یا فرگمنت مربوطه کد‌های زیر اضافه کنید :

package com.example.YourProject
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
  Button button;
  private static final int REQUEST_CODE_DRAW_OVERLAY_PERMISSION = 5;
  private FloatViewManager mFloatViewManager;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mFloatViewManager = new FloatViewManager(MainActivity.this);
    button = (Button) findViewById(R.id.btn_Reset);
    findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        if (checkDrawOverlayPermission()) {
          mFloatViewManager.showFloatView();
        }
      }
    });
  }
  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CODE_DRAW_OVERLAY_PERMISSION) {
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Settings.canDrawOverlays(this)) {
        mFloatViewManager.showFloatView();
      }
    }
  }
  private boolean checkDrawOverlayPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
      Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
      startActivityForResult(intent, REQUEST_CODE_DRAW_OVERLAY_PERMISSION);
      return false;
    } else {
      return true;
    }
  }
}

و در آخر اگر سوالی بود ذکر کنین شما رو راهنمایی کنم.

و نکته اخر هیچوقت یادگیری رو متوقف نکنیم حتی شده روزی نیم ساعت ولی مستمر

چون به قول سعدی؟حافظ بهر حال نمیدونم کدوم شاعر عزیز هست رهرو آن است که اهسته و پیوسته رود .

پیروز باشین هم دوره ای‌های باحال.

 و همچنین ارادتمند استاد شاهینی عزیز.

 

سلام پوریا جان مرسی که از تجربیاتت اینجا میگی فقط اینکه توی MainActivity از آیدی btn_reset استفاده کردی که توی layout هامون تعریف نشده دوم اینکه دلیلی داشت از ساپورت لایبرری استفاده کردی؟

علی باقری ۱۹ اردیبهشت ۱۳۹۹، ۲۳:۵۳