How to terminate an Activity in Adroid on touch. Here i shows a view which is described in details.xml. I need to dismiss the activity on touch. I tried the following code. But its not working. Any ideas?
public class Details extends Activity {
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.details);
}
public boolean onTouchEvent(MotionEvent event){
this.finish();
return true;
}
}
You should use
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
finish();
return super.dispatchTouchEvent(ev);
}
Your onTouchEvent() will only be called if no other views under the finger in the view hierarchy have consumed the event. This is uncommon, since many views do interact with touch events.
It is wrong to do stuff in onTouchEvent() without look at what the actual event is.
Generally you should implement a view that reacts to touches and does the appropriate thing.
I know its an old question but my solution is this if anyone need it:
I had the same problem so I solved it with giving my parent layout i.e(consraintLayout) an id then calling finish() in setOnClickListener() method and it worked.
View v = findViewById(R.id.validateLayout);
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
validateLayout is parent constraint layout of my activity.
any review is welcomed.
Also i want to know if suggestion of Addev is better then this code.
You didn't install a listener in onCreate(). Like:
findViewById(R.id.some_view).setOnTouchListener(this);
Related
When I try to add onTouchListner() to a button, it gets me the
Button has setOnTouchListener called on it but does not override
performClick
warning. Does anyone know how to fix it?
btnleftclick.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return false;
}
});
Error:
Custom view has setOnTouchListener called on it but does not override
performClick If a View that overrides onTouchEvent or uses an
OnTouchListener does not also implement performClick and call it when
clicks are detected, the View may not handle accessibility actions
properly. Logic handling the click actions should ideally be placed in
View#performClick as some accessibility services invoke performClick
when a click action should occur.
This warning comes up because Android wants to remind you to think about the blind or visually impaired people who may be using your app. I suggest you watch this video for a quick overview about what that is like.
The standard UI views (like Button, TextView, etc.) are all set up to provide blind users with appropriate feedback through Accessibility services. When you try to handle touch events yourself, you are in danger of forgetting to provide that feedback. This is what the warning is for.
Option 1: Create a custom view
Handling touch events is normally something that is done in a custom view. Don't dismiss this option too quickly. It's not really that difficult. Here is a full example of a TextView that is overridden to handle touch events:
public class CustomTextView extends AppCompatTextView {
public CustomTextView(Context context) {
super(context);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
return true;
case MotionEvent.ACTION_UP:
performClick();
return true;
}
return false;
}
// Because we call this from onTouchEvent, this code will be executed for both
// normal touch events and for when the system calls this using Accessibility
#Override
public boolean performClick() {
super.performClick();
doSomething();
return true;
}
private void doSomething() {
Toast.makeText(getContext(), "did something", Toast.LENGTH_SHORT).show();
}
}
Then you would just use it like this:
<com.example.myapp.CustomTextView
android:id="#+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="Click me to do something"/>
See my other answer for more details about making a custom view.
Option 2: Silencing the warning
Other times it might be better to just silence the warning. For example, I'm not sure what it is you want to do with a Button that you need touch events for. If you were to make a custom button and called performClick() in onTouchEvent like I did above for the custom TextView, then it would get called twice every time because Button already calls performClick().
Here are a couple reasons you might want to just silence the warning:
The work you are performing with your touch event is only visual. It doesn't affect the actual working of your app.
You are cold-hearted and don't care about making the world a better place for blind people.
You are too lazy to copy and paste the code I gave you in Option 1 above.
Add the following line to the beginning of the method to suppress the warning:
#SuppressLint("ClickableViewAccessibility")
For example:
#SuppressLint("ClickableViewAccessibility")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button myButton = findViewById(R.id.my_button);
myButton.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return false;
}
});
}
Solution:
Create a class that extends Button or whatever view you are using and override performClick()
class TouchableButton extends Button {
#Override
public boolean performClick() {
// do what you want
return true;
}
}
Now use this TouchableButton in xml and/or code and the warning will be gone!
Have you tried adding :
view.performClick()
or adding suppresslint annotation :
#SuppressLint("ClickableViewAccessibility")
?
Custom view controls may require non-standard touch event behavior.
For example, a custom control may use the onTouchEvent(MotionEvent)
listener method to detect the ACTION_DOWN and ACTION_UP events and
trigger a special click event. In order to maintain compatibility with
accessibility services, the code that handles this custom click event
must do the following:
Generate an appropriate AccessibilityEvent for the interpreted click
action. Enable accessibility services to perform the custom click
action for users who are not able to use a touch screen. To handle
these requirements in an efficient way, your code should override the
performClick() method, which must call the super implementation of
this method and then execute whatever actions are required by the
click event. When the custom click action is detected, that code
should then call your performClick() method.
https://developer.android.com/guide/topics/ui/accessibility/custom-views#custom-touch-events
At the point in the overridden OnTouchListener, where you interprete the MotionEvent as a click, call view.performClick(); (this will call onClick()).
It is to give the user feedback, e.g. in the form of a click sound.
you can suppress a warning
#SuppressLint("ClickableViewAccessibility")
or call performClick()
[Example]
I have an Activity with a ViewPager with 3 dynamically created Fragments. Each page has numerous Buttons and ImageButtons that activate on their own onTouch..MotionEvent.ACTION_DOWN.
The problem I'm having is that these buttons activate accidentally when am trying to swipe the ViewPager.
Can anyone recommend a way to keep this from happening?
Thanks
Josh
Instead of using onTouch..MotionEvent.ACTION_DOWN.
on the ImageButton I will make them implement;
.OnItemClickListener() /This ensures that only when clicked they will call the desired functionality, I suggest you to check it out this way and let me know.
Hope it helps, more info at; The Documentation for OnItemClickListener
I think that the flow you are following is not really good, the button also has the business code to handle the ACTION_DOWN touch event and the parent (ViewPager) always need handle touch event to detect the scroll events, so button will handle the ACTION_DOWN touch event first and then pass the touch to ViewPager.
You can move the business code into the OnClickListener of Button or another way you should let the button intercept the touch event and don't pass it to ViewPager (Parent View).
This can be easy to handle by customize the Viewpager class and add a variable in the custom ViewPager like this :
private boolean mTouchEnable = true;
#Override
public boolean onTouchEvent(MotionEvent arg0) {
if (!mTouchEnable) {
return false;
}
return super.onTouchEvent(arg0);
}
The button will need a reference to the viewPager and set the mTouchEnable = false in ACTION_DOWN and true in ACTION_UP
I did a viewpager of buttons and I was able to replicate the issue.
I solved to this way:
My buttons have a listener OnClickListener
optionButton.setOnClickListener(this);
public void onClick(View v) {
// your code here
}
Then I add this button to my customPagerAdapter
In your customViewPager you have to override the onInterceptTouchEvent method like this:
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
super.onInterceptTouchEvent(ev);
if (ev.getAction() == MotionEvent.ACTION_MOVE) {
return true;
}
else{
return false;
}
}
This code will intercept the MotionEvent.ACTION_MOVE in child views (return true) and won't intercept MotionEvent.ACTION_DOWN neither onClick event in the child views.
I have an extended view from SurfaceView like this:
public class MyView extends SurfaceView implements View.OnClickListener {
public MyView(Context context)
{
super(context);
mContext = context;
setOnClickListener(this);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case DOWN OR UP OR MOVE: <-- I do something here like move and drag and drop and
// any related behavior to MyView
}
invalidate();
return true;
}
Now I implemented OnClickListener and set it in my constructor.
OnClick method:
#Override
public void onClick(View v){
Log.e("as", "clicked");
}
But onClick method never not called. How can I solved that?
When replaced return true; with return super.onTouchEvent(event); my onClick method called, but when I want to move my custom view, onClick method again called and this is not my porpuse.
I want only when I tapped my custom view, onClick called, and when moved it not called.
Thanks In advance.
The problem is probably your onTouch Listener. You are overriding and not dealing with the onClick possibility. Additionally you are consuming the event with a return true so the onClick will never be called.
Remember that onClick is dealt in onTouchEvent implemented in the original view class.
You can check more info at:
http://developer.android.com/reference/android/view/View.html#onTouchEvent(android.view.MotionEvent)
where you can read:
public boolean onTouchEvent (MotionEvent event)
Added in API level 1 Implement this method to handle touch screen
motion events.
If this method is used to detect click actions, it is recommended that
the actions be performed by implementing and calling performClick().
This will ensure consistent system behavior, including:
obeying click sound preferences dispatching OnClickListener calls
handling ACTION_CLICK when accessibility features are enabled
Parameters event The motion event.
Returns True if the event was
handled, false otherwise.
Since you want to choose when click is performed, you should implement the performClick (like it states in the link I have referenced).
I want to open dialog activity on long touch of current activity.
I have accomplished it on simple touch event but i want to perform the same on long touch so that if user is touched the screen by mistake it will not affect on app.
How to acieve it?
Any help is appriciated.
You don't touch an activity but a view that is shown by your activity. You can set a View.OnLongClickListener with the setOnLongClickListener method.
I want to open dialog activity on long touch of current activity.
You can not set the event on click of an Activity you can set the event on the Particular layout or a view(the root layout is better if you want to set it for whole activity).
you can set event on LongClick on view or layout by using following line.
yourViewOrLayout.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
//The Action you want to perform
return false;
}
});
hope this helps.
Try this :
RelativeLayout rl=(RelativeLayout) findViewById(R.id.relative1);
rl.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
Toast.makeText(getBaseContext(), "Long Clicked", Toast.LENGTH_SHORT).show();
return false; // do false here
}
});
EDIT :
Intent loginIntent = new Intent(ypurActivity.this, Login.class);
I have a Linear Layout that has a Button and a TextView on it. I have written a OnTouchEvent for the activity. The code works fine if I touch on the screen, but if I touch the button the code does not work. What is the possible solution for this?
public boolean onTouchEvent(MotionEvent event) {
int eventaction=event.getAction();
switch(eventaction)
{
case MotionEvent.ACTION_MOVE:
reg.setText("hey");
break;
}
return true;
}
The problem is the order of operations for how Android handles touch events. Each touch event follows the pattern of (simplified example):
Activity.dispatchTouchEvent()
ViewGroup.dispatchTouchEvent()
View.dispatchTouchEvent()
View.onTouchEvent()
ViewGroup.onTouchEvent()
Activity.onTouchEvent()
But events only follow the chain until they are consumed (meaning somebody returns true from onTouchEvent() or a listener). In the case where you just touch somewhere on the screen, nobody is interested in the event, so it flows all the way down to your code. However, in the case of a button (or other clickable View) it consumes the touch event because it is interested in it, so the flow stops at Line 4.
If you want to monitor all touches that go into your Activity, you need to override dispatchTouchEvent() since that what always gets called first, onTouchEvent() for an Activity gets called last, and only if nobody else captured the event. Be careful to not consume events here, though, or the child views will never get them and your buttons won't be clickable.
public boolean dispatchTouchEvent(MotionEvent event) {
int eventaction=event.getAction();
switch(eventaction) {
case MotionEvent.ACTION_MOVE:
reg.setText("hey");
break;
default:
break;
}
return super.dispatchTouchEvent(event);
}
Another option would be to put your touch handling code into a custom ViewGroup (like LinearLayout) and use its onInterceptTouchEvent() method to allow the parent view to steal away and handle touch events when necessary. Be careful though, as this interaction is one that cannot be undone until a new touch event begins (once you steal one event, you steal them all).
HTH
Let me add one more comment to this excellent post by #Devunwired.
If you've also set an onTouchListener on your View, then its onTouch() method will be called AFTER the dispatch methods, but BEFORE any onTouchEvent() method, i.e. in between no.3 and no.4 on #Devunwired's answer.
Try to set the descendantFocusability attribute of your layout to blocksDescendants
Activity::onTouchEvent will be called only when non of the views in the Activity WIndow consumes/handles the event. If you touch the Button, the Button will consume the events, so the Activity won't be able to handle it.
Check out following articles for more about Android Touch Event handling pipeline.
http://pierrchen.blogspot.jp/2014/03/pipeline-of-android-touch-event-handling.html
you can also try onUserInteraction():
#Override
public void onUserInteraction(){
//your code here
super.onUserInteraction();
}
works well for me!
RecyclerView list_view = findViewById(R.id.list_view);
list_view.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener(){
#Override
public boolean onInterceptTouchEvent(#NonNull RecyclerView rv, #NonNull MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
Log.i("Hello", "World");
return false;
}
});
use public boolean dispatchTouchEvent(MotionEvent event) instead on onTouchEvent()