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.
Related
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);
I have a RecyclerView wrapped in a LinearLayout and it works perfectly as expected. I can see all the data in the RecyclerView as populated. So far so good.
When I wrap the LinearLayout in a ScrollView, the RecyclerView goes blank. I do not see anything inside RecyclerView. Why? How to make this work.
The page is one of the tabs in a ViewPagerIndicator, so everything in that tab needs to be in a ScrollView.
Thanks for all the help.
Set this property for the ScrollView,
android:fillViewport="true"
ScrollView will extend itself to fill the contents
After checking implementation, the reason appears to be the following. If RecyclerView gets put into a ScrollView, then during measure step its height is unspecified (because ScrollView allows any height) and, as a result, gets equal to minimum height (as per implementation) which is apparently zero.
You have couple of options for fixing this:
Set a certain height to RecyclerView
Set ScrollView.fillViewport to true
Or keep RecyclerView outside of ScrollView. I my opinion, this is the best option by far. If RecyclerView height is not limited - which is the case when it's put into ScrollView - then all Adapter's views have enough place vertically and get created all at once. There is no view recycling anymore which kinda breaks the purpose of RecyclerView.
Nothing helped me except this:
mRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
int action = e.getAction();
switch (action) {
case MotionEvent.ACTION_MOVE:
rv.getParent().requestDisallowInterceptTouchEvent(true);
break;
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
});
I got this answer there. Thank you Piyush Gupta for that.
Hope this helps :
Add this line to your recyclerView xml :
android:nestedScrollingEnabled="false"
Try it ,recyclerview will be smoothly scrolled with flexible height inside scrollview .
Before Scrolling:
During Scrolling:
What I expect during scrolling:
I have a problem with HorizontalScrollView. When I choose an element from this View, I set focus to that element by calling:
else if (v.getParent() == candidatesScrollView.getChildAt(0))
{
Button candidateButton = (Button) v;
v.requestFocusFromTouch();
v.setSelected(true);
(...)
}
After that, when I scroll the list without choosing other element, I lose focus of previously selected element. I made some research about this topic, but there was no solution that could work for me... How can I scroll my HorizontalScrollList without loosing focus from selected element? Any Help is Appreciated. It has been about 14 days since I asked that question and still didn't find solution. Please help.
Here is part of my XML:
<HorizontalScrollView
android:id="#+id/CandidatesHorizontalScrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/linearLayout2"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:visibility="gone" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:orientation="horizontal" >
<Button
android:id="#+id/horizontalscrollview1_button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:textSize="25sp" />
(...)
// 11 more buttons
</LinearLayout>
</HorizontalScrollView>
UPDATE
MY CURRENT SOLUTION #1 (not working correctly):
After scrolling, and then scrolling again (for example scrolling back), scrolling starts from selected element.
I created custom HorizontalScrollView class inside which I overridden onTouchEvent() method. I don't think this is optimal way of doing that, because in that case I have to do calculations every time I move even one pixel. for example, if I add toast.show() to the below method, it will try to show as many toast as many I moved pixels (If I move by 10 pixels, it will try to show 10 Toast). Anyway, it works for me and the selection and focus are being kept. Please help me modify this code to make finally a good answer for that known issue:
#Override
public boolean onTouchEvent(MotionEvent ev)
{
int i = 0;
Button button = null;
for (; i < 11; i++)
{
button = (Button)((LinearLayout)getChildAt(0)).getChildAt(i);
if(button.isSelected())
break;
}
super.onTouchEvent(ev);
button.setSelected(true);
button.requestFocusFromTouch();
return true;
}
To be sure that the above code will work, you need to have only one selected item in your HorizontalScrollView at a time, i.e when you press diferent button, you need to make the previous one setSelected(false)
MY CURRENT SOLUTION #2 (not working correctly):
Solution #2 that I tried to implement, thinking that first one is not elegant enough, involves usage of gesture detector. In my custom HorizontalListView class I have added the following code:
Constructor:
public MyHorizontalScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
gestureDetector = new GestureDetector(context, new MyHorizontalScrollViewGestureDetector());
this.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
gestureDetector.onTouchEvent(event);
return true;
}
});
// TODO Auto-generated constructor stub
}
MyHorizontalScrollViewGestureDetector internal class:
public class MyHorizontalScrollViewGestureDetector extends SimpleOnGestureListener
{
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
{
//Here code similar like that one in solution #1
//But the View is not scrolling, even without that code
super.onScroll(e1, e2, distanceX, distanceY);
return true;
}
}
However, the list is not scrolling with that solution. I can add to onScroll method:
ScrollBy((int)positionX, (int)positionY);
which makes the list will scroll, but not in a good way ad it will freeze sometimes.
I am wondering why scrolling is not called by the super. method.
MY CURRENT SOLUTION #3 (working, but it is walk-around):
Because both solution 1 and 2 were not working, I decided to not play with focus anymore.
What I do now, is to change the Button Drawable whenever I click it and every time when I change to different Button. I use same Drawable as is used for focused button (Holo). In that case, I don't have to be worried about scrolling in HorizontalScrollView. This solution is some kind of walk-around, so I am looking forward to any comments, suggestions and edits.
Can the following solution be applicable (I took the idea from here):
You may want to try creating your own custom class that extends HorizontalScrollView and overriding the onScrollChanged() function as such:
public class TestHorizontalScrollView extends HorizontalScrollView {
public TestHorizontalScrollView(Context context) {
super(context);
}
#Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
// TODO Auto-generated method stub
Log.i("Scrolling", "X from ["+oldl+"] to ["+l+"]");
Button button = null;
for (; i < 11; i++)
{
button = (Button)((LinearLayout)getChildAt(0)).getChildAt(i);
if(button.isSelected())
break;
}
button.setSelected(true);
button.requestFocusFromTouch();
super.onScrollChanged(l, t, oldl, oldt);
}
}
Now that you have detected the scroll (we're speaking about one of the HorizontalScrollView) you can set again the selected status of the corresponding button. Can you please try this solution out and see if it works. I'm very interested in the resolution of this one, as the question is quite interesting also.
Anyway, I managed to find the following article. They state there that:
Imagine a simple application, ApiDemos for example, that shows a list
of text items. The user can freely navigate through the list using the
trackball and they can also scroll and fling the list using their
finger. The issue in this scenario is the selection. If I select an
item at the top of the list and then fling the list towards the
bottom, what should happen to the selection? Should it remain on the
item and scroll off the screen? In this case, what would happen if I
then decide to move the selection with the trackball? Or worse, if I
press the trackball to act upon the currently selected item, which is
not shown on screen anymore. After careful considerations, we decided
to remove the selection altogether.
In touch mode, there is no focus and no selection. Any selected item
in a list of in a grid becomes unselected as soon as the user enters
touch mode. Similarly, any focused widgets become unfocused when the
user enters touch mode. The image below illustrates what happens when
the user touches a list after selecting an item with the trackball.
Anyway, the statements there didn't make me happy and I went further to find this:
android:focusable="true"
android:focusableInTouchMode="true"
Also set android:clickable="true" (you might as well set android:focusable="true" of the LinearLayout).
Try adding those to the buttons and to the Layout that contains them.
Try everything.
I'l try backing you up as much as I can.
Cheers
I remember having a problem with scroll views that I think was similar to the problem you're having.
The solution I came up with was to override the onRequestFocusInDescendants method in the HorizontalScrollView class. This requires you creating your own class extended from HorizontalScrollView if you aren't already doing so.
In my case, I always returned true from the method. This tells the caller that you have taken care of the focus change so it shouldn't try to do anything further.
#Override
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
return true;
}
Depending on your requirements, you may find it necessary to return true only under certain conditions (say when a scroll is in progress), otherwise forward the call to the superclass.
This question has no answer except for custom way of doing it, as you might have already done like changing the drawables. Reason is when you slide, the focus goes to the HorizontalScroll, and you can only focus on one item, it makes no sense to focus more than one view. So either implement a drawable (which you seem to have done) or extend a checkbox and override the functionality so when it is focused it is checked and changes the looks.
I have found a solution to my problem. You can see the updated question for details. Basically, instead of using focus I decided to use Drawable selector, which is much more easier.
I am having a listview inside a scrollview, but the problem is that the scrollview is scrolling but listview is not scrolling. I think this is due to that scrollView.
Can somebody who has a working solution post it here as reference?
Generally, you cannot put scrollable things inside other scrollable things, where they scroll in the same direction, and have the results be reliable. Occasionally this works (e.g., WebViews in a ViewPager), but that is the exception, not the norm.
Either:
Move the ListView out of the ScrollView, or
Move all the rest of the contents of the ScrollView into the ListView, whether using things like addHeaderView() or my MergeAdapter
If you put your ListView/any scrollable View inside the scrollView it will not work properly because when you touch the screen ,main focus of your touch is on parent view(scrollView ) not the child View (ListView).
ListView must have fixed height as below in your XML file
<ListView android:id="#+id/lv"
android:listSelector="#0f0"
android:layout_width="fill_parent"
android:layout_height="500px" />
In Java file, write below code after setContentView()
lv = (ListView)findViewById(R.id.lv);
lv.setAdapter(your adapter here); // you have to add your adapter here
lv.setOnTouchListener(new ListView.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_MOVE)
{
lv.scrollBy(0, 1);
}
return false;
}
});
Make these changes to your code and test it. After too many experiments i written this code. It is working 100% fine.
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'