FT8CN/ft8cn/app/src/main/java/com/bg7yoz/ft8cn/floatview/FloatView.java

382 wiersze
12 KiB
Java

package com.bg7yoz.ft8cn.floatview;
/**
* FloatButton的主界面
* @author BGY70Z
* @date 2023-03-20
*/
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageButton;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;
import androidx.constraintlayout.widget.Constraints;
import java.util.ArrayList;
public class FloatView extends ConstraintLayout {
private static final String TAG = "FloatView";
public enum FLOAT_BOARD {
LEFT, RIGHT, TOP, BUTTON
}
private int parentViewHeight = 100;//上一级view的高度
private int parentViewWidth = 100;//上一级view的宽度
private float mDownX = 0;
private float mDownY = 0;
private int lastLeft = 0;
private int lastTop = 0;
//------------悬浮窗口的属性--------------------
private int buttonSize = 96;//按钮的大小
private final ArrayList<FloatViewButton> buttons = new ArrayList<>();
private boolean originalFromTop = false;//是否上下靠边
private boolean originalFromLeft = true;//是否左右靠边
private int buttonBackgroundResourceId = -1;//按钮的背景
private int backgroundResourceId = -1;//浮窗的背景
private int buttonMargin = 0;//按钮在浮窗中的边界宽度
private int floatMargin = 40;//浮窗距离边界的距离
private FLOAT_BOARD floatBoard = FLOAT_BOARD.LEFT;
/**
* 构造函数,需要大小
*
* @param context context
* @param buttonSize 按钮大小,正方形
*/
public FloatView(@NonNull Context context, int buttonSize) {
this(context);
this.buttonSize = buttonSize;
}
public FloatView(@NonNull Context context) {
this(context, null);
}
public FloatView(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public FloatView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
public FloatViewButton addButton(String name, int imageResourceId, OnClickListener onClickListener) {
FloatViewButton floatViewButton=getButtonByName(name);
if (floatViewButton==null){
floatViewButton =addButton(View.generateViewId(), imageResourceId, onClickListener);
}
floatViewButton.setName(name);
return floatViewButton;
}
public FloatViewButton addButton(int id, String name, int imageResourceId, OnClickListener onClickListener) {
FloatViewButton floatViewButton=getButtonByName(name);
if (floatViewButton==null){
floatViewButton = addButton(id, imageResourceId, onClickListener);
}
floatViewButton.setName(name);
return floatViewButton;
}
public FloatViewButton addButton(int id, int imageResourceId, OnClickListener onClickListener) {
FloatViewButton imageButton = new FloatViewButton(getContext());
//imageButton.setScaleType(ImageView.ScaleType.FIT_CENTER);
imageButton.setImageResource(imageResourceId);
if (buttonBackgroundResourceId != -1) {
imageButton.setBackgroundResource(buttonBackgroundResourceId);
}
//imageButton.setId(R.id.float_nav);
imageButton.setId(id);
imageButton.setOnClickListener(onClickListener);
imageButton.setAlpha(0.5f);
addView(imageButton);
buttons.add(imageButton);
resetView();
return imageButton;
}
/**
* 通过按钮的名称删除按钮
*
* @param name 按钮的名称
*/
public void deleteButtonByName(String name) {
for (int i = buttons.size() - 1; i >= 0; i--) {
FloatViewButton floatViewButton = buttons.get(i);
if (floatViewButton.getName().equals(name)) {
buttons.remove(i);
removeView(floatViewButton);
}
resetView();
}
}
public void deleteButtonByIndex(int index) {
if (buttons.size() > index && index > -1) {
FloatViewButton floatViewButton = buttons.get(index);
buttons.remove(index);
removeView(floatViewButton);
resetView();
}
}
public FloatViewButton getButtonByName(String name) {
for (FloatViewButton button : buttons) {
if (button.getName().equals(name)) {
return button;
}
}
return null;
}
/**
* 把dp值转换为像素点
*
* @param dp dp值
* @return 像素点
*/
private int dpToPixel(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp
, getResources().getDisplayMetrics());
// return (int) (dp*getResources().getDisplayMetrics().density);
}
/**
* 重新设置一下按钮
*/
public void resetView() {
for (int i = 0; i < buttons.size(); i++) {
//LayoutParams buttonLp = new LayoutParams(buttonSize, buttonSize);
LayoutParams buttonLp = new LayoutParams(dpToPixel(buttonSize), dpToPixel(buttonSize));
buttonLp.startToStart = ConstraintSet.PARENT_ID;
buttonLp.endToEnd = ConstraintSet.PARENT_ID;
buttonLp.leftMargin = buttonMargin;
buttonLp.rightMargin = buttonMargin;
if (i == 0) {
buttonLp.topToTop = ConstraintSet.PARENT_ID;
buttonLp.topMargin = buttonMargin;
} else {
buttonLp.topToBottom = buttons.get(i - 1).getId();
buttonLp.topMargin = buttonMargin+dpToPixel(4);//按钮之间留一点点空隙
}
if (i == buttons.size() - 1) {
buttonLp.bottomToBottom = ConstraintSet.PARENT_ID;
buttonLp.bottomMargin = buttonMargin;
}
buttons.get(i).setLayoutParams(buttonLp);
}
}
@SuppressLint("ClickableViewAccessibility")
private void initView() {
LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);// LayoutParams.WRAP_CONTENT);
lp.startToStart = ConstraintSet.PARENT_ID;//只连接窗口的左边和上边
lp.topToTop = ConstraintSet.PARENT_ID;
this.setLayoutParams(lp);
}
public void initLocation() {
initLocation(this.floatBoard);
}
/**
* 初始化浮窗的位置,默认在窗口的右侧,
*/
public void initLocation(FLOAT_BOARD float_board) {
this.floatBoard = float_board;
getParentViewHeightAndWidth();
int width;
int height;
if (parentViewWidth == 0 && parentViewHeight == 0) {
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
width = wm.getDefaultDisplay().getWidth();
height = wm.getDefaultDisplay().getHeight();
} else {//这部分基本没有执行过
width = parentViewWidth;
height = parentViewHeight;
}
switch (float_board) {
case RIGHT:
setLayoutLeftTop(width - dpToPixel(floatMargin * 2 - buttonSize) - 10
, (int) (height / 2f - dpToPixel(buttonMargin + buttonSize * buttons.size())/2f));
break;
case LEFT:
setLayoutLeftTop(floatMargin + 10
, (int) (height / 2f - dpToPixel(buttonMargin + buttonSize * buttons.size() )/2f));
break;
case TOP:
setLayoutLeftTop((int) (width / 2f - dpToPixel(buttonMargin - buttonSize) / 2f), floatMargin);
break;
case BUTTON:
setLayoutLeftTop((int) (width / 2f - dpToPixel(buttonMargin - buttonSize) / 2f)
, height - dpToPixel(floatMargin - buttonMargin * 2 - buttonSize * buttons.size()));
break;
}
}
/**
* 获取父View的高度和宽度
*/
private void getParentViewHeightAndWidth() {
View view = (View) getParent();
if (view != null) {
parentViewHeight = view.getHeight();
parentViewWidth = view.getWidth();
}
}
public void setLayoutLeftTop(int left, int top) {
ConstraintLayout.LayoutParams layoutParams = new Constraints.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT
, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.topToTop = ConstraintSet.PARENT_ID;
layoutParams.startToStart = ConstraintSet.PARENT_ID;
layoutParams.leftMargin = left;
layoutParams.topMargin = top;
setLayoutParams(layoutParams);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mDownX = event.getX();
mDownY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
offsetTopAndBottom((int) (event.getY() - mDownY));
offsetLeftAndRight((int) (event.getX() - mDownX));
lastLeft = getLeft();
lastTop = getTop();
setLayoutLeftTop(getLeft(), getTop());
case MotionEvent.ACTION_UP:
setLayoutLeftTop(lastLeft, lastTop);
adsorbTopAdnBottom();//吸附上下
adsorbLeftAndRight();//吸附左右
break;
case MotionEvent.ACTION_CANCEL:
break;
}
return super.onInterceptTouchEvent(event);
}
private void adsorbTopAdnBottom() {
if (originalFromTop) {
getParentViewHeightAndWidth();
float boundaryLine = parentViewHeight / 4f;
if (getTop() < boundaryLine) {
setLayoutLeftTop(getLeft(), floatMargin);
} else if (getBottom() > parentViewHeight - boundaryLine) {
setLayoutLeftTop(getLeft(), parentViewHeight - getHeight() - floatMargin);
}
}
}
private void adsorbLeftAndRight() {
if (originalFromLeft) {
getParentViewHeightAndWidth();
float boundaryLine = parentViewWidth / 4f;
if (getLeft() < boundaryLine) {
setLayoutLeftTop(floatMargin, getTop());
} else if (getRight() > parentViewWidth - boundaryLine) {
setLayoutLeftTop(parentViewWidth - getWidth() - floatMargin, getTop());
//animate().setInterpolator(new DecelerateInterpolator()).setDuration(300).x(parentViewWidth - getWidth() - floatMargin).start();
}
}
}
public boolean isOriginalFromTop() {
return originalFromTop;
}
public void setOriginalFromTop(boolean originalFromTop) {
this.originalFromTop = originalFromTop;
}
public boolean isOriginalFromLeft() {
return originalFromLeft;
}
public void setOriginalFromLeft(boolean originalFromLeft) {
this.originalFromLeft = originalFromLeft;
}
public int getButtonBackgroundResourceId() {
return buttonBackgroundResourceId;
}
public void setButtonBackgroundResourceId(int buttonBackgroundResourceId) {
this.buttonBackgroundResourceId = buttonBackgroundResourceId;
for (ImageButton button : this.buttons) {
button.setBackgroundResource(buttonBackgroundResourceId);
}
}
public int getBackgroundResourceId() {
return backgroundResourceId;
}
public void setBackgroundResourceId(int backgroundResourceId) {
this.setBackgroundResource(backgroundResourceId);
this.backgroundResourceId = backgroundResourceId;
}
public int getButtonMargin() {
return buttonMargin;
}
public void setButtonMargin(int buttonMargin) {
this.buttonMargin = buttonMargin;
}
public int getFloatMargin() {
return floatMargin;
}
public void setFloatMargin(int floatMargin) {
this.floatMargin = floatMargin;
}
public FLOAT_BOARD getFloatBoard() {
return floatBoard;
}
public void setFloatBoard(FLOAT_BOARD float_board) {
this.floatBoard = float_board;
}
}