Scrollable MultiLine TextView within a ScrollView (No Touch Interaction Involved) - android

I have created a scroll view with a EditText in the middle that is multiLine (Scrollable). When that view is edited and lines are added beyond the allowed height it scrolls as expected. However, the parent scroll view for the whole container also scrolls as if it is following the text.
<ScrollView
p1:minWidth="25px"
p1:minHeight="25px"
p1:layout_width="match_parent"
p1:layout_height="match_parent"
p1:background="#F7F3DE"
p1:id="#+id/scrollview">
<RelativeLayout
p1:layout_width="match_parent"
p1:layout_height="match_parent"
p1:clickable="true"
p1:focusableInTouchMode="true"
p1:id="#+id/realtiveLayout">
<EditText
p1:id="#+id/editText"
p1:focusableInTouchMode="true"
p1:layout_width="match_parent"
p1:layout_height="150dp"
p1:hint="Comments"
p1:background="#00000000"
p1:textSize="16sp"
p1:textColor="#555555"
p1:gravity="top"
p1:minLines="5"
p1:maxLines="5"
p1:inputType="textCapSentences|textMultiLine"
p1:scrollHorizontally="false"
p1:layout_marginTop="5dp"
p1:textColorHint="#A9A9A9" />
</RelativeLayout>
</ScrollView>
Has anyone seen or know of a resolution for this issue?
(Note: This is not a question of how to scroll one instead of the other by touch as that I already understand. It is a question of the main scrollview moving while typing inside the EditText even though the text is not going lower but scrolling instead.

There is an answer here:
https://stackoverflow.com/a/28180281/3956566
Using this Managing Touch Events in a ViewGroup
Each child touch needs to provide an intercept that returns the parents touch event as false. To disable the parents touch event whilst the child element is being used. You can do this by creating an onInterceptTouchEvent(MotionEvent ev) in your java.
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
/*
* This method JUST determines whether we want to intercept the motion.
* If we return true, onTouchEvent will be called and we do the actual
* scrolling there.
*/
// ...
// In general, we don't want to intercept touch events. They should be
// handled by the child view.
return false;
}
EDIT
This answer provided by
https://stackoverflow.com/users/498468/carl-odonnell
should help:
https://stackoverflow.com/a/5090420/3956566
Where the scrollview is disabled when the text field is touched.
// Get the ScrollView
final ScrollView myScroll = (ScrollView) findViewById(R.id.display_scrollview);
// Disable Scrolling by setting up an OnTouchListener to do nothing
myScroll.setOnTouchListener( new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
// Enable Scrolling by removing the OnTouchListner
tvDisplayScroll.setOnTouchListener(null);

Related

Android: Pass touches to the view (Another App) under Floating view

thank you for reading my question.
I make a floating view and it has an image inside.
It is translucent.
I want this floating view just shows its translucent image and doesn't bother me at all.
Pass touches to the view under
I've seen this article and I've done it.
OnTouchListener -> OnTouch -> return false.
clickable = false, focusable = false.
But the touch event doesn't pass through my floating view.
Would it be possible to solve my problem?
Thank you. I'm going to really appreciate it if you could give me just one hint.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:clickable="false">
...
#TargetApi(Build.VERSION_CODES.FROYO)
#Override
public boolean onTouch(View v, MotionEvent event) {
if(!activate){
return false;
}
}
That's not possible. Communication between apps is limited and there is no touch events communication.

Android: Nested bottom sheet click/drag touch event issue

I have a bottom sheet nested inside another bottom sheet (FrameLayouts using the BottomSheet layout behavior)
I also have a couple of 'peek views' (FrameLayouts) which have click listeners attached, to expand the bottom sheet(s) respectively, when clicked.
So the app basically has 3 main screens. The 'main container', then the first 'bottom sheet', which can be expanded full-screen, and then at the bottom of the first bottom sheet, is the second bottom sheet, which can also be expanded full-screen.
Problem:
When I add a RecyclerView to the nested bottom sheet 'container' view, dragging stops working for the second peek view (Sheet 2 Peek). If I remove the peek view ClickListener or the RecyclerView, things seem to work perfectly fine.
Desired result:
Both bottom sheets should remain draggable, and the peek views should be able to be clicked to expand their parent bottom sheet. The bottom sheet should respond to nested scrolls as it would normally.
I've tried removing the ClickListener and using touch gestures instead, but nothing I've tried seems to help.
I'm using v25.3.1 of the design support library, and I'm able to reproduce this problem on a Galaxy S4 running 4.4.4 stock, and a Nexus 6P running 7.1.2 stock. (I don't have any other devices available).
I've also created a test project on github for anyone interested in taking a closer look:
https://github.com/timusus/bottomsheet-test
Here's a couple of screenshots demonstrating the layout:
The layout structure looks like this (some code omitted for clarity):
<CoordinatorLayout>
<FrameLayout
android:id="#+id/mainContainer"
android:layout_height="match_parent"/>
<FrameLayout
android:id="#+id/sheet1"
android:layout_height="match_parent"
app:layout_behavior="CustomBottomSheetBehavior"
app:behavior_peekHeight="64dp">
<FrameLayout
android:id="#+id/sheet1Container"
android:layout_height="match_parent"/>
<CoordinatorLayout>
<FrameLayout
android:id="#+id/sheet2
android:layout_height="match_parent"
app:layout_behavior="CustomBottomSheetBehavior"
app:behavior_peekHeight="64dp">
<FrameLayout
android:id="#+id/sheet2Container"
android:layout_height="match_parent">
<!-- Problematic RecyclerView -->
<RecyclerView
android:layout_height="match_parent"/>
</FrameLayout>
<!-- Problematic Click Listener on this view -->
<FrameLayout
android:id="#+id/sheet2PeekView"
android:layout_height=64dp"/>
</FrameLayout>
</CoordinatorLayout>
<FrameLayout
android:id="#+id/sheet1PeekView"
android:layout_height=64dp"/>
</FrameLayout>
</CoordinatorLayout/>
The CustomBottomSheetBehavior is just a simple subclass of BottomSheetBehavior which prevents the first sheet from intercepting touch events if the second sheet is expanded or dragging. This allows the second sheet to be dragged from 'expanded' to 'collapsed' without also collapsing the first sheet.
public class CustomBottomSheetBehavior<V extends View> extends BottomSheetBehavior<V> {
private boolean allowDragging = true;
public void setAllowDragging(boolean allowDragging) {
this.allowDragging = allowDragging;
}
#Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
if (!allowDragging) {
return false;
}
return super.onInterceptTouchEvent(parent, child, event);
}
}
I don't believe the customisation of BottomSheetBehavior is relevant to this problem, but for completeness, here's how it's used:
FrameLayout sheet1 = (FrameLayout) findViewById(R.id.sheet1);
bottomSheetBehavior1 = (CustomBottomSheetBehavior) BottomSheetBehavior.from(sheet1);
FrameLayout sheet2 = (FrameLayout) findViewById(R.id.sheet2);
bottomSheetBehavior2 = (CustomBottomSheetBehavior) BottomSheetBehavior.from(sheet2);
bottomSheetBehavior2.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
//If the second sheet is expanded or dragging, don't allow the first sheet to respond to touch events.
if (newState == BottomSheetBehavior.STATE_EXPANDED || newState == BottomSheetBehavior.STATE_DRAGGING) {
bottomSheetBehavior1.setAllowDragging(false);
} else {
bottomSheetBehavior1.setAllowDragging(true);
}
}
I can't seem to figure out if this is to do with the onInterceptTouchEvent of the BottomSheet, nested scroll handling of the inner RecyclerView, View.ClickListener stealing touch events, a combination of the above, or something else altogether.
Any help would be much appreciated.
FIXED
I can't seem to figure out if this is to do with the
onInterceptTouchEvent of the BottomSheet, nested scroll handling of
the inner RecyclerView, View.ClickListener stealing touch events, a
combination of the above, or something else altogether.
It is a combination of the above CustomBottomSheetBehavior and View.ClickListener
Issue was bottomSheetBehavior1 is taking drag event when getSheet2PeekView is dragging so detect touch event on getSheet2PeekView and set bottomSheetBehavior1 dragging false and bottomSheetBehavior2 true
Solution
Put this code and your problem is resolved.
findViewById(getSheet2PeekViewResId()).setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.e(TAG, "onTouch: ");
bottomSheetBehavior1.setAllowDragging(false);
bottomSheetBehavior2.setAllowDragging(true);
return false;
}
});
Also created Pull Request to your repo with fully working changes.

Multiple Scrollable TextViews inside a ScrollView

I have a ScrollView that contains a complex LinearLayout with various elements, among which there are several TextView with maxHeight defined and a long text inside. I need to enable scrolling the text inside the TextView when touch-and-dragging inside it, and the normal scroll of the ScrollView when touch-and-drag outside of them.
Is there a proper and elegant way to do this - if at all possible - or do I have to get dirty and start overriding the onTouchEvent handlers on all elements involved?
UPD 1: Judging from this there is no elegant solution, and the UI will have to be rethinked to include only one layer of scrollable elements.
So it's not pretty, but you can extend from TextView and block the scrollview from scrolling. It's not as nice unless your textviews are large enough. After using this solution we found that it is best if you have a "show more" label that the users can click to show the full thing. Anyway, extend from TextView and override the onTouchEvent method:
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
this.getParent().requestDisallowInterceptTouchEvent(true);
}
if (ev.getAction() == MotionEvent.ACTION_UP) {
this.getParent().requestDisallowInterceptTouchEvent(false);
}
return super.onTouchEvent(ev);
}
A ScrollView is a FrameLayout, meaning you should place one child in it containing the entire contents to scroll; this child may itself be a layout manager with a complex hierarchy of objects. A child that is often used is a LinearLayout in a vertical orientation, presenting a vertical array of top-level items that the user can scroll through.
<ScrollView
android:id="#+id/ScrollView01"
android:layout_height="150px"
android:layout_width="fill_parent">
<TextView
android:id="#+id/TEXT_VIEW"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="This text view should act as header This text view should act as header This text view should act as header This text view should act as header This text view should act as header This text view should act as header This text view should act as header" />
</ScrollView>
you can see the APIdemos for more information, there is a a view of lot of text's with their own stylized scrollview in the same windows. For more inforation you can visit:
http://developer.android.com/resources/samples/ApiDemos/index.html

Can I make a "layer"

Is there any way to create a view above all the others,so when this view is visible, I cannot interact with other views except this one. Sounds like a lock screen.And yeah,that's what I really want to achieve. Any suggestion?
Use a RelativeLayout which fills parent both in width and height. Let this layout have a child view which could be any view.
Put the view on top and set a onTouchlistener.
view.bringToFront();
view.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
That is, have a touch listener that takes all touch events and consumes them (return true).
Use RelativeLayout and ViewGroup.bringChildToFront for the View you want to be above all others.
When adding element to RelativeLayout set layout_height and layout_width to 'match_parent'

How can i disable a scrollview?

I am using relativelayout and inside it a scrollview and inside it a linear layout and a textview which is ensuring scrolling of textview, but I do not want to scroll the text after the particular condition. So, what can I do for this?
To make the scrollbars invisible use this attribute.
android:scrollbars="none"
Edit:
if there is need of runtime changes on visibility or state of enabling, for that we can use the scrolview.setEnabled(false) or android:enabled=false.
There is no direct way to stop scrollview to scroll but u can do it in other way Like:
//global boolean variable
boolean enable = true;
scrollview.setOnTouchListener(new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
return !enable;
}
});
when you set enable variable to true it will start scrolling and when you set it to false it stop scrolling.
If I interpreted your question correctly, you probably want to extend ScrollView and write your own implementation of onInterceptTouchEvent. You could then make your ScrollView conditionally ignore touch events, thus disabling the scrolling behavior. See this question for more details.

Categories

Resources