ScrollBy() is not working - android

As the title
I have a fragment layout like this
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/host_profile_scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true" >
</Scrollview>
declare my Scrolview:
content = (ScrollView) rootView.findViewById(R.id.host_profile_scroll_view);
and then I set on click listener for a button
public void onClick(View v) {
content.scrollBy(0, +20);
System.out.println(content.canScrollVertically(+20));
}
But It not working at all and the sysout comman always print out "false".
My question is what cause canScrollVertically get false result and how to resolved is .
Thanks in advance !

Is the content of scrollview scrollable? I mean for the code you wrote, the content of the scrollview should have height at least 20px greater than the height of scrollview.

In fact , the method 'scrollBy' move the content of ViewGroup . Here, if you want to move the ScrollView ,you should call the scrollBy of its father View .

Related

RecyclerView does not fully expand to show all elements

I've created an EditText, a Button and a RecyclerView (composed of 1 TextView and 1 ImageView children) to add TextViews that looks like this . In the EditText at the top, users may enter text and hit the + button. This adds their text to a List(String) which is used to update the RecyclerView. The user may hit the x at the right to delete an entry from the RecyclerView. Here is an image of the overall fragment layout
The issue, which you can see in the image, is that after a few submissions, the RecyclerView stops expanding and remains at a fixed size (notice the small blip in the bottom right). You may scroll in the RecyclerView to view the items, items are still added to it, but it will not expand to the full size (the one in the image has 20+ items). If I delete an item, the height grows for some reason but it still won't display all elements and it shrinks back when I add a new item.
Things I've tried
Here is the RecyclerView code. The heirarchy goes
<LinearLayout>
<ScrollView>
<LinearLayout>
<RecyclerView />
</LinearLayout>
</ScrollView>
</LinearLayout>
All heights and widths are set to match parent, all orientations to vertical:
<android.support.v7.widget.RecyclerView
android:id="#+id/ingredientsRecyclerView"
android:layout_marginTop="4dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
>
The code to add an entry to the RecyclerView (outside of the adapter):
ingredientsButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (ingredientsText.getText().toString().length() > 0) {
mIngredients.add(ingredientsText.getText().toString());
ingredientsText.setText("");
mAdapter.notifyDataSetChanged();
mRecyclerView.setBackgroundResource(R.drawable.rounded_edittext);
}
}
});
And, finally, the code to delete an entry from the RecyclerView (inside the RV adapter):
cancelImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mIngredients.remove(getAdapterPosition());
mAdapter.notifyItemRemoved(getAdapterPosition());
mAdapter.notifyItemRangeChanged(getAdapterPosition(), mIngredients.size());
if(mAdapter.getItemCount() == 0)
mRecyclerView.setBackgroundResource(0);
}
});
Any assistance would be GREATLY appreciated, as I can't figure this out for the life of me!
use NestedScrollView instead of ScrollView and setNestedScrollEnabled(false) on the RecyclerView
k0sh is absolutely right. Just to add, use the full class name, which is android.support.v4.widget.NestedScrollView (make sure you have the v4 support library in your build.gradle file), or Android won't find NestedScrollView class. Source: Error inflating class - NestedScrollView - class not found
Use NestedScrollView instead of ScrollView and on your NestedScrollView set
isNestedScrollingEnabled = false

Set height of children in RecyclerView?

I am trying to use RecyclerView in a similar way to ViewPager (Vertical).
I have setup fling and scroll gestures so the views are scrolled in exactly the same way as ViewPager but now I would like to setup children views (LinearLayoutManager) and LinearLayout used for each child view to fill screen instead of wrap_content. I have made all views to match_parent and fill_parent but that does not work.
I did this:
holder.layout.setMinimumHeight(this.recyclerView.getMeasuredHeight());
Which is nice but when the orientation changes then layout overflows the screen which makes smooth scrolling/gestures flicker etc. I don't want it to overflow the screen.
Any good tips how to make it properly so all children are laid out to maximum height of the screen but do not overflow?
Thanks
Edit: I changed setting minimum height to this:
holder.layout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, this.recyclerView.getHeight()));
which solves flickering issue but is there a better way?
I have low reputation so unable to comment down. thats why answering here .
to over come the overflow issue lets say you have XMl of single item like this
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:id="#+id/mainLayout" >
<-- some views --->>
</RelativeLayout>
now in your adapter get this Layout in viewHolder
and make a boolean variable where you are setting adabpter.. which you can use for knowing orientation changed . when orientation get changed then change its value .
in your adapter make a function
public void orientaiotnChange(){
notifyDataSetChanged();
}
in your function
#Override
public void onBindViewHolder(final ViewHolder viewHolder, final int arg1) {
if(isOrientationHorizontal){
viewHolder.Mainlayout.setOrientation(horizontal);
}
else{
viewHolder.Mainlayout.setOrientation(vertical);
}
also change the orientation of RecyclerView in activity from where you set adapter and from where you are checking orientation is changed or not .
hopefully it will work so :)

Resize parent LinearLayout when adding Buttons Programatically

so what i want to do is add buttons to a LinearLayout programaticalls, this works fine. I want them to apper as one line of buttons in a horizontal order so i set the LinearLayout like this:
<LinearLayout
android:id="#+id/button_frame"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</LinearLayout>
Then i add the buttons programatically:
for (String text: textlist) {
Button cbut = new Button(context);
cbut.setText(text);
cbut.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
cbut.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View arg0) {
Log.d(LOGTAGNAME, "TEST: " + buttonText);
}
});
button_frame.addView(cbut);
button_frame.invalidate();
}
This works until the buttons extend the screen width. So what i want to happen is that there is a horizontal scollbar if the buttons extend the screen width. As an alternative there could be a "line break" for the buttons inside the LinearLayout.
I've tried different setups including a scrollview around the listview but i never saw a scrollbar.
So maybe my problem is that the LinearLayout is not resizing correctly? What do i have to do to make the LinearLayout recalculate width every time after a view is added? invalidate() has no effect at all.
Thanks for any help.
Try putting the linearlayout inside a horiztonalscrollview. That should provide the scrollbar once the button exceeds the screen width.
You trying a simple scrollview or http://developer.android.com/reference/android/widget/HorizontalScrollView.html ? If you don't trying HorizontalScrollView, I think that must help.
try HorizontalScrollView and add Buttons to it . this will scroll automatically whenever needed . for more help share complete layout code
LinearLayout provide only "linear" positioning of views ;) I mean you can do like this:
[btn1][btn2][btn3][btn4]
or like this:
[btn1]
[btn2]
[btn3]
[btn4]
Difference between two variants is in android:orientation param. For more complicated views you should use TableLayout or RelativeLayout.
If you want to do scrollable variant of linear layout creta this structure:
<HorizontalScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
...any other params...>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horisontal"
...any other params.../>
</HorizontalScrollView>
and add buttons to linear layout like you do it now.

onClick not triggered on LinearLayout with child

I've got a custom LinearLayout with a smaller TextView child. I'd like to be able to click the area not covered by the TextView, so I set clickable=true and an onclicklistener to the LinearLayout, but onClick is not triggered. If I set the onclick listener on the TextView it works as expected...
Anybody can help?
ar_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/ar_item" android:layout_width="202dp"
android:layout_height="62dp" android:background="#drawable/bg_item_ar"
android:clickable="true">
<TextView android:id="#+id/ar_item_txt"
android:layout_width="164dp" android:layout_height="fill_parent"
android:paddingBottom="8dp" android:paddingLeft="8dp"
android:paddingTop="8dp" android:paddingRight="6dp" android:gravity="center"
android:background="#50000000" />
</LinearLayout>
My custom LinearLayout
public class ARView extends LinearLayout
{
public ARView(final Context context, String name, String id)
{
super(context);
getLayoutInflater().inflate(R.layout.ar_item, this ,true);
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.ar_item, null);
TextView textView = (TextView) findViewById(R.id.ar_item_txt);
textView.setText(name);
setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
Toast t = Toast.makeText(context, "hey!", Toast.LENGTH_SHORT);
t.show();
}
});
}
}
android:duplicateParentState="true" did not help me.
To make your layout clickable with its children you need add this option for every child:
android:clickable="false"
Then click handling will go up to parent.
for every child
android:duplicateParentState="true"
This isn't your case, but I had similar problem with clickable ViewGroup. After a hour of looking for solution a found out that I set android:inputType to TextView inside my ViewGroup which was blocking onClick() listener (no idea why)
Don't use android:inputType with TextView
Make Your parent LinearLayout's android:clickable="true"
Make all of the the childview's android:clickable="false"
Under Linearlayout - Remove android:inputType="" from TextView
The android:duplicateParentState="true" made my TextView looks like it's disabled, and cannot receive click event.
All you need is set the TextView clickable="false". So the click event will dispatch to parent layout, and the TextView still can react to touch event (with ripple effect).
Your TextView height covers the whole parent (whole layout) so you might clicking on empty space but not on the layout. Try using wrap_content for android:layout_height for your TextView. Set click listener for the layout as well.
You aren't using your custom View; you're using a standard LinearLayout. Your XML tag should be:
<com.yourcode.ARView ...> ... </com.yourcode.ARView>
One thing to make sure of is that another view is not on top of the view you are trying to click. This is especially common in FrameLayouts (where your sub LinearLayout may be covered) or with Relative Layouts you might have forgot to update this line:
android:layout_below="#id/shouldBeTheIdOfTheViewCurrentlyBeingCovered"
so that views don't fill the same space.
If the views in question are TextViews, you may need to set them as focusable="false" so that the first click isn't used focusing on the text view.
The problem may be from the textview that has android:layout_height="fill_parent" in its layout. If that doesn't fix the issue, the problem may be the onClick() event. The linear layout may not actually ever call onClick() since its a layout. Try overriding the onTouch() event listener instead.
Add the following attributes to the linearlayout
Any Click events not handled by the child views will be automatically passed over to the LinearLayout.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
android:focusable="true"
android:clickable="true">
<child/>
<child/>
</LinearLayout>
I faced the same problem, and all the XML Attributes didn't work. I am not sure if this happens because i programmatically inflate and add the views, but this is how i worked around the problem.
I have a Class which extends LinearLayout, with a TextView and an ImageView.
After inflating the layout and getting the views, I assigned the child views a OnClickListener, when pressed, executes the LineaLayout's onClickListner.
public class MyView extends LinearLayout {
private OnClickListener clickListener;
ImageView imageView;
TextView textView;
#Override
public void setOnClickListener(#Nullable OnClickListener l) {
super.setOnClickListener(l);
clickListener = l;
}
void afterViews() {
imageView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
clickListener.onClick(MyView.this);
return false;
}
});
textView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
clickListener.onClick(MyView.this);
return false;
}
});
}
I also tried overriding OnTouchListener, but then my child views didn't have the ripple effect, which I needed.
None of the solutions above forked for me. Than i noticed that a LinkMovementMethod set to TextView inside my LinearLayout. This class intercepts touch events, click events and properties of TextView such as clickable, focusable vs..
I faced the same problem, and all the XML attributes didn't work. I think this happens because I programmatically inflate and add the views. The fix for me was to - also that programatically - set the inflated root view not clickable:
View view = layoutInflater.inflate(R.layout.some_layout, someLinearLayout, false);
view.setClickable(false);
(Yes, I tried to have the some_layout not clickable in XML.)
android:duplicateParentState="true" >= not worked
focusable="false" >= not worked
clickable="false>= not worked
So i did a quick fix by adding Transparent Button on top with match_parent for height and width
Problem solved without any extra code,

How can I get my ListView to scroll?

I have a quite complex View build-up, and as a part of that, I have a ListView inside a LinearLayout within a ScrollView (and quite a lot more components, but they do not matter in this issue).
Now the whole activity scrolls nicely as it should, but the ListView has a limited height, and when the Items inside it surpass the height, the disappear of my screen. I've tried to place the ListView inside it's own ScrollView, but this doesn't work. When I try to scroll on the ListView, the main ScrollView is selected and my screen scrolls instead of the ListView.
My question may sound easy, but I haven't been able to fix this... Is it possible to make the ListView scrollable aswell?
The relevant XML:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout android:id="#+id/GlobalLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView android:id="#+id/EndpointList"
android:choiceMode="multipleChoice"
android:layout_height="175dip"
android:layout_width="fill_parent" />
</LinearLayout>
</ScrollView>
Instead of ListView with other layouts inside ScrollView create one ListView with header and footer.
Add views that should be above ListView as a header:
addHeaderView(View v)
and that below as a footer:
addFooterView(View v)
Put everything what should be above ListView to header of ListView and the same with footer.
LayoutInflater inflater = LayoutInflater.from(this);
mTop = inflater.inflate(R.layout.view_top, null);
mBottom = inflater.inflate(R.layout.view_bottom, null);
list.addHeaderView(mTop);
list.addFooterView(mBottom);
// add header and footer before setting adapter
list.setAdapter(mAdapter);
In result you'll get one scrollable view.
Actually, the way that I have it set up is really working... Placing a ListView in a LinearLayout within a ScrollView. Just avoid that the ListView is the direct child of the ScrollView, and it will work out just fine...
Just be aware that if there aren't enough items in the ListView to fill it so it goes 'off screen', that it won't scroll (kind of logically though). Also note that when you have enough items to scroll through, you need to keep pressing on an item in the ListView to make it scroll, and half of the time, focus is given to the global scrollview in stead of the ListView... To avoid this (most of the time), keep pressing on the most top or most down item, depending on which way you want to scroll.This will optimize your chance to get focus on your ListView.
I've made a video that it is possible, am uploading it now to YouTube...
Video is http://www.youtube.com/watch?v=c53oIg_3lKY. The quality is kinda bad, but it proves my point.
Just for a global overview, I used the ScrollView to be able to scroll my entire activity, the LinearLayout for the Activity's layout, and the ListView to, well, make the list...
I would like to just note something for the video
The listview is working once every x touches not because you placed it inside a linearlayout but because you are touching the the divider...
the scrollview will then consider that the place you touched does not have children to dispatch the motionevent to... so it calls the super.dispatchTouchEvent which is in this case the View.dispatchTouchView hence the listview.onTouchEvent.
When you touch inside a row the scrollview which is really a viewgroup will send the dispatch to the children in your case the textview and never calls the one of the view so the listview do not scroll.
Hope my explanation was clear enough to point out why is it not working.

Categories

Resources