I'm using this library to use slide down menu, the problem is when I want to move the handle from top to bottom and want to change from slide down to slide up, I try to change the variable but can't make it right
This is the original code
/* User tapped down on screen. */
case MotionEvent.ACTION_DOWN:
// User has tapped the screen
yStart = event.getRawY();
lastY = event.getRawY();
currentHeight = slideDownView.getHeight();
break;
/* User is dragging finger. */
case MotionEvent.ACTION_MOVE:
// Calculate the total height change thus far.
float totalHeightDiff = event.getRawY() - yStart;
// Adjust the slide down height immediately with touch movements.
LayoutParams params = slideDownView.getLayoutParams();
params.height = (int)(currentHeight + totalHeightDiff);
slideDownView.setLayoutParams(params);
// Check and set which direction drag is moving.
if (event.getRawY() > lastY) {
directionDown = true;
} else {
directionDown = false;
}
// Set the lastY for comparison in the next ACTION_MOVE event.
lastY = event.getRawY();
break;
/* User lifted up finger. */
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
/*
* Need to snap either up or down. Using ValueAnimator to "finish" the action.
* HeightEvaluator is a custom class.
*
* NOTE: I'm using the nineoldandroids library for
*/
if (directionDown) {
// Open the sliding view.
int startHeight = slideDownView.getHeight();
ValueAnimator animation = ValueAnimator.ofObject(
new HeightEvaluator(slideDownView),
startHeight,
(int) openHeight).setDuration(300);
// See Table 3 for other interpolator options
// - http://developer.android.com/guide/topics/graphics/prop-animation.html
animation.setInterpolator(new OvershootInterpolator(1));
animation.start();
} else {
// Close the sliding view.
int startHeight = slideDownView.getHeight();
ValueAnimator animation = ValueAnimator.ofObject(
new HeightEvaluator(slideDownView),
startHeight,
(int) closedHeight).setDuration(300);
animation.setInterpolator(new OvershootInterpolator(1));
animation.start();
}
break;
How to make it reverse ? so I can slide up from bottom to top ? is it have to change also in HeightEvaluator.java ?
At the end I use BottomSheet and set PeekHeight to make a slideUp with button at the bottom that still visible to trigger the slideView
Related
im trying to add touchlistener for every item in listview.
here my code in my CustomAdapter for currentView (as i think)
rowView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x1 = event.getX();
return true;
case MotionEvent.ACTION_UP:
x2 = event.getX();
float deltaX = x2 - x1;
if (Math.abs(deltaX) > MIN_DISTANCE) {
if (x2 > x1) {
LEFT = false;
Logger.e("FALSE ");
txtTitle.setText("LEFT TO RIGHT");
moveLefttoRight = new TranslateAnimation(0, -150, 0, 0);
moveLefttoRight.setDuration(1500);
moveLefttoRight.setFillAfter(true);
swipeLayout.setAnimation(moveLefttoRight);
HomeChatAdapter.super.notifyDataSetChanged();
}
else {
LEFT = true;
Logger.e("TRUE");
txtTitle.setText("RIGHT TO LEFT");
moveLefttoRight = new TranslateAnimation(0, -150, 0, 0);
moveLefttoRight.setDuration(1500);
moveLefttoRight.setFillAfter(true);
swipeLayout.setAnimation(moveLefttoRight);
}
} else {
CLICKITEM = true;
return false;
}
break;
}
return false;
}
});
problem with animation and view.setText("blabla")
When my swipe is done "from left to right or from right to left"
no changes on screen
If i move out
txtTitle.setText("LEFT TO RIGHT");
moveLefttoRight = new TranslateAnimation(0, -150, 0, 0);
moveLefttoRight.setDuration(1500);
moveLefttoRight.setFillAfter(true);
swipeLayout.setAnimation(moveLefttoRight);
this part of code from TouchListener - than all ok but its work one time when created.
Can any help me how to do solution in this situation ?
Just want to move item in listview to left or right . Regard Peter.
If I am understanding your question correctly, you want to use
swipeLayout.startAnimation(...);
instead.
According to setAnimation vs startAnimation in android :
setAnimation
Sets the next animation to play for this view.But view animation does
not start yet.
startAnimation
If you want the animation to play immediately, use startAnimation.
This method provides allows fine-grained control over the start time
and invalidation, but you must make sure that
1) the animation has a start time set,
2) the view will be invalidated when the animation is supposed to
start.
I create an ui in which the image button is animate or moved on touch. But its moving throughout the layout, I want to move it in particular set area.
UPDATE code:
I just clear the animation and use this on behalf. This code lets me to move the Image button on touch in specific radius but it flicker the image means the image is constantly moving around not stopping after touch.
case (MotionEvent.ACTION_MOVE):
x = event.getRawX();
y = event.getRawY();
float deltaX = x - idx;
float deltaY = y - idy;
double angleInDegrees = Math.atan(deltaY / deltaX) * 360 / Math.PI;
idx = x;
idy = y;
imknob.setTranslationX((float)(200*(Math.cos(angleInDegrees))));
imknob.setTranslationY((float)(200*(Math.sin(angleInDegrees))));
break;
Please if someone help me with this !
The red dot image must move inside the black circle. How would I limit it!!
final RelativeLayout rl = (RelativeLayout) findViewById(R.id.rel);
final ImageView circle = (ImageView) findViewById(R.id.circle);
final ViewGroup.MarginLayoutParams screen = (ViewGroup.MarginLayoutParams) rl.getLayoutParams();
and..
View v;
v = arrayofImages[i];
v.setOnTouchListener(new View.OnTouchListener() {
PointF DownPT = new PointF();
PointF StartPT = new PointF();
#Override
public boolean onTouch(View v, MotionEvent event) {
int eid = event.getAction();
switch (eid) {
case MotionEvent.ACTION_MOVE:
PointF mv = new PointF(event.getX() - DownPT.x, event.getY() - DownPT.y);
v.setX((StartPT.x + mv.x));
v.setY( (StartPT.y + mv.y));
StartPT = new PointF(v.getX(), v.getY());
if (circle.getRight() > v.getX() && circle.getTop() <= v.getY()
&& circle.getBottom() > v.getY() && circle.getLeft() <= v.getX()) {
v.setVisibility(View.INVISIBLE);
}
if (v.getX() > screen.bottomMargin) {
v.setX(screen.bottomMargin);
}
break;
case MotionEvent.ACTION_DOWN:
DownPT.x = event.getX();
DownPT.y = event.getY();
StartPT = new PointF(v.getX(), v.getY());
break;
case MotionEvent.ACTION_UP:
// Nothing have to do
break;
default:
break;
}
return true;
}
});
So basically I'm trying to not allow an imageView to go ofscreen. if the view v is going too far left position it on the left side.
if (v.getX() > screen.leftMargin) {
v.setX(screen.leftMargin);
}
This should do to trick and it does but only for the left margin. If i try something like this
if (v.getX() > screen.rightMargin) {
v.setX(screen.rightMargin);
}
It acts like it's the leftMargin (it moves my image when i touch it on the left side.)
I don't know what i've done wrong...Please help..If you need more code i will paste but this is all that matters i think.
Well, you are not supposed to be using bottomMargin or topMargin fields. These are the Margins that you set for the RelativeLayout. If you want to check if the View doesn't go OUTSIDE the RelativeLayout, you need to be checking with width and height.
But if all you are going to do is to keep the View inside the RelativeLayout, you need to use View.getLeft() and View.getRight() instead of getX(). This will give the position of the View relative to the parent. You can use this in your logic, rather than using getX() (which returns the visual x position of this view, in pixels.)
It is possible to retrieve the location of a view by invoking the
methods getLeft() and getTop(). The former returns the left, or X,
coordinate of the rectangle representing the view. The latter returns
the top, or Y, coordinate of the rectangle representing the view.
These methods both return the location of the view relative to its
parent. For instance, when getLeft() returns 20, that means the view
is located 20 pixels to the right of the left edge of its direct
parent.
I'm having a very similar issue described here, except instead of using ScaleAnimation, I'm allowing pinch zoom/pan in my RelativeLayout.
The zoom/panning works perfectly, but regardless of how my view is panned/zoomed, the clickable area does not change along with the visual representation. Here's what my dispatchTouchEvent looks like:
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (mScaleGestureDetector != null && mGestureDetector != null) {
mScaleGestureDetector.onTouchEvent(ev);
mGestureDetector.onTouchEvent(ev);
}
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();
mLastTouchX = x;
mLastTouchY = y;
mActivePointerId = ev.getPointerId(0);
break;
}
case MotionEvent.ACTION_MOVE: {
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(pointerIndex);
final float y = ev.getY(pointerIndex);
// Only move if the ScaleGestureDetector isn't processing a gesture.
if (!mScaleGestureDetector.isInProgress() && mScaleFactor > 1f) {
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
float newPosX = mPosX + dx;
float newPosY = mPosY + dy;
if (isCoordinateInBound(newPosX, mScreenSize.x))
mPosX = newPosX;
if (isCoordinateInBound(newPosY, mScreenSize.y))
mPosY = newPosY;
invalidate();
}
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_UP: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = ev.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = ev.getX(newPointerIndex);
mLastTouchY = ev.getY(newPointerIndex);
mActivePointerId = ev.getPointerId(newPointerIndex);
}
break;
}
}
return super.dispatchTouchEvent(ev);
}
and my dispatchDraw:
protected void dispatchDraw(Canvas canvas) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor);
super.dispatchDraw(canvas);
canvas.restore();
}
How do you modify the clickable area accordingly to modified scale/transformation of canvas?
Since you are already onverriding dispatchTouchEvent, you can try this:
manually evaluate each MotionEvent by considering the current zoom/pan transformation; you can create a new MotionEvent (let's call it FakeMotionEvent) by applying the reverse zoom/pan transformation to the original MotionEvent m.
Check if the FakeMotionEvent intercepts a specific View v; this means the user is touching in a position which represents the user-visibile position of v.
If FakeMotionEvent intercepts v, consume the current MotionEvent and invoke v.dispatchTouchEvent(m);
TIP: You can use the method below to evaluate if a MotionEvent intercepts a View with a certain degree of tolerance:
private boolean intercept(MotionEvent ev, View view, float boundingBoxTolerance){
if (boundingBoxTolerance < 1.0f) {
boundingBoxTolerance = 1.0f;
}
try {
if (ev != null && view != null) {
int coords[] = new int[2];
view.getLocationOnScreen(coords);
if (ev.getRawX() >= ((float)coords[0]) / boundingBoxTolerance && ev.getRawX() <= coords[0] + ((float) view.getWidth()) * boundingBoxTolerance) {
if(ev.getRawY() >= ((float)coords[1]) / boundingBoxTolerance && ev.getRawY() <= coords[1] + ((float) view.getHeight()) * boundingBoxTolerance)
return true;
}
}
}
catch (Exception e) {}
return false;
}
I guess you are using View Animations, i will prefer to use Property animations instead
excerpt from Android documentation (see highlighted)
The view animation system provides the capability to only animate View
objects, so if you wanted to animate non-View objects, you have to
implement your own code to do so. The view animation system is also
constrained in the fact that it only exposes a few aspects of a View
object to animate, such as the scaling and rotation of a View but not
the background color, for instance.
Another disadvantage of the view animation system is that it only
modified where the View was drawn, and not the actual View itself. For
instance, if you animated a button to move across the screen, the
button draws correctly, but the actual location where you can click
the button does not change, so you have to implement your own logic to
handle this.
With the property animation system, these constraints are completely
removed, and you can animate any property of any object (Views and
non-Views) and the object itself is actually modified. The property
animation system is also more robust in the way it carries out
animation. At a high level, you assign animators to the properties
that you want to animate, such as color, position, or size and can
define aspects of the animation such as interpolation and
synchronization of multiple animators.
The view animation system, however, takes less time to setup and
requires less code to write. If view animation accomplishes everything
that you need to do, or if your existing code already works the way
you want, there is no need to use the property animation system. It
also might make sense to use both animation systems for different
situations if the use case arises.
I can get the coordinates of the touch just fine from:
event.getX();
event.getY();
But I want to start from an origin point of 0,0.
So I can touch anywhere on the screen, and as I drag my finger upwards, it will increase the Y by increments of 1, as I drag my finger to the right, the X will increase by increments of 1. Movement to the left will decrease the X by -1, movement downwards will decrease the Y by increments of -1.
Is there a mathematical way to do this, or better yet a class or function?
Any guidance would be appreciated! Thanks!
just use:
event.getRawX();
event.getRawY();
that results in screen coordinates,
starting at 0,0 (upper left corner)
to width,height (lower right corner)
depending on device, but i think thats not new to you ;)
--- update ---
I think I've missunderstood you, sorry..
then try this:
int saved_x = -1;
int saved_y = -1;
#Override
public boolean onTouchEvent(MotionEvent event)
{
final int action = event.getAction();
final int pointer_index = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
int pid = event.getPointerId(pointer_index);
int x = (int)event.getX();
int y = (int)event.getY();
switch (action & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
saved_x = x;
saved_y = y;
break;
case MotionEvent.ACTION_MOVE:
int relative_x = x - saved_x;
int relative_y = y - saved_y;
//move right --> relative_x increases by 'm' pixels of movement
//move left --> relative_x decreases by 'm' pixels of movement
//move down --> relative_y increases by 'm' pixels of movement
//move up --> relative_y decreases by 'm' pixels of movement
//use it :D
break;
case MotionEvent.ACTION_UP:
saved_x = -1; //-1 indicates "no finger on screen" -- just a feature :)
saved_y = -1; //-1 indicates "no finger on screen" -- just a feature :)
break;
}
return true;
}
I hope this is now what you wanted :)