I have got an Activity with a function, where I can create a new ImageView.
I would like to move the ImageView, so implemented a new OnTouchListener. That is working great, but I would also like to add a LongClickListener and here is my problem:
My LongClickListener starts one time when I am moving the ImageView.
What can I do to fix this?
public ImageView neuesDefaultBild(int x, int y, int id){
ImageView iv=new ImageView(this);
iv.setImageResource(R.drawable.usericon);
iv.setId(id);
iv.setX(x);
iv.setY(y);
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.width=180;
params.height=130;
iv.setLayoutParams(params);
iv.setLongClickable(true);
iv.setFocusable(true);
iv.setFocusableInTouchMode(true);
iv.setEnabled(true);
iv.setOnTouchListener(new View.OnTouchListener(){
public boolean onTouch(View v, MotionEvent event) {
boolean defaultResult = v.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
//Get the coords from the Event
int x_cord = (int) event.getRawX();
int y_cord = (int) event.getRawY();
v.setX(x_cord-90);
v.setY(y_cord-130);
return true;
default:
return defaultResult;
}
return false;
}
});
iv.setOnLongClickListener(new View.OnLongClickListener() {
public boolean onLongClick(View v) {
Toast.makeText(getApplicationContext(), "Long!!", Toast.LENGTH_SHORT).show();
return false;
}
});
return iv;
}
OnclickListener can be set using OnTouchListener itself
Just set a flag
private int boolean onClick;
switch (event.getAction())
{
case MotionEvent. ACTION_DOWN:
{
onClick = true;
break ;
}
case MotionEvent. ACTION_MOVE:
{
onClick = false;
break ;
}
case MotionEvent. ACTION_UP:
{
if(onClick)
{
//Call your own click listener
}
break;
}
}
Related
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;
}
I have a linearlayout filled with programmatically created views. I have implemented drag and drop code (shown below) so that if I touch down on the right side of any of the views, they start in drag mode. The drag mode itself works fine but the problem I am having is finding out where to place the view on release so that it falls in the expected place. Thanks for the help in advance!
Here is the onTouchMethod of the view(s):
view.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (Math.round(event.getX()) >= 720) {
ClipData data = ClipData.newPlainText("", "");
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v);
v.startDrag(data, shadowBuilder, v, 0);
v.setVisibility(View.INVISIBLE);
return true;
} else {
return false;
}
default:
return false;
}
}
});
and here is the onDragMethod that is also placed on the views:
view.setOnDragListener(new View.OnDragListener() {
#Override
public boolean onDrag(View v, DragEvent event) {
View view = (View) event.getLocalState();
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
break;
case DragEvent.ACTION_DROP:
LinearLayout owner = (LinearLayout) view.getParent();
owner.removeView(view);
owner.addView(view, getNewViewPosition(fillView.indexOfChild(v), Math.round(v.getY()), Math.round(event.getY())));
view.setVisibility(View.VISIBLE);
break;
}
return true;
}
});
finally here is the getNewViewPosition method:
public int getNewViewPosition(int currentPosition, int stationaryY, int floatingY) {
Toast.makeText(this, stationaryY + " and then " + floatingY, Toast.LENGTH_SHORT).show();
if (floatingY - stationaryY <= 15) {
return currentPosition - 1;
} else {
return currentPosition + 1;
}
}
I figured it out, since I knew that my views had a height of 52 I was able to formulate this code:
public int getNewViewPosition(int currentPosition, int stationaryY, int floatingY) {
if (floatingY - stationaryY >= 13) {
return currentPosition - 1;
} else if (floatingY - stationaryY <= 39) {
return currentPosition + 1;
} else
return currentPosition;
}
Hey Friends help me to achieve the objective. I am newbie to the android development and the only thing I want to do is that I am trying to drag a button and drop it onto the other View(i.e RelativeLayout) the very first thing I have done the code for the drag.
rootView = inflater.inflate(R.layout.fragment_game_map,container,false);
button1 = (Button) rootView.findViewById(R.id.button1);
button1.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
ClipData.Item item = new ClipData.Item((CharSequence)v.getTag());
String[] mimeTypes = {ClipDescription.MIMETYPE_TEXT_PLAIN};
ClipData dragData = new ClipData(v.getTag().toString(),mimeTypes, item);
View.DragShadowBuilder myShadow = new View.DragShadowBuilder(button1);
v.startDrag(dragData,myShadow,null,0);
return true;
}
});
button1.setOnDragListener(new View.OnDragListener() {
#Override
public boolean onDrag(View v, DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
layoutParams = (RelativeLayout.LayoutParams) v.getLayoutParams();
Log.d(TAG, "Action is DragEvent.ACTION_DRAG_STARTED");
// Do nothing
break;
case DragEvent.ACTION_DRAG_ENTERED:
Log.d(TAG, "Action is DragEvent.ACTION_DRAG_ENTERED");
int x_cord = (int) event.getX();
int y_cord = (int) event.getY();
break;
case DragEvent.ACTION_DRAG_EXITED:
Log.d(TAG, "Action is DragEvent.ACTION_DRAG_EXITED");
x_cord = (int) event.getX();
y_cord = (int) event.getY();
layoutParams.leftMargin = x_cord;
layoutParams.topMargin = y_cord;
v.setLayoutParams(layoutParams);
break;
case DragEvent.ACTION_DRAG_LOCATION:
Log.d(TAG, "Action is DragEvent.ACTION_DRAG_LOCATION");
x_cord = (int) event.getX();
y_cord = (int) event.getY();
break;
case DragEvent.ACTION_DRAG_ENDED:
Log.d(TAG, "Action is DragEvent.ACTION_DRAG_ENDED");
// Do nothing
break;
case DragEvent.ACTION_DROP:
Log.d(TAG, "ACTION_DROP event");
// Do nothing
break;
default:
break;
}
return true;
}
});
button1.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
ClipData data = ClipData.newPlainText("", "");
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(button1);
button1.startDrag(data, shadowBuilder, button1, 0);
button1.setVisibility(View.INVISIBLE);
return true;
}
else
{
return false;
}
}
});
return rootView;
}
but the second thing I don't have Idea to do.. that is I want to drop it onto the RelativeLayout but the RelativeLayout can only allow one button to be drop on it.
You missing the point of DragLiatenr. DragListenr listen to event of dragging, and handle them properly, so if your RelativeLayout not register to DragEvent he can't handle them.
Actually for what you asking you just need to listen for ACTION_DROP, and return true for all the others events.
Your could should like something like:
final RelativeLayout container; //You need to initialize your Relativelayout here
container.setOnDragListener(new View.OnDragListener() {
#Override
public boolean onDrag(View v, DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DROP:
Log.d(TAG, "ACTION_DROP event");
((ViewGroup)v.getParent()).removeView(v); //you must first remove view from it former container
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
container.addView(v, params); // of course you need to modify params for your need
return true;
break;
default:
return true;
}
}
});
Also why you put onTouchListenr you never use?
I implemented a Camera.PreviewCallback in my android app to grab frames from the textureview and it works fine. i would like to know to to keep repeating this callback when a button is pressed down.
My code is below:
This is the code for the Camera.PreviewCallback:
Camera.PreviewCallback previewCallback = new Camera.PreviewCallback() {
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
Camera.Parameters parameters = camera.getParameters();
Size size = parameters.getPreviewSize();
YuvImage image = new YuvImage(data, parameters.getPreviewFormat(),size.width, size.height, null);
image.compressToJpeg(new Rect(0, 0, image.getWidth(), image.getHeight()), 90, out);
byte[] imageBytes = out.toByteArray();
Bitmap images = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
rev = new ArrayList<Bitmap>();
rev.add(images);
}
};
This is the code to handle Button press down:
button.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
mCamera.setPreviewCallback(previewCallback);
break;
case MotionEvent.ACTION_UP:
// End
break;
}
return false;
}
});
Again how do i make the callback repeat when the button is pressed down.Thanks
First we need a way to check if the Button is still pressed. For that purpose define a new boolean field called buttonPressed:
private boolean buttonPressed = false;
Next we define the Runnable we want to run as long as the Button is pressed:
private final Runnable buttonPressedRunnable = new Runnable() {
#Override
public void run() {
// Check if the Button is pressed
if(buttonPressed) {
// Insert whatever you want to do while the Button is pressed here
...
// Repost the Runnable with an appropriate delay
button.postDelayed(this, 100);
}
}
};
Finally in your OnTouchListener you need to set buttonPressed to true in ACTION_DOWN and again to false in ACTION_UP. You also need to post the buttonPressedRunnable once, as long as the Button is pressed it will repost itself.
button.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
mCamera.setPreviewCallback(previewCallback);
buttonPressed = true;
button.post(buttonPressedRunnable);
break;
case MotionEvent.ACTION_UP:
buttonPressed = false;
break;
}
return false;
}
});
I have a LinearLayout with a mapView, zoomIn button, zoomOut button.
the app receives touchevents and it is supposed to manage the LinearLayout children with the given information (X coordinate, Y coordinate , type of touch event)
I am able to zoomIn and ZoomOut with the following code, but I am not able to move the map:
#Override
public boolean onTouch(View arg0, MotionEvent event) {
int action = event.getAction();
switch(action)
{
case MotionEvent.ACTION_DOWN:
savedTouchedX = event.getX();
savedTouchedY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
doPanning(event, mapView);
break;
case MotionEvent.ACTION_UP:
doPanning(event, mapView);
savedTouchedX = -1;
savedTouchedY = -1;
break;
default:
break;
}
return true;
}
});
//move mapView
private boolean doPanning(MotionEvent e, MapView mapView)
{
if(savedTouchedX >= 0 && savedTouchedY >= 0)
{
IGeoPoint mapCenter = mapView.getMapCenter();
GeoPoint panToCenter = new GeoPoint((int)(mapCenter.getLatitudeE6() + (e.getY() - savedTouchedY) * 1E5),(int)(mapCenter.getLongitudeE6() - (e.getX() - savedTouchedX) * 1E5));
mapView.getController().setCenter(panToCenter);
}
savedTouchedX = e.getX();
savedTouchedY = e.getY();
return true;
}
....
public void lookForButton(String msg){
String[] strArray = msg.split(" ");
final MotionEvent m;
int x=Integer.valueOf(strArray[1]);
int y=Integer.valueOf(strArray[2]);
int type=Integer.valueOf(strArray[3]);
switch (type){
case 2:
m = MotionEvent.obtain(226707,226707,0/*ACTION_DOWN*/,x,y,0);
runOnUiThread(new Runnable() {
public void run() {
memecontentView.dispatchTouchEvent(m);
}
});
break;
case 3:
m = MotionEvent.obtain(226707,226707,1/*ACTION_UP*/,x,y,0);
runOnUiThread(new Runnable() {
public void run() {
memecontentView.dispatchTouchEvent(m);
}
});
break;
case 5:
m = MotionEvent.obtain(226707,226707,2/*ACTION_MOVE*/,x,y,0);
runOnUiThread(new Runnable() {
public void run() {
memecontentView.dispatchTouchEvent(m);
}
});
break;
}
}
public void ZoomInButton(View v){
mapView.getController().zoomIn();
}
public void ZoomOutButton(View v){
mapView.getController().zoomOut();
}
How can I programmatically move mapview with the given information (X coordinate, Y coordinate , type of touch event)?
You can call mapView.scrollTo(x, y).
Another possibility is mapView.getController().animateTo() (with animation) or mapView.getController().setCenter() (without animation).
It takes an IGeoPoint as a parameter which you can instantiate with your coordinates:
new GeoPoint(latitude, longitude)