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

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

Ответ 1

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

<сильные > Преимущества:

  • Поскольку с помощью адаптера Recyclerview шаблон ViewHolder является автоматически реализовано
  • Анимация легко выполнить
  • Много других функций

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

Пример:

survivingwithandroid.com

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

Code-фрагмент

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

Ответ 2

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

https://github.com/sephiroth74/HorizontalVariableListView

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

Ответ 3

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

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

private float mInitialX;
private float mInitialY;

Ответ 4

Поскольку 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:

Ответ 5

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

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

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

Вы можете загрузить предварительные документы здесь.

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

Обновление

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

LinearLayoutManager layoutManager
    = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);

RecyclerView myList = findViewById(R.id.my_recycler_view);
myList.setLayoutManager(layoutManager);

Ответ 6

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

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

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

 <com.devsmart.android.ui.HorizontalListView
    android:id="@+id/hlistview"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    />

теперь в классе 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;
}

Ответ 7

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

mlistView.setRotation(-90);

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

 mylistViewchild.setRotation(90);

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

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

Ответ 8

Мое решение - просто использовать виджет 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 override this method to fit 5 pages within single screen
    @Override
    public float getPageWidth(int position) {
        return 0.2f;
    }
}

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

Ответ 9

Примечание. Android теперь поддерживает горизонтальные представления списка с использованием RecyclerView, поэтому теперь этот ответ не рекомендуется для получения информации о RecyclerView: https://developer.android.com/reference/android/support/v7/widget/RecyclerView

Я разработал логику, чтобы сделать это без использования какой-либо внешней библиотеки горизонтальной прокрутки, вот горизонтальное представление, которое я достиг, и я разместил свой ответ здесь: fooobar.com/questions/34044/...

Мой 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"}]}}

Файл макета:

    <?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>

файл класса:

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

Ответ 10

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

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

Android Recycler View Docs

Ответ 12

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

Ответ 13

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

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

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

Ответ 14

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

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

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

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

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

Ответ 15

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

Ответ 16

HorizontialListView не может работать, когда данные в адаптере участвуют в другом потоке. Все работает на 100% в потоке пользовательского интерфейса. Это большая проблема в многопоточном режиме. Я думаю, что использование HorizontialListView - не лучшее решение для вашей проблемы. Хороший способ - это лучший способ. Вы просто замените свою предыдущую галерею HorzListView. Вам не нужно изменять код об адаптере. Затем все идет так, как вы надеетесь. Посмотрите fooobar.com/questions/34033/... о HorzListView.

Ответ 17

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

Ответ 18

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

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

<style name="TwoWayView">
    <item name="android:orientation">horizontal</item>
</style>

Затем

В XML-формате Layout используйте следующий код для добавления 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" />

и, наконец, просто объявите его и обработайте его как любой обычный 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.

Ответ 19

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