效果如下:包含 删除,编辑(是否选中),移动,放大
和之前的自定义LinearLayout相似,有移动和放大
1.消息拦截
为啥要这么写忘了,为了判断是否选中然后调用事件,好像也没用,
返回false 就 自己处理了,然后我调用了接口处理事件,还会走自己的onTouch吗 会走
/**
* 消息处理决定者 用来拦截子 View 的触摸事
* true 进行拦截 告诉dispatchTouchEvent我们来处理 进入父视图的onTouchEvent
* false 不拦截 告诉dispatchTouchEvent我们不管 会走自己的onTouchEvent
*
* @param ev
* @return
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (!isFocus) {
return true;
}
int action = ev.getActionMasked();
if (action == MotionEvent.ACTION_DOWN) {
if (isViewUnder(ivDel, ev.getX(), ev.getY())) {
mOnChildViewClickListener.onChildViewClick(ivDel, this);
return false;
}
if (isViewUnder(ivEdit, ev.getX(), ev.getY())) {
mOnChildViewClickListener.onChildViewClick(ivEdit, this);
return false;
}
}
return true;
}
刚又简便了一下
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return !isFocus;
}
2.判断触摸点是否在View的范围内的方法
/**
* 判断一个 View 是否包含某个点
*
* @param view 要判断的 View
* @param x 点的 x 坐标
* @param y 点的 y 坐标
* @return 如果 View 包含该点返回 true,否则返回 false
*/
private boolean isViewUnder(View view, float x, float y) {
Rect rect = new Rect();
view.getHitRect(rect); //此方法获取的是View在其父容器坐标系中的矩形区域(即相对于父容器的坐标)。
Log.d(TAG, "isViewUnder: " + rect.toString() + x + "yyyyy" + y);
if (rect.contains((int) x, (int) y)) {
// 坐标在 View 内部
return true;
}
return false;
}
// 判断触摸点是否在View的范围内的方法
private boolean isTouchInsideView(View view, float x, float y) {
// 创建一个Rect对象,表示View在屏幕中的矩形区域
Rect rect = new Rect();
view.getGlobalVisibleRect(rect);//这意味着返回的Rect对象的坐标是相对于屏幕的左上角为原点的坐标系。
// 判断触摸点是否在矩形区域内
return rect.contains((int) x, (int) y);
}
3.这是onTouchEvent方法
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
if (!isFocus) {
return true;
}
switch (action) {
case MotionEvent.ACTION_DOWN:
//设定移动的初始位置相对位置
lastX = event.getRawX();
lastY = event.getRawY();
viewScale = isViewUnder(ivScale, event.getX(), event.getY());
break;
case MotionEvent.ACTION_MOVE:
float dx = event.getRawX() - lastX;
float dy = event.getRawY() - lastY;
if (viewScale) {
scaleView(dx, dy);
} else {
moveView(dx, dy);
}
lastX = event.getRawX();
lastY = event.getRawY();
break;
case MotionEvent.ACTION_UP:
viewScale = false;
invalidate();
break;
default:
break;
}
return true;
}
4.选中
public void setFocus(boolean is) {
setUi(is);
isFocus = is;
}
private void setUi(boolean isSelect) {
// isFocus = isSelect;
ivScale.setVisibility(isSelect ? VISIBLE : INVISIBLE);
ivEdit.setVisibility(isSelect ? VISIBLE : INVISIBLE);
ivDel.setVisibility(isSelect ? VISIBLE : INVISIBLE);
textView.setSelected(isSelect);
}
isFocus 是有用的,因为view 设置为 INVISIBLE之后仍然可以点击,这样设置 isFocus 之后在onTouchEvent 可以做判断,onInterceptTouchEvent 里可以让用户去操作未被选中的父布局
5.放大
放大有点问题,不会改
/**
* 作用:放大
* 问题:加上后四句后,越放越大
*/
private void scaleView(float dx, float dy) {
float newWidth = textView.getWidth() + dx;
float newHeight = textView.getHeight() + dy;
float newScaleX = newWidth / textView.getWidth();
float newScaleY = newHeight / textView.getHeight();
// 限制最小缩放比例为 0.5
newScaleX = Math.max(newScaleX, 0.5f);
newScaleY = Math.max(newScaleY, 0.5f);
// Log.e(TAG, "scaleView2: newScaleX"+newScaleX+"____newScaleY"+newScaleY );
textView.setScaleX(newScaleX);
textView.setScaleY(newScaleY);
float newTextSize = textView.getTextSize() * newScaleX;
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, newTextSize);
textView.requestLayout();
//增加下面这几句就可以实现文字换行,但是会出现:不断来回下拉 下拉控件,字体越来越大
// ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) textView.getLayoutParams();
// layoutParams.width = (int) newWidth;
// layoutParams.height = (int) newHeight;
// textView.setLayoutParams(layoutParams);
}