Horizontal ListView in Android?

AndroidListviewGalleryHorizontal Scrolling

Android Problem Overview


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?

Android Solutions


Solution 1 - Android

As per Android Documentation RecyclerView is the new way to organize the items in listview and to be displayed horizontally

Advantages:

  1. Since by using Recyclerview Adapter, ViewHolder pattern is automatically implemented
  2. Animation is easy to perform
  3. Many more features

More Information about RecyclerView:

  1. grokkingandroid.com
  2. 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);

Solution 2 - Android

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!

Solution 3 - Android

@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;

Solution 4 - Android

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:

Solution 5 - Android

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);

Solution 6 - Android

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;
}

Solution 7 - Android

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>

Solution 8 - Android

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: enter image description here

Solution 9 - Android

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... :)

http://i.stack.imgur.com/lXrpG.png

Solution 10 - Android

This isn't much of an answer, but how about using a Horizontal Scroll View?

Solution 11 - Android

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

Solution 12 - Android

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.

Solution 13 - Android

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

Solution 14 - Android

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.

Solution 15 - Android

well you can always create your textviews etc dynamically and set your onclicklisteners like you would do with an adapter

Solution 16 - Android

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.

Solution 17 - Android

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 :)

Solution 18 - Android

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.

Solution 19 - Android

You may use ViewFlipper to include the layout XML and add images , listview for each layout XML

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPraveenView Question on Stackoverflow
Solution 1 - AndroidDevrathView Answer on Stackoverflow
Solution 2 - AndroidMalachiaszView Answer on Stackoverflow
Solution 3 - AndroidXavi GilView Answer on Stackoverflow
Solution 4 - AndroidklimatView Answer on Stackoverflow
Solution 5 - AndroidAbhay BuchView Answer on Stackoverflow
Solution 6 - AndroidSiddhpura AmitView Answer on Stackoverflow
Solution 7 - Androidkc ochibiliView Answer on Stackoverflow
Solution 8 - AndroidfraggjkeeView Answer on Stackoverflow
Solution 9 - AndroidAbdul AzizView Answer on Stackoverflow
Solution 10 - AndroidFaisalView Answer on Stackoverflow
Solution 11 - AndroidmobileideafactoryView Answer on Stackoverflow
Solution 12 - AndroidNeil TraftView Answer on Stackoverflow
Solution 13 - AndroidSileriaView Answer on Stackoverflow
Solution 14 - AndroidJorge CespedesView Answer on Stackoverflow
Solution 15 - AndroidweakwireView Answer on Stackoverflow
Solution 16 - AndroidEuropaView Answer on Stackoverflow
Solution 17 - AndroidTigerView Answer on Stackoverflow
Solution 18 - AndroidMuhammed RefaatView Answer on Stackoverflow
Solution 19 - AndroidRaju yourPepeView Answer on Stackoverflow