I want to execute some action if user click the space(created by margin) between two items in RecyclerView, however I did not found a way to do that. OnTouchListener might do the trick but it is posible to get view by given coordinate (x, y)?
Setting onTouchListener on root does not do the trick, it seems like the event is handled by view on top of it. I want to register that can handle all ontouch event and pass the ontouch event to the right view after pre-handle.
You can also achieve this by creating margin using View tag-
Something like this-
<View
android:id="#+id/left_margin_view"
android:layout_width="10dp"
android:layout_height="match_parent"/>
Remove margin applied to recycle item root tag and create view and now you can use any event listener with this view id left_margin_view.
Related
I have a TextView in a layout whos background is a Selector. And the TextView's text is set to Spanned from HTML.
Then I set the TextView with the LinkMovementMethod.
Now when I tap on the TextView, the click event is not sent to its parent layout to trigger the selector.
How should this be solved?
Declare your TextView not clickable / focusable by using android:clickable="false" and android:focusable="false" or v.setClickable(false) and v.setFocusable(false). The click events should be dispatched to the TextView's parent now.
Note:
In order to achieve this, you have to add click to its direct parent. or set
android:clickable="false" and android:focusable="false" to its direct parent to pass listener to further parent.
I think you need to use one of those methods in order to be able to intercept the event before it gets sent to the appropriate components:
Activity.dispatchTouchEvent(MotionEvent) - This allows your Activity to intercept all touch events before they are dispatched to the window.
ViewGroup.onInterceptTouchEvent(MotionEvent) - This allows a ViewGroup to watch events as they are dispatched to child Views.
ViewParent.requestDisallowInterceptTouchEvent(boolean) - Call this upon a parent View to indicate that it should not intercept touch events with onInterceptTouchEvent(MotionEvent).
More information here.
Hope that helps.
Sometime only this helps:
View child = parent.findViewById(R.id.btnMoreText);
child.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
View parent = (View) v.getParent();
parent.performClick();
}
});
Another variant, works not always:
child.setOnClickListener(null);
Put
android:duplicateParentState="true"
in child then the views get its drawable state (focused, pressed, etc.) from its direct parent rather than from itself.
you can set onclick for parent and it call on child clicked
If your TextView create click issues, than remove android:inputType="" from your xml file.
This answer is similar to Alexander Ukhov's answer, except that it uses touch events rather than click events. Those event allow the parent to display the proper pressed states (e.g., ripple effect). This answer is also in Kotlin instead of Java.
view.setOnTouchListener { view, motionEvent ->
(view.parent as View).onTouchEvent(motionEvent)
}
If you want to both OnTouch and OnClick listener to parent and child view both, please use below trick:
User ScrollView as a Parent view and inside that placed your child view inside Relative/LinearLayout.
Make Parent ScrollView android:fillViewport="true" so View not be scrolled.
Then set OnTouch listener to parent and OnClick listener to Child views.
And enjoy both listener callbacks.
Then I set the TextView with the LinkMovementMethod.
TextView.setMovementMethod() internally calls a private method fixFocusableAndClickableSettings. It is the root of the problem: calls setFocusable(FOCUSABLE); setClickable(true); setLongClickable(true);. So no matter what clickability you think you've set, it'll be all true.
source
Those 3 flags have to be reset back to false in order for the view to become non-clickable.
I have the following problem.
In an Android application, there is a custom layout class, which extends the FrameLayout. It overrides the onTouchEvent method for a custom implementation. We have a TextView which resides as the content of this layout class. We want that the URL links in this TextView to be clickable. For that purpose, we add 'android:autoLink="web"' to the TextView's property. The following Xml ensues:
<PinchZoomScrollView
android:layout_weight="350"
android:layout_width="0dp"
android:layout_height="match_parent"
android:id="#+id/newsDetailScrollView">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:autoLink="web"
android:id="#+id/newsDetailText"/>
</PinchZoomScrollView>
After adding autoLink="web", it seems that the onTouchEvent of the custom layout class "PinchZoomEvent" is not being called. It seems that the TextView with the autoLink property blocks touch events somehow. This is weird since the PinchZoomScrollView is TextView's parent and it should receive the event first. What should be done in this case?
Parents don't automatically receive touches first in Android. You're thinking of other frameworks. Touch events start at the children and go up the chain in Android. If you have a parent class such as a scroller that wants to intercept touch events and possible override the child behavior, it needs to implement onInterceptTouchEvent, and return true from it when it detects an action it wants to take from the children.
I have two rows of imageViews in a ScrollView. The imageViews all have onClickListener and when i want to scroll in this area it doesn't work. So i guess the Click listeners intercept the scrolling of the ScrollView. What's the best way to change this behaviour ?
My View hierarchy is like this:
<ScrollView>
<RelativeLayout>
<FrameLayout>
</FrameLayout>
<RelativeLayout>
</ScrollView>
in the FrameLayout i put a Fragment which has a LinearLayout in which i inflate other LinearLayouts like this:
productHolder.productLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
}
});
Maybe you could use an OnTouchListener instead of an OnClickListener.
In the OnTouchListener you can check if the action of the motion event was a click and consume the event (return true). Otherwise you can leave the event for other listeners (return false) to consume.
Note, that you might need to add some additional implementation for figuring out which image view was clicked, however without seeing your layout, it's hard to give you a hint how to do it.
I have a custom view with id R.id.dragableview inside a RelativeLayout, which moves up and down by drag and drop. My problem is, in the layout there is another view which depends on the dragable one:
<View android:id="#+id/dependent_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/dragableview"
/>
My problem is, when the dragable view moves, the other stays where it originally was. I want it to be below the other view always!
how can I achieve that? Which method should I call from inside my custom view, so the other view can update its position?
thanks
I think you've got two options:
Use a RelativeLayout and position your 2nd view at some position relative to your draggable view.
If option #1 doesn't work, you can also try translating your 2nd view by the same distance the 1st view gets dragged, using setTranslationX (float translationX) and setTranslationY (float translationY).
I have a TextView in a layout whos background is a Selector. And the TextView's text is set to Spanned from HTML.
Then I set the TextView with the LinkMovementMethod.
Now when I tap on the TextView, the click event is not sent to its parent layout to trigger the selector.
How should this be solved?
Declare your TextView not clickable / focusable by using android:clickable="false" and android:focusable="false" or v.setClickable(false) and v.setFocusable(false). The click events should be dispatched to the TextView's parent now.
Note:
In order to achieve this, you have to add click to its direct parent. or set
android:clickable="false" and android:focusable="false" to its direct parent to pass listener to further parent.
I think you need to use one of those methods in order to be able to intercept the event before it gets sent to the appropriate components:
Activity.dispatchTouchEvent(MotionEvent) - This allows your Activity to intercept all touch events before they are dispatched to the window.
ViewGroup.onInterceptTouchEvent(MotionEvent) - This allows a ViewGroup to watch events as they are dispatched to child Views.
ViewParent.requestDisallowInterceptTouchEvent(boolean) - Call this upon a parent View to indicate that it should not intercept touch events with onInterceptTouchEvent(MotionEvent).
More information here.
Hope that helps.
Sometime only this helps:
View child = parent.findViewById(R.id.btnMoreText);
child.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
View parent = (View) v.getParent();
parent.performClick();
}
});
Another variant, works not always:
child.setOnClickListener(null);
Put
android:duplicateParentState="true"
in child then the views get its drawable state (focused, pressed, etc.) from its direct parent rather than from itself.
you can set onclick for parent and it call on child clicked
If your TextView create click issues, than remove android:inputType="" from your xml file.
This answer is similar to Alexander Ukhov's answer, except that it uses touch events rather than click events. Those event allow the parent to display the proper pressed states (e.g., ripple effect). This answer is also in Kotlin instead of Java.
view.setOnTouchListener { view, motionEvent ->
(view.parent as View).onTouchEvent(motionEvent)
}
If you want to both OnTouch and OnClick listener to parent and child view both, please use below trick:
User ScrollView as a Parent view and inside that placed your child view inside Relative/LinearLayout.
Make Parent ScrollView android:fillViewport="true" so View not be scrolled.
Then set OnTouch listener to parent and OnClick listener to Child views.
And enjoy both listener callbacks.
Then I set the TextView with the LinkMovementMethod.
TextView.setMovementMethod() internally calls a private method fixFocusableAndClickableSettings. It is the root of the problem: calls setFocusable(FOCUSABLE); setClickable(true); setLongClickable(true);. So no matter what clickability you think you've set, it'll be all true.
source
Those 3 flags have to be reset back to false in order for the view to become non-clickable.