35

I have written code for gridview in which i can show image and text but i want to show all image in single scrollable row like Pulse news apps. I have implemented horizontalscroll-view for gridview in xml but it does not work at all. I am using pageviwer for tabs and i am using fragments.

Here is my xml code

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
   <HorizontalScrollView 
   android:id="@+id/horizontalScrollView1" 
   android:layout_width="fill_parent" 
   android:layout_height="wrap_content"
   android:fillViewport="true"
   android:scrollbars="horizontal" >
<GridView
    android:layout_width="500dp"
    android:layout_height="400dp"
    android:id="@+id/gridview"
    android:columnWidth="300dp"
    android:numColumns="3"
    android:horizontalSpacing="10dp"
    android:scrollbars="horizontal">
</GridView>
 </HorizontalScrollView>
</RelativeLayout>

Here is my image adpator code

public class ImageAdapter extends BaseAdapter {
private Context context;
private final String[] mobileValues;
private TextView t;
public ImageAdapter(Context context, String[] mobileValues) {
    this.context = context;
    this.mobileValues = mobileValues;
}
public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View gridView;
    if (convertView == null) {
        gridView = new View(context);
        // get layout from mobile.xml
        gridView = inflater.inflate(R.layout.showlist_item, null);
       // set value into textview
        TextView textView = (TextView) gridView
                .findViewById(R.id.grid_item_label);
        textView.setText(mobileValues[position]);
        // set image based on selected text
        ImageView imageView = (ImageView) gridView
                .findViewById(R.id.grid_item_image);
        String mobile = mobileValues[position];
        if (mobile.equals("Windows")) {
            imageView.setImageResource(R.drawable.test_play_image);
        } else if (mobile.equals("iOS")) {
            imageView.setImageResource(R.drawable.test_play_image);
        } else if (mobile.equals("Blackberry")) {
            imageView.setImageResource(R.drawable.test_play_image);
        } else {
            imageView.setImageResource(R.drawable.test_play_image);
        }
    } else {
        gridView = (View) convertView;
    }
    return gridView;
}
private void clickedButton(TextView tv){
    int num = Integer.parseInt(tv.getText().toString());
    ++num;
    tv.setText(Integer.toString(num));
}
private void clickedButtonm(TextView tv){
    int num = Integer.parseInt(tv.getText().toString());
    if(num>0){
        --num;
        tv.setText(Integer.toString(num));
    }
}
public int getCount() {
    return mobileValues.length;
}
public Object getItem(int position) {
    return null;
}
public long getItemId(int position) {
    return 0;
}
class MyOnClickListener implements OnClickListener{
    public final TextView tv;
    public MyOnClickListener(TextView tv){
        this.tv=tv;
    }
    public void onClick(View v) {
        // TODO Auto-generated method stub
        clickedButton(tv);
    }
}
class MyOnClickListenerm implements OnClickListener{
    public final TextView tv;
    public MyOnClickListenerm(TextView tv){
        this.tv=tv;
    }
    public void onClick(View v) {
        // TODO Auto-generated method stub
        clickedButtonm(tv);
    }
}

I want to display like this scrollable to right. enter image description here

Swap-IOS-Android
  • 4,363
  • 6
  • 49
  • 77

8 Answers8

24

There is a nice solution in Android from now on (as Zainodis has said in its comment ) : HorizontalGridView.

1. Gradle dependency

dependencies {
    compile 'com.android.support:leanback-v17:23.1.0'
}

2. Add it in your layout

your_activity.xml

<!-- your stuff before... -->
        <android.support.v17.leanback.widget.HorizontalGridView
            android:layout_width="wrap_content"
            android:layout_height="80dp"
            android:id="@+id/gridView"
            />
<!-- your stuff after... -->

3. Layout grid element

Create a layout for your grid element ( grid_element.xml ). I have created a simple one with only one button in it.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Button"
        android:id="@+id/button" />
</LinearLayout>

4. Create an adapter

Highly inspired by this link : https://gist.github.com/gabrielemariotti/4c189fb1124df4556058

public class GridElementAdapter extends RecyclerView.Adapter<GridElementAdapter.SimpleViewHolder>{

    private Context context;
    private List<String> elements;

    public GridElementAdapter(Context context){
        this.context = context;
        this.elements = new ArrayList<String>();
        // Fill dummy list
        for(int i = 0; i < 40 ; i++){
            this.elements.add(i, "Position : " + i);
        }
    }

    public static class SimpleViewHolder extends RecyclerView.ViewHolder {
        public final Button button;

        public SimpleViewHolder(View view) {
            super(view);
            button = (Button) view.findViewById(R.id.button);
        }
    }

    @Override
    public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        final View view = LayoutInflater.from(this.context).inflate(R.layout.grid_element, parent, false);
        return new SimpleViewHolder(view);
    }

    @Override
    public void onBindViewHolder(SimpleViewHolder holder, final int position) {
        holder.button.setText(elements.get(position));
        holder.button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(context, "Position =" + position, Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getItemCount() {
        return this.elements.size();
    }
}

5. Initialize it in your activity :

private HorizontalGridView horizontalGridView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.your_activity);
    horizontalGridView = (HorizontalGridView) findViewById(R.id.gridView);
    GridElementAdapter adapter = new GridElementAdapter(this);

    horizontalGridView.setAdapter(adapter);
}
Community
  • 1
  • 1
kmas
  • 6,401
  • 13
  • 40
  • 62
  • 4
    Nice. This is what I was looking for, but there is a big bug: if you set `horizontalGridView.setNumRows(2);` it will also make the grid **infinitly** scrollable in vertical direction. Setting the row height doesn't help. – Jakub Michalko Feb 16 '16 at 17:20
  • I've just tried what you've said. And you're right. I don't know if there's an option I don't know to solve that problem or if it is a huge bug. Hopefully for me one row was always the maximum I needed. – kmas Mar 07 '16 at 14:21
  • This solution has a problem, after get it done, there is an error occurs to AndroidManifest.xml and I have to use `` to fix that. I am using v17:23.2.1 – Logan Guo Mar 29 '16 at 07:31
  • 1
    OMG why is that the HORIZONTALgridView is scrolling infinitely vertically *also*. WTF. I spent like 4 hours on this crap for nothing – Someone Somewhere Jun 26 '16 at 22:54
  • 2
    Waste of time, requires too many dependencies and forces you to up your SDK level, plus forces appcompat changes to the theme, stay clear of this – Odaym Jul 09 '16 at 21:54
  • does this widget provides zoom focus on Android TV when navigate with dpad – Hussnain Azam Jan 31 '17 at 13:48
  • Upload the last dependency version to compile 'com.android.support:leanback-v17:25.3.1' – Terranology Nov 03 '17 at 10:30
  • Good answer, but does require too many dependencies. Would be perfect for me if it supported BaseAdapter Class. – grantespo Jun 04 '18 at 17:04
  • deprecated now. caution while implementing – Vivek Feb 23 '20 at 13:28
  • @Vivek, you have to use AndroidX/JetPack instead. Il doesn't change so much : https://developer.android.com/reference/androidx/leanback/widget/HorizontalGridView?hl=en . But you're right, I should change the dependency and the package. – kmas Feb 25 '20 at 16:05
15
        <HorizontalScrollView
            android:layout_width="match_parent"
            android:layout_height="fill_parent"
            android:layout_below="@+id/seatLegendLayout">

            <FrameLayout
                android:layout_width="fill_parent"
                android:layout_height="match_parent">

                <LinearLayout
                    android:id="@+id/linearLayout_gridtableLayout"
                    android:layout_width="900dp"
                    android:layout_height="match_parent"
                    android:orientation="horizontal">

                    <GridView
                        android:id="@+id/gridView1"
                        android:layout_width="fill_parent"
                        android:layout_height="fill_parent"
                        android:layout_margin="4dp"
                        android:columnWidth="100dp"
                        android:gravity="center"
                        android:numColumns="9"
                        android:horizontalSpacing="1dp"
                        android:scrollbarAlwaysDrawHorizontalTrack="true"
                        android:scrollbarAlwaysDrawVerticalTrack="true"
                        android:scrollbars="horizontal"
                        android:stretchMode="none"
                        android:verticalSpacing="1dp">

                    </GridView>


                </LinearLayout>
            </FrameLayout>
        </HorizontalScrollView>
Ashish Soni
  • 286
  • 3
  • 4
  • 1
    nice ans but this leaves blank white space at the end in right side. Any solution for this? @Ashish Soni – Dhiraj Devkar Jul 08 '16 at 09:10
  • 1
    @DhirajDevkar You need to make sure that the width of `@+id/linearLayout_gridtableLayout` will be equal of `numColumns * columnWidth + gridView padding` – mtfk Mar 25 '18 at 19:25
11

I found Two-way GridView helpful on github.

It has some methods:

scrollDirectionPortrait (vertical | horizontal)

scrollDirectionLandscape (vertical | horizontal)

numRows()

etc

IronBlossom
  • 3,898
  • 3
  • 35
  • 42
5

There is a better cleaner working solution that i have tested without any kind of extra dependencies just change your layout xml something similar like below .

  <HorizontalScrollView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/horizontal_grid_view"
        android:layout_width="wrap_content"
        android:layout_height="112dp"
        android:scrollbarAlwaysDrawVerticalTrack="true"></android.support.v7.widget.RecyclerView>
</HorizontalScrollView>

Also setSpan count based on your requirement while assigning Grid layout manager.

Alok
  • 881
  • 1
  • 11
  • 18
  • This worked for me, but you should improve your answer with more code, then this one would be the best answer without using external libraries. – Crono Feb 16 '18 at 20:34
1

I don't think that gridviews can be made horizontally scrollable. Android has provided galleryView for this purpose. You can use that. Here is a thead that can help you making galleryView work as a horizontal gridview:- Horizontal scrolling in android gridview

Community
  • 1
  • 1
Ethan Hunt
  • 366
  • 3
  • 17
  • 3
    A better option might be the new RecyclerView based HorizontalGridView http://developer.android.com/reference/android/support/v17/leanback/widget/HorizontalGridView.html – AgentKnopf Aug 03 '15 at 10:39
0

The library Android-DraggableGridViewPager by Justin(zzhouj)

Provides the following features

  • Grid view layout split into pages.
  • Horizontally swipe pages like ViewPager in support-v4 library.
  • Setting col & row count.
  • Setting listeners for: page change, item click, item long click, rearrange.

Helped me create a horizontal scroll-able grid with page indicators, hope it helps someone trying to implement something similar.

usr30911
  • 2,731
  • 7
  • 26
  • 56
0

You can use recyclerView as an GridView no need to use GridView if it's difficult for you. Have a look below

<androidx.recyclerview.widget.RecyclerView 
    android:id="@+id/rvQuickAccess"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:spanCount="2"
    android:gravity="center"
    android:orientation="horizontal"
    tools:listitem="@layout/layout_item"
    app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
    android:scrollbarAlwaysDrawHorizontalTrack="true"/>

You can set number of columns by app:spanCount = " ". Don't forget to set layoutManager as GridLayoutManager and orientation "Horizontal"

Adam Noor
  • 101
  • 3
-3

For a small set of data, a fine route would be to use a layout such as below for your container:

<HorizontalScrollView
        android_id="@+id/scroll_view"
        android_width="match_parent"
        android_height="wrap_content">
    <LinearLayout
            android_id="@+id/my_list"
            android_width="wrap_content"
            android_height="wrap_content" >
    </LinearLayout>
</HorizontalScrollView>

a different layout for your list items (list_item.xml):

<FrameLayout
        android_id="@+id/item_container"
        android_width="100dp"
        android_height="100dp">
    <ImageView
            android_id="@+id/item_background"
            android_width="match_parent"
            android_height="match_parent" />
    <TextView
            android_id="@+id/item_title"
            android_width="match_parent"
            android_height="50dp"
            android_background="#80000000"
            android_gravity="center_vertical" />
</FrameLayout>

and then programatically add views as needed:

public void addItensToLayout(String... mobileValues, LayoutInflater inflater) {
    LinearLayout list = (LinearLayout) findViewById(R.id.my_list);
    for (String item : mobileValues) {
        FrameLayout item = inflater.inflate(R.layout.list_item, list, false);
        TextView textView = (TextView) gridView
            .findViewById(R.id.item_title);
        textView.setText(item);
        ImageView imageView = (ImageView) item
            .findViewById(R.id.item_background);
        String mobile = mobileValues[position];
        if (mobile.equals("Windows")) {
            imageView.setImageResource(R.drawable.test_play_image);
        } else if (mobile.equals("iOS")) {
            imageView.setImageResource(R.drawable.test_play_image);
        } else if (mobile.equals("Blackberry")) {
            imageView.setImageResource(R.drawable.test_play_image);
        } else {
            imageView.setImageResource(R.drawable.test_play_image);
        }
        list.addView(item);
    }
}

By doing so, you are not longer using an adapter. If you really need to use an adapter, you should use an ViewPager, there is plenty of info for doing so in android documentation, or you can start right here in StackOverflow:

Using viewpager in my application android viewPager implementation

Please ask for more info if I missed any point back there.

Community
  • 1
  • 1
apenasVB
  • 1,463
  • 1
  • 11
  • 21
  • 5
    Depending on the size of your data this can be really bad. ListViews give you view recycling instead of having all views in memory at the same time, with this approach you lose that ability and will quickly run out of memory and performance will be terrible. – rharter Feb 14 '14 at 17:28