Горизонтальный ListView в Android?

Можно ли сделать ListView горизонтально? Я сделал это с помощью просмотра галереи, но выбранный элемент автоматически попадает в центр экрана. Я не хочу, чтобы выбранный элемент находился в том же месте, на котором я нажал. Как я могу устранить эту проблему? Моя идея состояла в том, чтобы установить ListView с горизонтальным прокруткой. Поделитесь идеей?

    Согласно документации на Android RecyclerView – это новый способ упорядочить элементы в списке и отображать горизонтально

    Преимущества:

    1. Поскольку с помощью адаптера Recycliewiew автоматически создается шаблон ViewHolder
    2. Анимацию легко выполнить
    3. Еще множество функций

    Дополнительная информация о RecyclerView :

    1. grokkingandroid.com
    2. antonioleiva.com

    Образец:

    survivingwithandroid.com

    Просто добавьте нижний блок, чтобы сделать ListView горизонтальным по вертикали

    Код-сниппет

     LinearLayoutManager layoutManager= new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL, false); mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); mRecyclerView.setLayoutManager(layoutManager); 

    Пол не потрудился исправить ошибки своей библиотеки или принять исправления пользователей. Вот почему я предлагаю другую библиотеку, которая имеет аналогичную функциональность:

    https://github.com/sephiroth74/HorizontalVariableListView

    Обновление : 24 июля 2013 автор (sephiroth74) выпустил полностью переписанную версию на основе кода android 4.2.2 ListView. Я должен сказать, что у него нет всех ошибок, которые имели предыдущая версия, и отлично работает!

    @Paul ответит на ссылки на отличное решение, но код не позволяет использовать onClickListeners на элементах children (функции обратного вызова никогда не вызывают). Некоторое время я пытался найти решение, и я решил опубликовать здесь, что вам нужно изменить в этом коде (на случай, если кому-то это понадобится).

    Вместо переопределения dispatchTouchEvent переопределяет onTouchEvent . Используйте тот же код dispatchTouchEvent и удалите метод (вы можете прочитать разницу между этими двумя здесь: http://developer.android.com/guide/topics/ui/ui-events.html#EventHandlers )

     @Override public boolean onTouchEvent(MotionEvent event) { boolean handled = mGesture.onTouchEvent(event); return handled; } 

    Затем добавьте следующий код, который решит украсть событие у детей элемента и передать его нашему onTouchEvent или позволить им обрабатывать их.

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

    Наконец, не забудьте объявить переменные в своем classе:

     private float mInitialX; private float mInitialY; 

    Поскольку Google представил Android Support Library v7 21.0.0, вы можете использовать RecyclerView для прокрутки элементов по горизонтали. Виджет RecyclerView представляет собой более совершенную и гибкую версию ListView.

    Чтобы использовать RecyclerView, просто добавьте зависимость:

     com.android.support:recyclerview-v7:23.0.1 

    Вот пример:

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

    Подробнее о RecyclerView:

    Это немного (очень) поздно, но я отправляю это на случай, если кто-то придет к этому позже.

    Библиотека поддержки с предварительного просмотра Android L имеет RecyclerView который делает именно то, что вы хотите.

    Прямо сейчас вы можете получить его только через предварительный просмотр minSdk и вам нужно установить minSdk в L Но вы можете скопировать все необходимые файлы в свой проект и использовать их таким образом, пока L не будет официально отключен.

    Здесь вы можете скачать предварительные документы.

    Предупреждение. API для просмотра Recycler может измениться, и у него могут быть ошибки.

    обновленный

    Исходный код для горизонтального списка:

     LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false); RecyclerView myList = findViewById(R.id.my_recycler_view); myList.setLayoutManager(layoutManager); 

    Загрузите файл jar отсюда

    теперь поместите его в папку libs, щелкните его правой кнопкой мыши и выберите «Добавить как библиотеку»,

    теперь в main.xml поместите этот код

       

    теперь в classе Activity, если вы хотите, чтобы Horizontal Listview с изображениями помещал этот код

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

    На самом деле это очень просто : просто поверните представление списка, чтобы лежать на боку

    mlistView.setRotation(-90);

    Затем при раздувании детей это должно быть внутри метода getView. вы вращаете детей, чтобы встать прямо:

      mylistViewchild.setRotation(90); 

    Edit: если ваш ListView не подходит должным образом после вращения, поместите ListView внутри этого RotateLayout следующим образом:

           

    Мое решение – просто использовать виджет ViewPager . Он не имеет централизованной блокировки как Gallery и имеет встроенные функции для просмотра видов (как ListView ). Подобный подход можно использовать в приложении Google Play, когда вы имеете дело с горизонтально прокручиваемыми списками.

    Вам просто нужно расширить PagerAdapter и выполнить пару настроек:

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

    В результате у вас будет виджет с прокруткой по горизонтали с адаптером, например: введите описание изображения здесь

    Я разработал логику для этого, не используя внешнюю горизонтальную библиотеку scrollview, вот горизонтальное представление, которое я достиг, и я опубликовал свой ответ здесь: https://stackoverflow.com/a/33301582/5479863

    Мой ответ json:

     {"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"}]}} 

    Файл макета:

              

    файл classа:

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

    трюк, который работает здесь, - это идентификатор, который я присвоил ImageView «imgView.setId (v)», и после этого, применяя onClickListener к этому, я снова получаю идентификатор представления .... Я также прокомментировал внутри кода так что его легко понять, я надеюсь, что это может быть очень полезно ... Happy Coding ... 🙂

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

    Вы можете использовать RecyclerView в библиотеке поддержки. RecyclerView – это обобщенная версия ListView, которая поддерживает:

    • Менеджер компоновки для позиционирования элементов
    • Анимация по умолчанию для операций с обычными элементами

    Android Recycler View Docs

    Это не очень ответ, но как насчет использования горизонтальной прокрутки ?

    Я много искал решение этой проблемы. Короткий ответ: нет хорошего решения, без переопределения частных методов и тому подобного. Лучшее, что я нашел, это реализовать его с нуля, расширив AdapterView . Это довольно жалко. См. Мой вопрос SO о горизонтальных списках ListView .

    Я должен был сделать то же самое для одного из моих проектов, и я тоже написал свою собственную. Я назвал его HorzListView теперь частью моей библиотеки с открытым исходным кодом Aniqroid .

    http://aniqroid.sileria.com/doc/api/ (Ищите загрузки внизу или используйте проект кода Google, чтобы узнать больше параметров загрузки: http://code.google.com/p/aniqroid/downloads/list )

    Документация по classу находится здесь: http://aniqroid.sileria.com/doc/api/com/sileria/android/view/HorzListView.html

    Для моего приложения я использую HorizontalScrollView, содержащий LinearLayout внутри, который имеет ориентацию, установленную на горизонтальную. Чтобы добавить изображения внутри, я создаю ImageViews внутри действия и добавляю их в свой LinearLayout. Например:

         

    Это прекрасно работает для меня. В этой деятельности все, что мне нужно сделать, это что-то вроде кода ниже:

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

    Как я уже сказал, это работает для меня, и я надеюсь, что это поможет кому-то тоже добиться этого.

    хорошо, вы всегда можете создавать свои текстовые изображения и т. д. динамически и устанавливать свои onclicklisteners так же, как и с адаптером

    HorizontialListView не может работать, когда данные в адаптере участвуют в другом streamе. Все работает на 100% в streamе пользовательского интерфейса. Это большая проблема в многопоточном режиме. Я думаю, что использование HorizontialListView – не лучшее решение для вашей проблемы. HorzListView – лучший способ. Вы просто замените свою предыдущую галерею HorzListView. Вам не нужно изменять код об адаптере. Затем все идет так, как вы надеетесь. Посмотрите https: // stackoverflow.com/a/12339708/1525777 о HorzListView.

    Я использовал горизонтальную ссылку списка в моем проекте, и у меня были хорошие результаты. Сначала меня использовали библиотеку devsmart, но это дало мне некоторые проблемы. Так что лучший способ использовать горизонтальную ссылку списка, поскольку он восстановил мои проблемы, а также недавно запустил мое приложение в Google PlayStore с помощью этой библиотеки и получил хороший ответ от пользователей. Поэтому я рекомендую вам использовать ту же библиотеку, о которой я говорил выше, для отображения listview по горизонтали. Наслаждаться 🙂

    Для этого есть большая библиотека, называемая TwoWayView , ее очень легко реализовать, просто включите библиотеку проекта в рабочее пространство и добавьте ее в качестве проекта библиотеки в свой оригинальный проект, а затем выполните следующие шаги, которые изначально упоминаются здесь :

    Во-первых, давайте добавим стиль, указывающий ориентацию ListView (горизонтальный или вертикальный) в (res / values ​​/ styles.xml):

      

    Затем,

    В XML-формате Layout используйте следующий код для добавления TwoWayView:

      

    и, наконец, просто объявите его и обработайте его, как любой обычный ListView :

     TwoWayView lvTest = (TwoWayView) findViewById(R.id.lvItems); 

    Все методы ListView будут работать здесь, как обычно, но есть только одна разница, которую я заметил, а именно при настройке режима выбора метод setChoiceMode не принимает значение int а значение из enum называемое ChoiceMode , поэтому list_view.setChoiceMode(ListView.CHOICE_MODE_SINGLE); будет lvTest.setChoiceMode(ChoiceMode.SINGLE); // or MULTIPLE or NONE lvTest.setChoiceMode(ChoiceMode.SINGLE); // or MULTIPLE or NONE .

    Вы можете использовать ViewFlipper для включения макета XML и добавления изображений, списка для каждого макета XML

    Давайте будем гением компьютера.