Drag and fling map - java

Hello,
I am trying to implement dynamic map (View) into my application and I need to make it's movement behave like Google Map has. So It has to do both, scroll and fling. (I have reasons for not using the actual Google Maps).
At First time, I handled dragging and flinging of map by it's Scroll. But it jittered, because void View.setScrollX(int) can't have parameter of float and so it isn't smooth enough.
At Second, I tried Translation for moving of the map, but even when dragging alone was working and fling alone was working, together it did strange behaviour on fling.
My question is: How to make Scroll and Fling work together well? I will be glad of every advice or snipped of code :)
This is the second solution:
ImageView img;
String msg = "My LOG";
float firstPosX = 0;
float firstPosY = 0;
int touchCount;
FlingAnimation flingAnimX;
FlingAnimation flingAnimY;
GestureDetector gestureDetector;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img = (ImageView) findViewById(R.id.imageView);
gestureDetector = new GestureDetector(getApplicationContext(), mGestureListener);
img.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
touchCount = event.getPointerCount();
//Stops Fling, so on the new touch it dont continue
if (flingAnimX != null) {
flingAnimX.cancel();
}
if (flingAnimY != null) {
flingAnimY.cancel();
}
if (touchCount == 1) {
float deltaPosX = 0;
float deltaPosY = 0;
if (event.getAction() == MotionEvent.ACTION_DOWN) {
firstPosX = event.getX();
firstPosY = event.getY();
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
deltaPosX = -firstPosX + event.getX();
deltaPosY = -firstPosY + event.getY();
img.setTranslationX(deltaPosX + img.getTranslationX());
img.setTranslationY(deltaPosY + img.getTranslationY());
}
}
gestureDetector.onTouchEvent(event);
return true;
}
});
}
GestureDetector.SimpleOnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2,
float velocityX, float velocityY) {
if (touchCount == 1) {
flingAnimX = new FlingAnimation(img, DynamicAnimation.TRANSLATION_X)
.setStartVelocity(velocityX);
flingAnimX.start();
flingAnimY = new FlingAnimation(img, DynamicAnimation.TRANSLATION_Y)
.setStartVelocity(velocityY);
flingAnimY.start();
}
return true;
}
};

Related

How to make draggable and zoomable image in android?

I'm currently creating my own game and I'm finding a way to recreate some sort of Clash of Clans kind of functionality where you can zoom in and out and drag the view of the screen these is what so far, I've done and it's kind of close to it I guess any other recommendations.
Functionality for it to zoom
image = (ImageView) findViewById(R.id.imageView);
sgd = new ScaleGestureDetector(this, new ScaleListener());
#Override
public boolean onTouchEvent(MotionEvent event) {
sgd.onTouchEvent(event);
return super.onTouchEvent(event);
}
class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener{
#Override
public boolean onScale(ScaleGestureDetector detector) {
FACTOR *= detector.getScaleFactor();
FACTOR = Math.max(.01f,Math.min(FACTOR, 10.f));
image.setScaleX(FACTOR);
image.setScaleY(FACTOR);
return true;
}
}
For it to drag
image.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getActionMasked()) {
//checks if the user place finger in the screen
case MotionEvent.ACTION_DOWN:
xDown = motionEvent.getX();
yDown = motionEvent.getY();
break;
//checks if the user moves thier finger
case MotionEvent.ACTION_MOVE:
float movedX, movedY;
movedX = motionEvent.getX();
movedY = motionEvent.getY();
//calculate how much the user move their fingers
float distanceX = movedX - xDown;
float distanceY = movedY - yDown;
//will move the view to that position
image.setX(image.getX() + distanceX);
image.setY(image.getY() + distanceY);
break;
}
return true;
}
});
}

Android, java, view.setOnTouchListener

I had a recyclerview with an adapter and everything was cool. I added view.setOnTouchListener so that I could scroll this recyclerview along with animation and other elements on 1 screen from left to right. But after that, scrolling up and down broke in recyclerview, and onclicklistener on the elements inside it stopped working. What to do and how to fix this conflict?
At the moment I can put return false in the public boolean onTouch (View v, MotionEvent event) method; instead of return gestureDetector.onTouchEvent (event); and get a working scrolling up and down back, but left-right stops working. I can do simultaneous scrolling as in ios, when scrolling of tablecloths and collections did not break when adding the svayp to the left-right.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
view.setOnTouchListener(new OnSwipeTouchListener(MainActivity.this) {
public void onSwipeRight() {
choseold = chosenow;
chosenow = chosenow - 1;
if (chosenow <= 0) {
chosenow = 5;
choseold = 6;
}
swipe();
}
public void onSwipeLeft() {
choseold = chosenow;
chosenow = chosenow + 1;
if (chosenow >= 6) {
chosenow = 1;
choseold = 0;
}
swipe();
}
});
view.setFocusableInTouchMode(true);
MyAdapterlang = new MyAdapterLang(MainActivity.this, yaziki1, yaziki2, flagi);
RVlang.setAdapter(MyAdapterlang);
mLayoutManager = new LinearLayoutManager(this);
RV1.setLayoutManager(mLayoutManager);
MyAdapter = new MyAdapterApps(MainActivity.this, childs, childs2);
RV1.setAdapter(MyAdapter);
}
}
class OnSwipeTouchListener implements View.OnTouchListener {
private final GestureDetector gestureDetector;
public OnSwipeTouchListener (Context ctx){
gestureDetector = new GestureDetector(ctx, new GestureListener());
}
#Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
//return false;
}
/*public boolean onTouch(final View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
y1 = event.getY();
break;
case MotionEvent.ACTION_MOVE:
y2 = event.getY();
float deltaY = y2 - y1;
if (Math.abs(deltaY) > MIN_DISTANCE) {
return false;
} else {
return gestureDetector.onTouchEvent(event);
}
}
return gestureDetector.onTouchEvent(event);
}
private float y1, y2;
private static final int MIN_DISTANCE = 50;*/
private final class GestureListener extends GestureDetector.SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
#Override
public boolean onDown(MotionEvent e) {
return true;
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
onSwipeRight();
} else {
onSwipeLeft();
}
return true;
}
}
} catch (Exception exception) {
exception.printStackTrace();
}
return false;
}
}
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
}
Here in ios, for example, is very simple and does not break the scrolling of collections:
- (void)viewDidLoad {
UISwipeGestureRecognizer * swipeleft=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(swipeleft:)];
swipeleft.direction=UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:swipeleft];
UISwipeGestureRecognizer * swiperight=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(swiperight:)];
swiperight.direction=UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:swiperight];
}
-(void)swipeleft:(UISwipeGestureRecognizer*)gestureRecognizer
{
if (self.currentnew <= 3) {
self.whatpress = 1;
[self.buttonnew sendActionsForControlEvents:UIControlEventTouchUpInside];
}
}
-(void)swiperight:(UISwipeGestureRecognizer*)gestureRecognizer
{
if ((self.currentnew >= 1) && (self.currentnew <= 3)) {
self.whatpress = 2;
[self.buttonnew sendActionsForControlEvents:UIControlEventTouchUpInside];
}
}
Here is a video:
https://2ch.hk/pr/src/1314926/15464190246250.mp4 https://2ch.hk/pr/src/1314926/15464193253190.mp4
If you only want to hook into default touch handling implementation you must return false here
#Override
public boolean onTouch(View v, MotionEvent event) {
gestureDetector.onTouchEvent(event);//Idk if it is needed or not - out of scope
return false;
}
Otherwise touch event will be considered as consumed and wont be propagated to other handlers (that handles scrolling, clicking etc. - all that stuff that stops working for you)

how to Get coordinates from Custom view android

I have some custom view with onTouchEvent where I'm setting mX and mY .
mx=event.getX();
my=event.getY();
this is for getting the drawing path of touch event - working great, and I can
see the coordinates in my text view which is defined in the main activity.
I want to use this 2 attributes in my Main activity layout
for setting the background color
for example
if (mx > 1000 && my > 100 ){
set color
}
but it seems that mx and my are not getting any values
what i tried is
custom_view paintview = (custom_view) findViewById(R.id.custum_view_id)
float mx =paintview.getmx();
float my =paintview.getmy();
maybe i didn't defined the getmx correctly in custom view ?
public float getmx(){
return mx;
}
i'm new in Java and android so be easy with me :)
adding MainActiviy.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Drawing - custom view
drawView = (Drawing) findViewById(R.id.drawing);
findCoordinates();
TextView Coordinates = (TextView) findViewById(R.id.CNcoordinates);
//Coordinates - message with coordinates
paintView.setTextView(Coordinates);
}
private Drawing drawView;
public void findCoordinates() {
Drawing paintView = (Drawing) findViewById(R.id.drawing);
float xX = drawView.getmX();
float yY = drawView.getmY();
int nColor = Color.BLUE;
View buttonmove1 = findViewById(R.id.layoutMove);
if (Math.abs(xX) > 1000 && Math.abs(yY) > 1000) {
buttonmove1.setBackgroundColor(nColor);
}
}
the coordinates come from:
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
canvas.drawPath(drawPath, drawPaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
mX = event.getX();
mY = event.getY();
View buttonmove = findViewById(R.id.drawing);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
drawPath.moveTo(mX, mY);
if(myCoordinates!=null){
myCoordinates.setText(":" + mX + " , " + ":" + mY);
}
break;
public void setTextView(TextView tv){
myCoordinates = tv;
}
Use interface or callback after finishing your touchEvent. you have to re-call your
findCoordinates()
so it will update your UI respect to new values.
i succeed to use OnViewTouchListener as a callback:
adding the method in custom view:
private OnViewTouchListener OnViewTouchListener;
public interface OnViewTouchListener {
public void onViewTouched (float x, float y, boolean touched);
}
public void setOnViewTouchListener (OnViewTouchListener listener){
OnViewTouchListener = listener;
}

Resize ImageView with only one finger movement instead of two

I'm trying to change an ImageView's height with only one finger movement (upside or downside). The code below changes height with two fingers (like pinching or reverse). How can I modify this code to do what I want? Thanks.
public class MainActivity extends Activity {
private ImageView iv;
private Matrix matrix = new Matrix();
private float scale = 1f;
private ScaleGestureDetector SGD;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = iv=(ImageView)findViewById(R.id.imageView);
SGD = new ScaleGestureDetector(this, new ScaleListener());
}
public boolean onTouchEvent(MotionEvent ev) {
SGD.onTouchEvent(ev);
return true;
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener
{
#Override
public boolean onScale(ScaleGestureDetector detector) {
scale *= detector.getScaleFactor();
scale = Math.max(0.1f, Math.min(scale, 5.0f));
matrix.setScale(1, scale);
iv.setImageMatrix(matrix);
return true;
}
}
}
Use GestureDetector for scroll:
#Bind(R.id.container)
ViewGroup container;
#Bind(R.id.image)
ImageView image;
private GestureDetectorCompat detector;
private float yscale = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
ButterKnife.bind(this);
image.setScaleType(ImageView.ScaleType.MATRIX);
detector = new GestureDetectorCompat(this, new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
Matrix m = new Matrix();
yscale += distanceY / container.getHeight();
m.setScale(1, yscale, 0, 0);
image.setImageMatrix(m);
return true;
}
});
}
#Override
public boolean onTouchEvent(MotionEvent event) {
return detector.onTouchEvent(event);
} detector.onTouchEvent(event);
}
change
public boolean onTouchEvent(MotionEvent ev) {
SGD.onTouchEvent(ev);
return true;
}
to
public boolean onTouchEvent(MotionEvent ev) {
switch(ev.getActionMasked()) {
case MotionEvent.ACTION_DOWN, case MotionEvent.ACTION_UP:
SGD.onTouchEvent(ev);
break;
return true;
}
This code snipet should help you to detect up and down
private VelocityTracker mVelocityTracker = null;
#Override
public boolean onTouchEvent(MotionEvent event) {
int index = event.getActionIndex();
int action = event.getActionMasked();
int pointerId = event.getPointerId(index);
switch(action) {
case MotionEvent.ACTION_DOWN:
if(mVelocityTracker == null) {
// Retrieve a new VelocityTracker object to watch the velocity of a motion.
mVelocityTracker = VelocityTracker.obtain();
}
else {
// Reset the velocity tracker back to its initial state.
mVelocityTracker.clear();
}
// Add a user's movement to the tracker.
mVelocityTracker.addMovement(event);
break;
case MotionEvent.ACTION_MOVE:
mVelocityTracker.addMovement(event);
// When you want to determine the velocity, call
// computeCurrentVelocity(). Then call getXVelocity()
// and getYVelocity() to retrieve the velocity for each pointer ID.
mVelocityTracker.computeCurrentVelocity(1000);
// Log velocity of pixels per second
// Best practice to use VelocityTrackerCompat where possible.
Log.d("", "X velocity: " +
VelocityTrackerCompat.getXVelocity(mVelocityTracker,
pointerId));
Log.d("", "Y velocity: " +
VelocityTrackerCompat.getYVelocity(mVelocityTracker,
pointerId));
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
// Return a VelocityTracker object back to be re-used by others.
mVelocityTracker.recycle();
break;
}
return true;
}

getView of element that you're swiping (onFling) for android?

I'm making a list with a linearLayout and adding TextViews depending on how many items I got in the database. Problem is that I want to be able to delete an item when I swipe left on the list. I was just wondering how to get the element (view) that you're swiping? Here's the code I got for adding a TextView.
for(int i = 0; i < nrOfTodos; i++) {
TextView v = new TextView(this);
String title = todos.get(i).getTitle();
System.out.println(title);
v.setText(title);
v.setHeight(listItemSize);
v.setAllCaps(true);
v.setTextColor(Color.parseColor("#FFD9A7"));
v.setTextSize(listItemSize/6);
v.setHorizontallyScrolling(false);
v.setMaxLines(1);
v.setEllipsize(TruncateAt.END);
v.setPadding(30, 50, 0, 0);
v.setId(i);
todoViews.add(v);
v.setOnTouchListener(new OnSwipeTouchListener(this) {
#Override
public void onSwipeLeft() {
/*
*
*
* TODO!!! NEXT PART OF MY PLAN TO WORLD DOMINATION!
*
*
*/
}
});
if(i%2 == 1) {
v.setBackgroundColor(Color.parseColor("#11FFFFFF"));
}
ll.addView(v, i);
}
and I also have this
public class OnSwipeTouchListener implements OnTouchListener {
private final GestureDetector gestureDetector;
public OnSwipeTouchListener(Context context) {
gestureDetector = new GestureDetector(context, new GestureListener());
}
public void onSwipeLeft() {
}
public void onSwipeRight() {
}
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
private final class GestureListener extends SimpleOnGestureListener {
private static final int SWIPE_DISTANCE_THRESHOLD = 50;
private static final int SWIPE_VELOCITY_THRESHOLD = 10;
#Override
public boolean onDown(MotionEvent e) {
//always return true since all gestures always begin with onDown and <br>
//if this returns false, the framework won't try to pick up onFling for example.
return true;
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
float distanceX = e2.getX() - e1.getX();
float distanceY = e2.getY() - e1.getY();
if (Math.abs(distanceX) > Math.abs(distanceY) && Math.abs(distanceX) > SWIPE_DISTANCE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (distanceX > 0)
onSwipeRight();
else
onSwipeLeft();
return true;
}
return false;
}
}
}
but I can't figure out how to actually get the view, get the titletext and remove that from the database (I can remove from the database, but I can't get what item was swiped ^^).
Any ideas would be greatly appreciated.
You may refer to this sample application Swipe_To_Delete
You may use ListView to list your data items which are got from the db.
Then modify the getSwipeItem() method in the MainActivity of the example, as follows.
#Override
public void getSwipeItem(boolean isRight, int position) {
[List_Of_Items].remove(position);
[Your_Adapter].notifyDataSetChanged();
}

Categories

Resources