How to put GridView inside ScrollView - android

I have to design layout such that whole layout should scroll and inside layout I have to display related content in Grid form so I decided to use GridView.But problem is that I’m unable to use GridView inside ScrollView I have read documentation(Documentation also saying that we should not use GridView inside ScrollView) also.But I have to do this,so can any please give me some idea about this.Thanks

There are definitely benefits to a GridView beside the inherent scrolling. For example, a consistent, dynamic layout of cells that will expand and contract based on the data you pass into it. So, when people say it's not good to desire such a functionality, I think that's wrong because you could want the dynamic grid of images (views) inside of a scrolling view, but want that entire scrolling view to contain other things than just the grid cells.
Now, here is how you can do this. Check the answer here. It is an expandable height GridView, which you will want to import / create in your project. What that basically means is that as more items are added to the GridView, it will just expand its height, as opposed to keeping its height set and using scrolling. This is exactly what you want.
Once you have the ExpandableHeightGridView in your project, go to your XML layout where you want the GridView to be. You can then do something like this (paraphrasing):
<ScrollView ...>
<RelativeLayout ...>
<com.example.ExpandableHeightGridView ... />
<other view items />
</RelativeLayout>
</ScrollView>
Then, in your activity where you set the GridView's adapter, you want to make sure you set it to expand. So:
ExpandableHeightGridView gridView = (ExpandableHeightGridView) findViewById(R.id.myId);
gridView.setAdapter(yourAdapter);
gridView.setExpanded(true);
The reason you want this expandable GridView is because, the fact that a standard GridView doesn't expand is what causes it to scroll. It sticks to a certain height, and then as more items fill it past its view bounds, it becomes scrollable. Now, with this, your GridView will always expand its height to fit the content within it, thus never allowing it to enter its scrolling mode. This enables you to use it inside of the ScrollView and use other view elements above or below it within the ScrollView, and have them all scroll.
This should give you the result you're looking for. Let me know if you have any questions.

I know I'm late but I have another solution which I must share and which works flawlessly. Here, the method calculates the GridView height based on the number of items it contains and sets the height to the GridView at run time.
public void setGridViewHeightBasedOnChildren(GridView gridView, int columns) {
ListAdapter listAdapter = gridView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
int items = listAdapter.getCount();
int rows = 0;
View listItem = listAdapter.getView(0, null, gridView);
listItem.measure(0, 0);
totalHeight = listItem.getMeasuredHeight();
float x = 1;
if( items > columns ){
x = items/columns;
rows = (int) (x + 1);
totalHeight *= rows;
}
ViewGroup.LayoutParams params = gridView.getLayoutParams();
params.height = totalHeight;
gridView.setLayoutParams(params);
}
After you have called setAdapter on your gridview, just call
setGridViewHeightBasedOnChildren( <yourGridView> , <no of grid view columns> )
and it'll work.
You can the define the gridview in your xml as you normally do
and let the code take care of it. :)

I found a way to give the GridView a fixed size inside ScrollView, and enable scrolling it. That allows you to see the entire ScrollView without having to scroll all elements of the GridView, and it makes more sense to me that using an ExpandableHeightGridView.
To do so, you would have to implement a new class extending GridView and override onTouchEvent() to call requestDisallowInterceptTouchEvent(true).
Thus, the parent view will leave the Grid intercept touch events.
GridViewScrollable.java:
package com.example;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.GridView;
public class GridViewScrollable extends GridView {
public GridViewAdjuntos(Context context) {
super(context);
}
public GridViewAdjuntos(Context context, AttributeSet attrs) {
super(context, attrs);
}
public GridViewAdjuntos(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public boolean onTouchEvent(MotionEvent ev){
// Called when a child does not want this parent and its ancestors to intercept touch events.
requestDisallowInterceptTouchEvent(true);
return super.onTouchEvent(ev);
}
}
Add it in your layout with the characteristics and margins you want, inside a ScrollView:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:isScrollContainer="true" >
<com.example.GridViewScrollable
android:id="#+id/myGVS"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:numColumns="auto_fit"
android:stretchMode="columnWidth" />
</ScrollView>
And just get it in your activity:
GridViewScrollable myGridView = (GridViewScrollable) findViewById(R.id.myGVS);
I hope it helps =)
In Kotlin:
class GridViewScrollable #JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : GridView(context, attrs, defStyleAttr) {
override fun onTouchEvent(ev: MotionEvent?): Boolean {
// Called when a child does not want this parent and its ancestors to intercept touch events.
requestDisallowInterceptTouchEvent(true)
return super.onTouchEvent(ev)
}
}
There is an annoying warning: "Custom view GridViewScrollable overrides onTouchEvent but not performClick". Please, resolve yourself if you want.

I was also trying to make a GridView scrollable inside a NestedScrollView.
This answer on another question helped me: https://stackoverflow.com/a/38612612
Enable your GridView Property as
android:nestedScrollingEnabled="true"
Original poster: Droid_Dev

To use gridview inside scrollview, set scrollview android:fillViewport="true"
I know its late to answer here but may be useful to some new developers.

If you have used dennisdrew's answer and you have content above your grid and it gets hidden when you open your view simply add the last line below
ExpandableHeightGridView gridView = (ExpandableHeightGridView) findViewById(R.id.myId);
gridView.setAdapter(yourAdapter);
gridView.setExpanded(true);
gridView.setFocusable(false);

i would not force the issue. GridView does not work well in a scrollView. instead convert your gridview into a recyclerview and use a gridLayoutManager to resolve the issue.

It's better to use ExpandableHeightlistView or ExpandableHeightGridView inside scrollview.
Logic
Calculate entire height by providing a very large height hint. But do not use the highest 2 bits of this integer; those are reserved for the MeasureSpec mode.
int expandSpec = MeasureSpec.makeMeasureSpec(
Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
for further information explore the example below with demo
http://www.londatiga.net/it/programming/android/make-android-listview-gridview-expandable-inside-scrollview/

Trust this solution worked for me!
android:nestedScrollingEnabled="true"
The code above inside grid view enables to scroll gridview
and set width and height
android:layout_width="match_parent"
android:layout_height="200sp"
This will work even inside scrollview
Thanks for the previous answers I figured out this for the previous answers.
Thanks to them

gridView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
v.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
// Setting on Touch Listener for handling the touch inside ScrollView

If you want to have GridView inside ScrollView / RecyclerView, there are 2 cases:
If you want to have GridView with all rows visible, see https://stackoverflow.com/a/63724794/2914140.
If you want to have one row visible in GridView, but be able to scroll it (to reveal other rows), see https://stackoverflow.com/a/26852498/2914140.

Related

Create a List containing a dynamic number of Views with RecyclerVIew

I want to show the user a scrollable list of items which can each have a different number of "sub-views". For example:
My first idea was to create a RecyclerView that would inflate "items" that each contain their own RecyclerView:
Item:
<LinearLayout
android:id="#+id/item">
<TextView
android:id="#+id/itemTitle" />
<android.support.v7.widget.RecyclerView
android:id="#+id/nestedRecyclerView"/>
</LinearLayout>
The problem I run into is that the main RecyclerView doesn't know the size of the nested one, and thus shows only the TextView above it, since it thinks that the height of the nested list is zero.
This can be somewhat fixed by setting a fixed layout:height to the nested list, but as shown on the item 3 of the example picture, the height may change depending on the number of items.
Is this the preferred way to create such a layout? If yes, how can I solve the "height" problem? If not, what would be the best method?
Can be achieved by adding a gridview for the layout of the list adapter.
U would need to subclass gridview like below, which measures the child height properly.
public class NonScrollableGridView extends GridView {
public NonScrollableGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Do not use the highest two bits of Integer.MAX_VALUE because they are
// reserved for the MeasureSpec mode
int heightSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightSpec);
getLayoutParams().height = getMeasuredHeight();
}
}

Disable Scrolling in child Recyclerview android

I have a layout consists of a Parent RecyclerView with a sub Recyclerview in it
i know that it is not good to put a list inside another list but i have to so that i can use the sub list features like swiping and drag and drop
My issue is that the child Recyclerview gain focus and stops the parent from scrolling if the touch point was on it
simply i want if the touch was vertically on the child Recyclerview
the parent scrolls up and down and if the touch was horizontal or a click then the child Recyclerview list item swipes left and right.
Any help to achieve this?
I finally found a solution.
Create Custom LinearLayoutManager
public class CustomLinearLayoutManager extends LinearLayoutManager {
public CustomLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
// it will always pass false to RecyclerView when calling "canScrollVertically()" method.
#Override
public boolean canScrollVertically() {
return false;
}
}
Then instantiate it like this for vertical scrolling
CustomLinearLayoutManager customLayoutManager = new CustomLinearLayoutManager(getActivity(),LinearLayoutManager.VERTICAL,false);
Finally set the custom layout as layout manager of recycler view
recyclerView.setLayoutManager(customLayoutManager);
android:nestedScrollingEnabled="false" in the child RecyclerView
You can add
android:nestedScrollingEnabled="false"
to your RecyclerView in XML or
childRecyclerView.setNestedScrollingEnabled(false);
to your RecyclerView in Java.
EDIT:-
childRecyclerView.setNestedScrollingEnabled(false); will work only in android_version>21 devices. to work in all devices use the following
ViewCompat.setNestedScrollingEnabled(childRecyclerView, false);
On your ActivityName.java, inside the onCreate() method write:
RecyclerView v = (RecyclerView) findViewById(R.id.your_recycler_view_id);
v.setNestedScrollingEnabled(false);
By any means, if you are using Coordinator Layout, In case you want to simplify things, and you want to disable nested scrolling.
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<android.support.v7.widget.RecyclerView
android:id="#+id/activitiesListRV"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.v4.widget.NestedScrollView>
And again you apply the same principle:
On your ActivityName.java, inside the onCreate() method write:
RecyclerView v = (RecyclerView) findViewById(R.id.your_recycler_view_id);
v.setNestedScrollingEnabled(false);
So basically in XML, you have to specify the app: layout_behavior
app:layout_behavior="#string/appbar_scrolling_view_behavior">
While it might not be good practice to have embedded recycler views, sometimes you cannot avoid it. Something like this might work:
public class NoScrollRecycler extends RecyclerView {
public NoScrollRecycler(Context context){
super(context);
}
public NoScrollRecycler(Context context, AttributeSet attrs){
super(context, attrs);
}
public NoScrollRecycler(Context context, AttributeSet attrs, int style){
super(context, attrs, style);
}
#Override
public boolean dispatchTouchEvent(MotionEvent ev){
//Ignore scroll events.
if(ev.getAction() == MotionEvent.ACTION_MOVE)
return true;
//Dispatch event for non-scroll actions, namely clicks!
return super.dispatchTouchEvent(ev);
}
}
This will disable the scroll event, but not the click events. Use this class for the "child" RecyclerView. You want the PARENT recyclerview to scroll, but not the child. Well this should do that, since the parent will just be the standard RecyclerView, but the child will be this custom one with no scrolling, but handles clicks. Might need to disable clicking for the parent RecyclerView.. Not sure as I have not tested this, so consider it just an example...
Also, to use this in XML (incase you didn't know) do the following:
<com.yourpackage.location.NoScrollRecycler
...
... >
...
...
</com.yourpackage.location.NoScrollRecycler>
you can use setNestedScrollingEnabled(false); on sub RecyclerView which stops scrolling inside sub RecyclerView.
In my case code was
mInnerRecyclerView.setNestedScrollingEnabled(false); where mInnerRecyclerView being inner RecyclerView.
Ithink I'm too late but here i found the solution if it's still annoying someone:
RecyclerView v = (RecyclerView);
findViewById(R.id.your_recycler_view_id);
v.setNestedScrollingEnabled(false);
sensorsRecyclerView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
I've tried many suggested solutions and couldn't find one that worked in my case. I have more than 1 RecyclerView inside a ScrollView using a GridLayoutManager. The result from the suggestion above resulted in the ScrollView stopping to scroll whenever I lifted my finger (it didn't glide to the top or bottom of the view when my finger was lifted over a RecyclerView)
Looking through the RecyclerView source, inside the onTouchEvent there is a call to the layout manager:
final boolean canScrollHorizontally = mLayout.canScrollHorizontally();
final boolean canScrollVertically = mLayout.canScrollVertically();
If you override these in a custom layout manager, return false and it will stop scrolling. It also fixes the problem where the ScrollView would stop scrolling abruptly.
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="#+id/rv"
android:layout_marginTop="2dp"
android:layout_marginLeft="2dp"
android:layout_marginBottom="10dp"
android:layout_marginRight="2dp"
android:nestedScrollingEnabled="false"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
put the code inside LinearLayout...no need to do anything pragmatically
If you don't want make a custom view, another option is to create a same sized layout in front of the RecyclerView, and make it clickable.
EDIT:
But unfortunately it blocks events for list item too.
The Kotlin way:
recyclerView.layoutManager = object: LinearLayoutManager(recyclerView.context) {
override fun canScrollVertically(): Boolean {
return false
}
}

How to manage to bring one child in front of other in custom viewgroup?

I am creating my own custom viewgroup in android. I have two children. One is a linearLayout (it's the first child and covers half of the screen) with some background image and buttons over it and other is a extension of View (it's the second child and covers whole screen) where I draw something using my finger.
I want the (first child) Linear Layout to be hidden under the (second child) extension of view so that I can use some gesture to swipe the second child to the right hand side (kind of like slide of google,youtube) and see the first child (LinearLayout). The problem is inside onLayout I place the children in certain order but the first child (LinearLayout) always comes in front no matter what I do.
secondchild.layout(0,0,top,bottom);
firstchild.layout(0,0,top/2,bottom);
I also tried
firstchild.layout(0,0,top/2,bottom);
secondchild.layout(0,0,top,bottom);
But the first child always comes on top.
Code for Costume ViewGroup:
public class RootViewLayout extends ViewGroup {
private View mDrawView;
private View mSlideView;
private int mTop;
private int mDragRange;
public RootViewLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onFinishInflate() {
mDrawView = findViewById(R.id.content_frame_white);
mSlideView = findViewById(R.id.slide_frame);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(widthSize, heightSize);
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom){
bringChildToFront(mDrawView);
mDrawView.layout(0, 0, right, bottom);
mSlideView.layout(0, 0, right/2, bottom);
}
}
XML Code :
<com.example.drawapp.RootViewLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/Root_View_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white">
<com.example.drawapp.DrawView
android:id="#+id/content_frame_white"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/whitepaperwithcoffeestain">
</com.example.drawapp.DrawView>
<LinearLayout
android:id="#+id/slide_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#drawable/slidebackgrd"
android:orientation="vertical">
<Button
android:id="#+id/pen"
android:layout_width="100dip"
android:layout_height="wrap_content"
android:background="#drawable/pic"/>
</LinearLayout>
</com.example.drawapp.RootViewLayout>
When I don't put
bringChildToFront(mDrawView);
the blank is placed with proper black background, but that's not what I actually want. I want whole screen to be covered with DrawView (whose background is white with coffee stain over it).
Is there any specific way to tell the children to be placed one on top of other?
You need to change the z-order of the child views. You should probably use bringChildToFront(), i.e.
parentLayout.bringChildToFront(secondChild);
However, the effect depends on the type of the parent layout (e.g. if it's a LinearLayout then the views would be swapped). Since you're overlaying I guess it means it's a RelativeLayout, and then it should work as you want.
I see that in your case you're using a custom ViewGroup. If it's only to achieve the "full width/half width" children, then I would suggest swapping it for a RelativeLayout. Add secondchild with match_parent and firstchild as right of a centered 0dp view as in Adjust width to half screen
Or another option, possibly simpler, is to just change the visibility on the child that goes on top (VISIBLE or GONE).

How can I add blank space to the end of a ListView?

I have a number of elements in a ListView that scroll off the screen.
I would like there to be blank space at the end of the View. That is, the user should be able to scroll past the last element such that the last element is in the middle of the viewport.
I could use an OverScroller, but I think that would only enable the View to have a bouncy effect like one often sees on the iPhone.
Is there something I might have overlooked?
The scrolled-to-the-botton screen should look something like this:
The accepted answer is too complicated, and addFooterView is not for this kind of thing. The proper and simpler way is to set the paddingTop and paddingBottom, and you need to set clipToPadding to "false". In your list view or grid view, add the following:
android:paddingTop="100dp"
android:paddingBottom="100dp"
android:clipToPadding="false"
You'll get blank space at the top and the bottom that moves with your finger scroll.
Inflate any layout of your choice (this could be an XML of and ImageView with no drawable and with set height and width of your choice)
Measure the screen height and create new LayoutParams and set the height of it to 1/2 of the screen height
Set the new layout params on your inflated view
Use the ListView's addFooterView() method to add that view to the bottom of your list (there is also an addHeaderView())
Code to measure screen height
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
int screenHeight = display.getHeight();
Code to set half screen height:
View layout = inflater.inflate(R.layout.mylistviewfooter, container, false);
ViewGroup.LayoutParams lp = layout.getLayoutParams();
lp.height = screenHeight/2;
layout.setLayoutParams(lp);
myListView.addFooterView(layout);
An Aside:
When you add a footer or header view to any listview, it has to be done before adding the adapter. Also, if you need to get your adapter class after doing this you will need to know calling the listview's adapter by getAdapter() will return an instance of HeaderViewListAdapter in which you will need to call its getWrappedAdapter method
Something like this :
MyAdapterClassInstance myAdapter = (MyAdapterClassInstance) ((HeaderViewListAdapter) myListView.getAdapter()).getWrappedAdapter();
this 100% works.
in adapter set your code like this
//in getCount
#Override
public int getCount() {
return ArrayList.size()+1;
}
//in getview make your code like this
public View getView(final int i, View view, ViewGroup viewGroup) {
view = inflter.inflate(R.layout.yourlayout, null);
if(i<getCount()-1) {
//your code
}
else{
ViewGroup itemContainer =(ViewGroup) view.findViewById(R.id.container);
itemContainer.setVisibility(View.INVISIBLE);
}
Return view;
}
if you have multiple listviews in your app, create an xml of a footer, something like this:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:minHeight="200dp"
android:layout_width="match_parent"
android:layout_height="200dp"></LinearLayout>
and then in the code, use this:
listView.addFooterView(LayoutInflater.from(getActivity()).inflate(R.layout.empty200, null));
This do the job in a simple way
android:paddingBottom="100dp"
android:clipToPadding="false"
Try the followings:
View footer = new View(getActivity());
footer.setLayoutParams( new AbsListView.LayoutParams( LayoutParams.FILL_PARENT, 100 ));
// 100 is the height, you can change it.
mListView.addFooterView(footer, null, false);

Horizontal ListView in Android?

Is it possible to make the ListView horizontally? I have done this using a gallery view, but the selected item comes to the center of the screen automatically. I don't want the selected item at the same spot I clicked. How can I rectify this problem? My idea was to set the ListView with a horizontal scroll. Share your idea?
As per Android Documentation RecyclerView is the new way to organize the items in listview and to be displayed horizontally
Advantages:
Since by using Recyclerview Adapter, ViewHolder pattern is
automatically implemented
Animation is easy to perform
Many more features
More Information about RecyclerView:
grokkingandroid.com
antonioleiva.com
Sample:
survivingwithandroid.com
Just add the below block to make the ListView to horizontal from vertical
Code-snippet
LinearLayoutManager layoutManager= new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL, false);
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(layoutManager);
Paul doesn't bother to fix bugs of his library or accept users fixes. That's why I am suggesting another library which has similar functionality:
https://github.com/sephiroth74/HorizontalVariableListView
Update: on Jul 24, 2013 author (sephiroth74) released completely rewritten version based on code of android 4.2.2 ListView. I must say that it doesn't have all the errors which previous version had and works great!
#Paul answer links to a great solution, but the code doesn't allow to use onClickListeners on items children (the callback functions are never called). I've been struggling for a while to find a solution and I've decided to post here what you need to modify in that code (in case somebody need it).
Instead of overriding dispatchTouchEvent override onTouchEvent. Use the same code of dispatchTouchEvent and delete the method (you can read the difference between the two here http://developer.android.com/guide/topics/ui/ui-events.html#EventHandlers )
#Override
public boolean onTouchEvent(MotionEvent event) {
boolean handled = mGesture.onTouchEvent(event);
return handled;
}
Then, add the following code which will decide to steal the event from the item children and give it to our onTouchEvent, or let it be handled by them.
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch( ev.getActionMasked() ){
case MotionEvent.ACTION_DOWN:
mInitialX = ev.getX();
mInitialY = ev.getY();
return false;
case MotionEvent.ACTION_MOVE:
float deltaX = Math.abs(ev.getX() - mInitialX);
float deltaY = Math.abs(ev.getY() - mInitialY);
return ( deltaX > 5 || deltaY > 5 );
default:
return super.onInterceptTouchEvent(ev);
}
}
Finally, don't forget to declare the variables in your class:
private float mInitialX;
private float mInitialY;
Since Google introduced Android Support Library v7 21.0.0, you can use RecyclerView to scroll items horizontally. The RecyclerView widget is a more advanced and flexible version of ListView.
To use RecyclerView, just add dependency:
com.android.support:recyclerview-v7:23.0.1
Here is a sample:
public class MyActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(layoutManager);
MyAdapter adapter = new MyAdapter(myDataset);
recyclerView.setAdapter(adapter);
}
}
More info about RecyclerView:
https://developer.android.com/training/material/lists-cards.html
https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html
This is a little (very) late, but I'm posting this in case someone comes by this later.
The Support Library as of the Android L preview has a RecyclerView that does exactly what you want.
Right now, you can only get it through the L preview SDK and you need to set your minSdk to L. But you can copy all of the necessary files into your project and use them that way until L is officially out.
You can download the preview docs here.
Warning: The API for Recycler View may change and it may have bugs.
Updated
The source code for horizontal listview is:
LinearLayoutManager layoutManager
= new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
RecyclerView myList = findViewById(R.id.my_recycler_view);
myList.setLayoutManager(layoutManager);
Download the jar file from here
now put it into your libs folder, right click it and select 'Add as library'
now in main.xml put this code
<com.devsmart.android.ui.HorizontalListView
android:id="#+id/hlistview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
now in Activity class if you want Horizontal Listview with images then put this code
HorizontalListView hListView = (HorizontalListView) findViewById(R.id.hlistview);
hListView.setAdapter(new HAdapter(this));
private class HAdapter extends BaseAdapter {
LayoutInflater inflater;
public HAdapter(Context context) {
inflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return Const.template.length;
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
HViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.listinflate, null);
holder = new HViewHolder();
convertView.setTag(holder);
} else {
holder = (HViewHolder) convertView.getTag();
}
holder.img = (ImageView) convertView.findViewById(R.id.image);
holder.img.setImageResource(Const.template[position]);
return convertView;
}
}
class HViewHolder {
ImageView img;
}
Its actually very simple:
simply Rotate the list view to lay on its side
mlistView.setRotation(-90);
Then upon inflating the children, that should be inside the getView method. you rotate the children to stand up straight:
mylistViewchild.setRotation(90);
Edit:
if your ListView doesnt fit properly after rotation, place the ListView inside this RotateLayout like this:
<com.github.rongi.rotate_layout.layout.RotateLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:angle="90"> <!-- Specify rotate angle here -->
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</com.github.rongi.rotate_layout.layout.RotateLayout>
My solution is to simply use ViewPager widget. It isn't center-locked as Gallery and has a built-in features for recycling views (as ListView). You may see similar approach at Google Play app, whenever you deal with horizontally scrollable lists.
You just need to extend PagerAdapter and perform a couple of tweaks there:
public class MyPagerAdapter extends PagerAdapter {
private Context mContext;
public MyPagerAdapter(Context context) {
this.mContext = context;
}
// As per docs, you may use views as key objects directly
// if they aren't too complex
#Override
public Object instantiateItem(ViewGroup container, int position) {
LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.item, null);
container.addView(view);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
#Override
public int getCount() {
return 10;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
// Important: page takes all available width by default,
// so let's override this method to fit 5 pages within single screen
#Override
public float getPageWidth(int position) {
return 0.2f;
}
}
As result, you'll have horizontally scrollable widget with adapter, like this:
Note: Android now supports horizontal list views using RecyclerView, so now this answer is deprecated, for information about RecyclerView :
https://developer.android.com/reference/android/support/v7/widget/RecyclerView
I have developed a logic to do it without using any external horizontal scrollview library, here is the horizontal view that I achieved and I have posted my answer here:https://stackoverflow.com/a/33301582/5479863
My json response is this:
{"searchInfo":{"status":"1","message":"Success","clist":[{"id":"1de57434-795e-49ac-0ca3-5614dacecbd4","name":"Theater","image_url":"http://52.25.198.71/miisecretory/category_images/movie.png"},{"id":"62fe1c92-2192-2ebb-7e92-5614dacad69b","name":"CNG","image_url":"http://52.25.198.71/miisecretory/category_images/cng.png"},{"id":"8060094c-df4f-5290-7983-5614dad31677","name":"Wine-shop","image_url":"http://52.25.198.71/miisecretory/category_images/beer.png"},{"id":"888a90c4-a6b0-c2e2-6b3c-561788e973f6","name":"Chemist","image_url":"http://52.25.198.71/miisecretory/category_images/chemist.png"},{"id":"a39b4ec1-943f-b800-a671-561789a57871","name":"Food","image_url":"http://52.25.198.71/miisecretory/category_images/food.png"},{"id":"c644cc53-2fce-8cbe-0715-5614da9c765f","name":"College","image_url":"http://52.25.198.71/miisecretory/category_images/college.png"},{"id":"c71e8757-072b-1bf4-5b25-5614d980ef15","name":"Hospital","image_url":"http://52.25.198.71/miisecretory/category_images/hospital.png"},{"id":"db835491-d1d2-5467-a1a1-5614d9963c94","name":"Petrol-Pumps","image_url":"http://52.25.198.71/miisecretory/category_images/petrol.png"},{"id":"f13100ca-4052-c0f4-863a-5614d9631afb","name":"ATM","image_url":"http://52.25.198.71/miisecretory/category_images/atm.png"}]}}
Layout file :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="5">
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="4" />
<HorizontalScrollView
android:id="#+id/horizontalScroll"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<LinearLayout
android:id="#+id/ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="horizontal">
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
class file:
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.ll);
for (int v = 0; v < collectionInfo.size(); v++) {
/*---------------Creating frame layout----------------------*/
FrameLayout frameLayout = new FrameLayout(ActivityMap.this);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, getPixelsToDP(90));
layoutParams.rightMargin = getPixelsToDP(10);
frameLayout.setLayoutParams(layoutParams);
/*--------------end of frame layout----------------------------*/
/*---------------Creating image view----------------------*/
final ImageView imgView = new ImageView(ActivityMap.this); //create imageview dynamically
LinearLayout.LayoutParams lpImage = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
imgView.setImageBitmap(collectionInfo.get(v).getCatImage());
imgView.setLayoutParams(lpImage);
// setting ID to retrieve at later time (same as its position)
imgView.setId(v);
imgView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// getting id which is same as its position
Log.i(TAG, "Clicked on " + collectionInfo.get(v.getId()).getCatName());
// getting selected category's data list
new GetSelectedCategoryData().execute(collectionInfo.get(v.getId()).getCatID());
}
});
/*--------------end of image view----------------------------*/
/*---------------Creating Text view----------------------*/
TextView textView = new TextView(ActivityMap.this);//create textview dynamically
textView.setText(collectionInfo.get(v).getCatName());
FrameLayout.LayoutParams lpText = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM | Gravity.CENTER);
// Note: LinearLayout.LayoutParams 's gravity was not working so I putted Framelayout as 3 paramater is gravity itself
textView.setTextColor(Color.parseColor("#43A047"));
textView.setLayoutParams(lpText);
/*--------------end of Text view----------------------------*/
//Adding views at appropriate places
frameLayout.addView(imgView);
frameLayout.addView(textView);
linearLayout.addView(frameLayout);
}
private int getPixelsToDP(int dp) {
float scale = getResources().getDisplayMetrics().density;
int pixels = (int) (dp * scale + 0.5f);
return pixels;
}
trick that is working here is the id that I have assigned to ImageView "imgView.setId(v)" and after that applying onClickListener to that I am again fetching the id of the view....I have also commented inside the code so that its easy to understand,
I hope this may be very useful...
Happy Coding... :)
This isn't much of an answer, but how about using a Horizontal Scroll View?
You can use RecyclerView in the support library. RecyclerView is a generalized version of ListView that supports:
A layout manager for positioning items
Default animations for common
item operations
Android Recycler View Docs
I've done a lot of searching for a solution to this problem. The short answer is, there is no good solution, without overriding private methods and that sort of thing. The best thing I found was to implement it myself from scratch by extending AdapterView. It's pretty miserable. See my SO question about horizontal ListViews.
I had to do the same for one of my projects and I ended up writing my own as well. I called it HorzListView is now part of my open source Aniqroid library.
http://aniqroid.sileria.com/doc/api/ (Look for downloads at the bottom or use google code project to see more download options: http://code.google.com/p/aniqroid/downloads/list)
The class documentation is here: http://aniqroid.sileria.com/doc/api/com/sileria/android/view/HorzListView.html
For my application, I use a HorizontalScrollView containing LinearLayout inside, which has orientation set to horizontal. In order to add images inside, I create ImageViews inside the activity and add them to my LinearLayout. For example:
<HorizontalScrollView
android:id="#+id/photo_scroll"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:scrollbars="horizontal"
android:visibility="gone">
<LinearLayout
android:id="#+id/imageview_holder"
android:layout_width="wrap_content"
android:orientation="horizontal"
android:layout_height="match_parent">
</LinearLayout>
</HorizontalScrollView>
An this works perfectly fine for me. In the activity all I have to do is something like the code below:
LinearLayout imgViewHolder = findViewById(R.id.imageview_holder);
ImageView img1 = new ImageView(getApplicationContext());
//set bitmap
//set img1 layout params
imgViewHolder.add(img1);
ImageView img2 = new ImageView(getApplicationContext());
//set bitmap
//set img2 layout params
imgViewHolder.add(img2);
As I said that works for me, and I hope it helps somebody looking to achieve this as well.
well you can always create your textviews etc dynamically and set your onclicklisteners like you would do with an adapter
HorizontialListView can't work when the data in the adapter is involved in another thread. Everything runs 100% on UI thread.This is a big problem in multithread. I think using HorizontialListView is not the best solution for your problem.HorzListView is a better way.You just replace your previous Gallery with HorzListView.You neednot modify the code about the adapter.Then everything goes the way you hope.See https://stackoverflow.com/a/12339708/1525777 about HorzListView.
I had used horizontal listview link in my project & I got good results. I had been used devsmart library initially but it gave me some issues. So best way to use horizontal listview link as it recovered my issues & also I recently launched my app on Google PlayStore using this library & got nice response from users. So I recommend you to use the same library which I mentioned above to show listview horizontally. Enjoy :)
There is a great library for that, called TwoWayView, it's very easy to implement, just include the project library into your work space and add it as a library project to your original project, and then follow the following steps which are originally mentioned here:
First, let's add a style indicating the orientation of the ListView
(horizontal or vertical) in (res/values/styles.xml):
<style name="TwoWayView">
<item name="android:orientation">horizontal</item>
</style>
Then,
In your Layout XML, use the following code to add the TwoWayView:
<org.lucasr.twowayview.TwoWayView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/lvItems"
style="#style/TwoWayView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:drawSelectorOnTop="false"
tools:context=".MainActivity" />
and finally, just declare it and deal with it like any regular ListView:
TwoWayView lvTest = (TwoWayView) findViewById(R.id.lvItems);
All the methods of ListView will work here as usual, but there is only one difference I noticed, which is when setting the choice mode, the method setChoiceMode not takes an int value but a value from enum called ChoiceMode, so list_view.setChoiceMode(ListView.CHOICE_MODE_SINGLE); will be lvTest.setChoiceMode(ChoiceMode.SINGLE); // or MULTIPLE or NONE.
You may use ViewFlipper to include the layout XML and add images , listview for each layout XML

Categories

Resources