kopia lustrzana https://github.com/N0BOY/FT8CN
382 wiersze
12 KiB
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;
|
|
}
|
|
}
|