I am a newbie in Andoird.
In my case, I have a scenario that when click certain part of an image it will trigger onclick events. I tried to detecte the position when the onTouch is fired, it works, but I think it's not a standard implementation, so what is the best practice for such case?
thanks.
here is codes like:
imgView.setOnTouchListener((OnTouchListener) new OnTouchListener(){
public boolean onTouch(View v, MotionEvent event) {
if(isIn(event.getX(), event.getY(), 124,3,221,36)){
ShowMemberInfo(R.string.app_m01);
} else if(isIn(event.getX(), event.getY(), 8,155,72,181)){
..
}
return true;
}
private boolean isIn(float x, float y, int fx, int fy, int tx, int ty) {
return x<tx && x > fx && y<ty && y>fy;
}
Try to use ImageButton
Simply implement onClickListener() for your ImageView.
Easiest way to implement onClick event is to include android:onClickMe="methodName" inside your <ImageView> in XML layout and define that method inside your activity file.
For example:
public void methodName(View v)
{
....
....
// do whatever you want for click even ton imageview
}
If you want to detect the position where user touched(Relative to the ImageView user touched), you can get the touch point from MotionEvent object.
Try to register a touch event listener for the ImageView and get the touched point position from MotionEvent object's getX() and getY() methods when touch event is triggered. And then define a rectangular area and using contains() to check whether the touch point is inside the area or not.
ImageView img = new ImageView(this);
img.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.w("Hit test", "is hit? "+isIn(event.getX(),event.getY(),0,0,120,120));
return false;
}
});
private boolean isIn(float x, float y, int fx, int fy, int tx, int ty){
return new Rect(fx,fy,tx,ty).contains((int)x,(int)y);
}
Hope this will be helpful to you. :)
Related
I have a custom View, which inherits from GestureOverlayView, and I want to log all the MotionEvent passed to this view.
It works well, but I can't get the MotionEvent when my gesture starts on an interactive layout widget (Button, TextEdit....)
Is there a way to bypass this behaviour?
Since you didn't mention any snipped code of yours,I make 2 different solution hopefully is help you
One way will be passing your widget to as View to method and call OnTouchListener
button.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
break;
}
case MotionEvent.ACTION_UP: {
break;
}
case MotionEvent.ACTION_CANCEL:{
break;
}
}
return false;
}
});
Another way could be manually creating a MotionEvent using custom constructor
like this:
static public CustomMotionEvent obtain(long downTime, long eventTime, int action,
float x, float y, int State) {
}
According to API
Create a new MotionEvent, filling in a subset of the basic motion
values. Those not specified here are: device id (always 0), pressure
and size (always 1), x and y precision (always 1), and edgeFlags
(always 0).
API
I am trying to implement my own drag and drop with touch view events. I want to trigger dragging with long click, in onLongClick i create view shadow as bitmap and this bitmap is set to imageview. This imageview i want to drag. My problem is, that imageview is not responding to touch events immediately after that long click event. I have to stop touching screen and tap to imageview again and then my image is moving.
Some relevant code:
mCategoryNews.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
v.setVisibility(View.INVISIBLE);
ImageView shadow = (ImageView) getView().findViewById(R.id.imgViewShadow);
shadow.setLayoutParams(new FrameLayout.LayoutParams(v.getWidth(), v.getHeight()));
shadow.setImageBitmap(Utils.loadBitmapFromView(v));
shadow.bringToFront();
((FrameLayout.LayoutParams) shadow.getLayoutParams()).leftMargin = rowCategories1.getLeft();
((FrameLayout.LayoutParams) shadow.getLayoutParams()).topMargin = rowCategories1.getTop();
return true;
}
});
private View.OnTouchListener mDragShadowTouchListener = new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.d(TAG, "onTouch");
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
Log.d(TAG, "action move");
int x = (int) event.getRawX();//- rowCategories1.getLeft() - v.getWidth() / 2;
int y = (int) event.getRawY();//- rowCategories1.getTop() - v.getHeight();
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(mRowWidth / 2, mRowHeight);
params.setMargins(x, y, 0, 0);
v.setLayoutParams(params);
break;
case MotionEvent.ACTION_DOWN:
break;
}
return true;
}
};
no log output is present while i am still holding finger on screen after long tap.
This is a late answer, but I had a similar problem and found this solution:
Pass the MotionEvent to the view that should take it over via the dispatchTouchEvent method.
View myView = findViewById(R.id.myView);
#Override
public boolean onTouchEvent(MotionEvent event) {
myView.dispatchTouchEvent(event);
}
After the MotionEvent is passed, myView takes over and responds to new touch events.
If you return true in onLongClick() it means the callback has consumed the event and thus it is not propagated further. If you return false, then it will reach down to the child views. (I assume the touch listener is set on the shadow ImageView).
I believe to delegate try returning false
I am currently working on galaxy s4 app, in which i want moving image with moving finger, but how to implement this onHoverListener. Please Help.
And thanks in advance.
you can implementing onTouchListener() to your imageView like below:
img = ((ImageView) findViewById(R.id.img_arrow));
img.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent motionEvent) {
int rawX = (int) motionEvent.getX();
int rawY = (int) motionEvent.getY();
if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
TranslateAnimation anim = new TranslateAnimation(rawX, rawY, 0, 0);
anim.setDuration(500L);
img.startAnimation(anim);
}
return true;
}
});
Here we are applying TranslationAnimation to our imageView img
Instead of hoverListener implement touch listener on ur image and also implement touchevent in ur activity. then u can use OnTouchEvent's actionMove.
when user doing actionMove find the coordinates using motionEvent object and translate ur view to those coordinates using translate animation.this will give look as if u r moving the image.
In Android, we can set OnClickListeners for views.
But how do we intercept the location of the touch event?
there is method in Activity
public boolean onTouchEvent(MotionEvent event){
int action = event.getAction();
int x = event.getX()
int y = event.getY();
return yourBoolean;
}
Edit: Or you can define OnTouchListener for any View and can use its method
public abstract boolean onTouch(View v, MotionEvent event);
Edit2: the x and y values depends upon the method call. If you use onTouchEvent() of Activity then it indicates that no View consumes the touch event see documentation and if you handle it on any View then the x and y will be according to the View's area.
You can set the onTouchListener for the same view. The MotionEvent will have the x and y.
While similar questions have been asked in the past they don't seem to really have been answered which might be due to confusion as to what's being asked.
Put simply, I'd like to detect which view is being entered as your finger slides over the screen. The best example of this in action is the soft keyboard on any android phone. When you press any key it shows up as a popup to tell you what letter is under your finger. If you now move your finger over the keyboard in a single gesture the various letters pop up as you move over the various letters of the alphabet.
What listeners are used for this type of behaviour. I've tried OnTouchListeners but they seem to be only when you 'touch' the button as opposed to 'finger past' them
Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {doStuff();}
});
button.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
doStuff();
return false;
}
});
OnFocusChangeListener don't help either.
create a Layout
add Views to your Layout
set the setOnTouchListener to your Layout
override the onTouch method with the following:
public boolean onTouch(View v, MotionEvent event)
{
LinearLayout layout = (LinearLayout)v;
for(int i =0; i< layout.getChildCount(); i++)
{
View view = layout.getChildAt(i);
Rect outRect = new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
if(outRect.contains((int)event.getX(), (int)event.getY()))
{
// over a View
}
}
}
EDIT:
I saw keyboard. I guess, it just one view and coordinates of every letter is known. So you can easily compute which letter the user slides through
AND NOW THE ANSWER:
I'm not sure, but probably this code helps your.
It's so far away, I wrote it for me. But the idea is following.
If I remember right, there is no gesturedetector for views, but you can combine touchlistener of the view with geturelistener of your activity.
Once you've touched your view, you have
private GestureDetector mGestureDetector;
// x and y coordinates within our view
private static float sideIndexX;
private static float sideIndexY;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
...
mGestureDetector = new GestureDetector(this, new SideIndexGestureListener());
}
class MyGestureListener extends
GestureDetector.SimpleOnGestureListener
{
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY)
{
// we know already coordinates of first touch
// we know as well a scroll distance
sideIndexX = sideIndexX - distanceX;
sideIndexY = sideIndexY - distanceY;
// when the user scrolls within our side index
// we can show for every position in it a proper
// item in the country list
if (sideIndexX >= 0 && sideIndexY >= 0)
{
doStuff();
}
return super.onScroll(e1, e2, distanceX, distanceY);
}
}
button.setOnTouchListener(new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
// now you know coordinates of touch
// store them
sideIndexX = event.getX();
sideIndexY = event.getY();
doStuff();
return false;
}
});
You may want to try GestureDetector.
http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html
it's geared to multitouch, but this is a good start toward understanding android touch/gestures, next stop, api docs/samples
The simple answer is you can't - not like the iPhone when in accessibility mode.
Until Ice Cream Sandwich that is. It now has the iPhone-like capability of being able to identify elements under your finger without having to lift it.
It's fairly straight forward to handle this manually.
Using your parent layout as the onTouchListener (in the following example, I extend a RelativeLayout), you can check for collisions between a MotionEvent and the child Views using simple co-ordinate comparison logic:
/** Returns the View colliding with the TouchEvent. */
private final View getCollisionWith(final MotionEvent pMotionEvent) {
// Declare the LocationBuffer.
final int[] lLocationBuffer = new int[2];
// Iterate the children.
for(int i = 0; i < this.getChildCount(); i++) { /** TODO: Order. */
// Fetch the child View.
final View lView = this.getChildAt(i);
// Fetch the View's location.
lView.getLocationOnScreen(lLocationBuffer);
// Is the View colliding?
if(pMotionEvent.getRawX() > lLocationBuffer[0] && pMotionEvent.getRawX() < lLocationBuffer[0] + lView.getWidth() && pMotionEvent.getRawY() > lLocationBuffer[1] && pMotionEvent.getRawY() < lLocationBuffer[1] + lView.getHeight()) {
// Return the colliding View.
return lView;
}
}
// We couldn't find a colliding View.
return null;
}
Calls to getCollisionWith will return View references that may be manipulated arbitrarily.