FloatingActionMenu 上的 setOnTouchListener 无法正常工作
setOnTouchListener on FloatingActionMenu Not working properly
我正在使用 FloatingActionMenu。在下图中,我将背景涂成绿色,这样就很容易理解问题了
我想在用户拖动粉红色按钮时移动 FloatingActionMenu。我写了一个函数来通过获取下面的运动事件来移动按钮
fab1.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
int action = motionEvent.getAction();
if (action == MotionEvent.ACTION_DOWN) {
downRawX = motionEvent.getRawX();
downRawY = motionEvent.getRawY();
dX = view.getX() - downRawX;
dY = view.getY() - downRawY;
return true; // not Consumed for ripple effect
} else if (action == MotionEvent.ACTION_MOVE) {
viewWidth = view.getWidth();
viewHeight = view.getHeight();
View viewParent = (View) view.getParent();
parentWidth = viewParent.getWidth();
parentHeight = viewParent.getHeight();
newX = motionEvent.getRawX() + dX;
newX = Math.max(layoutParams.leftMargin, newX); // Don't allow the FAB past the left hand side of the parent
newX = Math.min(parentWidth - viewWidth - layoutParams.rightMargin, newX); // Don't allow the FAB past the right hand side of the parent
newY = motionEvent.getRawY() + dY;
newY = Math.max(layoutParams.topMargin, newY); // Don't allow the FAB past the top of the parent
newY = Math.min(parentHeight - viewHeight - layoutParams.bottomMargin, newY); // Don't allow the FAB past the bottom of the parent
view.animate()
.x(newX)
.y(newY)
.setDuration(0)
.start();
return true; // Consumed
} else if (action == MotionEvent.ACTION_UP) {
float upRawX = motionEvent.getRawX();
float upRawY = motionEvent.getRawY();
float upDX = upRawX - downRawX;
float upDY = upRawY - downRawY;
if (newX > ((parentWidth - viewWidth - layoutParams.rightMargin) / 2)) {
newX = parentWidth - viewWidth - layoutParams.rightMargin;
} else {
newX = layoutParams.leftMargin;
}
view.animate()
.x(newX)
.y(newY)
.setInterpolator(new OvershootInterpolator())
.setDuration(300)
.start();
if (Math.abs(upDX) < CLICK_DRAG_TOLERANCE && Math.abs(upDY) < CLICK_DRAG_TOLERANCE) { // A click
if (customClickListener != null) {
customClickListener.onClick(view);
}
return false;// not Consumed for ripple effect
} else { // A drag
return false; // not Consumed for ripple effect
}
} else {
return true;
}
}
});
但它不会按照我的要求工作。当我从粉红色按钮拖动时,我想移动按钮。但是当我从绿色背景中拖动时它会移动。不是来自粉红色区域。如何只给圆形图标添加touchlistener?
当前 XML 文件是
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<com.github.clans.fab.FloatingActionMenu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:fab="http://schemas.android.com/tools"
android:id="@+id/fab_menu_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="@color/colorPrimary"
app:fab_colorNormal="#DA4336"
app:fab_colorPressed="#E75043"
app:fab_colorRipple="#99FFFFFF"
app:fab_shadowColor="#66000000"
app:fab_showShadow="true"
app:menu_backgroundColor="#DA4336"
app:menu_labels_colorNormal="#333333"
app:menu_labels_colorPressed="#444444"
app:menu_labels_colorRipple="#66FFFFFF"
app:menu_labels_ellipsize="end"
app:menu_labels_maxLines="-1"
app:menu_labels_position="left"
app:menu_labels_showShadow="true"
app:menu_labels_singleLine="true"
app:menu_openDirection="up">
<com.github.clans.fab.FloatingActionButton
android:id="@+id/fab_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/fab_add"
app:fab_label="kkjj"
app:fab_size="mini" />
<com.github.clans.fab.FloatingActionButton
android:id="@+id/fab_scan_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/fab_add"
app:fab_label="lljjl"
app:fab_size="mini" />
<com.github.clans.fab.FloatingActionButton
android:id="@+id/fab_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/fab_add"
app:fab_label="jkjkjkj"
app:fab_size="mini" />
</com.github.clans.fab.FloatingActionMenu>
</RelativeLayout>
尝试使用 event.getX()
而不是 getRawX()
。
下面的代码对我有用:
// below are declared as fields
float downX;
float downY;
float dx;
float dy;
// set on touch listener
fab.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
dx += event.getX() - downX;
dy += event.getY() - downY;
fab.setTranslationX(dx);
fab.setTranslationY(dy);
break;
case MotionEvent.ACTION_UP:
fab.performClick();
break;
}
return true;
}
});
再看一遍你的代码,好像你不仅要拖动fab,还要限制它到它的父区域,所以你需要在ACTION_MOVE
中做限制,通过比较fab 的边界及其父边界。
我正在使用 FloatingActionMenu。在下图中,我将背景涂成绿色,这样就很容易理解问题了
我想在用户拖动粉红色按钮时移动 FloatingActionMenu。我写了一个函数来通过获取下面的运动事件来移动按钮
fab1.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
int action = motionEvent.getAction();
if (action == MotionEvent.ACTION_DOWN) {
downRawX = motionEvent.getRawX();
downRawY = motionEvent.getRawY();
dX = view.getX() - downRawX;
dY = view.getY() - downRawY;
return true; // not Consumed for ripple effect
} else if (action == MotionEvent.ACTION_MOVE) {
viewWidth = view.getWidth();
viewHeight = view.getHeight();
View viewParent = (View) view.getParent();
parentWidth = viewParent.getWidth();
parentHeight = viewParent.getHeight();
newX = motionEvent.getRawX() + dX;
newX = Math.max(layoutParams.leftMargin, newX); // Don't allow the FAB past the left hand side of the parent
newX = Math.min(parentWidth - viewWidth - layoutParams.rightMargin, newX); // Don't allow the FAB past the right hand side of the parent
newY = motionEvent.getRawY() + dY;
newY = Math.max(layoutParams.topMargin, newY); // Don't allow the FAB past the top of the parent
newY = Math.min(parentHeight - viewHeight - layoutParams.bottomMargin, newY); // Don't allow the FAB past the bottom of the parent
view.animate()
.x(newX)
.y(newY)
.setDuration(0)
.start();
return true; // Consumed
} else if (action == MotionEvent.ACTION_UP) {
float upRawX = motionEvent.getRawX();
float upRawY = motionEvent.getRawY();
float upDX = upRawX - downRawX;
float upDY = upRawY - downRawY;
if (newX > ((parentWidth - viewWidth - layoutParams.rightMargin) / 2)) {
newX = parentWidth - viewWidth - layoutParams.rightMargin;
} else {
newX = layoutParams.leftMargin;
}
view.animate()
.x(newX)
.y(newY)
.setInterpolator(new OvershootInterpolator())
.setDuration(300)
.start();
if (Math.abs(upDX) < CLICK_DRAG_TOLERANCE && Math.abs(upDY) < CLICK_DRAG_TOLERANCE) { // A click
if (customClickListener != null) {
customClickListener.onClick(view);
}
return false;// not Consumed for ripple effect
} else { // A drag
return false; // not Consumed for ripple effect
}
} else {
return true;
}
}
});
但它不会按照我的要求工作。当我从粉红色按钮拖动时,我想移动按钮。但是当我从绿色背景中拖动时它会移动。不是来自粉红色区域。如何只给圆形图标添加touchlistener?
当前 XML 文件是
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<com.github.clans.fab.FloatingActionMenu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:fab="http://schemas.android.com/tools"
android:id="@+id/fab_menu_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="@color/colorPrimary"
app:fab_colorNormal="#DA4336"
app:fab_colorPressed="#E75043"
app:fab_colorRipple="#99FFFFFF"
app:fab_shadowColor="#66000000"
app:fab_showShadow="true"
app:menu_backgroundColor="#DA4336"
app:menu_labels_colorNormal="#333333"
app:menu_labels_colorPressed="#444444"
app:menu_labels_colorRipple="#66FFFFFF"
app:menu_labels_ellipsize="end"
app:menu_labels_maxLines="-1"
app:menu_labels_position="left"
app:menu_labels_showShadow="true"
app:menu_labels_singleLine="true"
app:menu_openDirection="up">
<com.github.clans.fab.FloatingActionButton
android:id="@+id/fab_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/fab_add"
app:fab_label="kkjj"
app:fab_size="mini" />
<com.github.clans.fab.FloatingActionButton
android:id="@+id/fab_scan_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/fab_add"
app:fab_label="lljjl"
app:fab_size="mini" />
<com.github.clans.fab.FloatingActionButton
android:id="@+id/fab_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/fab_add"
app:fab_label="jkjkjkj"
app:fab_size="mini" />
</com.github.clans.fab.FloatingActionMenu>
</RelativeLayout>
尝试使用 event.getX()
而不是 getRawX()
。
下面的代码对我有用:
// below are declared as fields
float downX;
float downY;
float dx;
float dy;
// set on touch listener
fab.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
dx += event.getX() - downX;
dy += event.getY() - downY;
fab.setTranslationX(dx);
fab.setTranslationY(dy);
break;
case MotionEvent.ACTION_UP:
fab.performClick();
break;
}
return true;
}
});
再看一遍你的代码,好像你不仅要拖动fab,还要限制它到它的父区域,所以你需要在ACTION_MOVE
中做限制,通过比较fab 的边界及其父边界。