I'm using FloatingActionMenu. In the below picture I have color the background with green color so it easy to understand the problem
I want to move the FloatingActionMenu when the user drags the pink color button. I wrote a function to move the button by getting the motion event as below
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;
}
}
});
But It won't be working as my requirement. I want to move the button when I'm drag from the pink color button. But it moving when I drag from the green color background. Not from the pink color area. How to add touchlistener only to the round icon only?
current XML file is
<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>
Try to use event.getX()
instead of getRawX()
.
Code below works for me:
// 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;
}
});
Read your code again, seems like not only you want to drag the fab, but also you want to limit it to its parent area, so you need to do the limitation in ACTION_MOVE
, by comparing the fab's bound and its parent's boundary.