web-dev-qa-db-ja.com

Androidの水平リストビュー?

ListViewを水平にすることは可能ですか?私はこれをギャラリービューを使って行いましたが、選択されたアイテムは自動的にスクリーンの中央に来ます。選択したアイテムをクリックした場所と同じ場所に配置したくありません。どうすればこの問題を解決できますか?私の考えは、水平スクロールでListViewを設定することでした。あなたのアイデアを共有しますか?

212
Praveen

Androidのドキュメントによると RecyclerView はリストビューでアイテムを整理して水平に表示する新しい方法です

利点:

  1. Recyclerview Adapterを使用することで、 ViewHolder pattern が自動的に実装されます
  2. アニメーションがしやすい
  3. より多くの機能

RecyclerViewに関する追加情報:

  1. grokkingandroid.com
  2. antonioleiva.com

サンプル:

survivingwithandroid.com

ListViewを垂直から水平にするためにbelowブロックを追加するだけです。

コードスニペット

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

Paulは、自分のライブラリのバグを修正したり、ユーザーの修正を受け入れたりしません。だからこそ、私は似たような機能を持つ別のライブラリを提案しています。

https://github.com/sephiroth74/Horizo​​ntalVariableListView

更新:2013年7月24日、作者(sephiroth74)がAndroid 4.2.2 ListViewのコードに基づいて完全に書き換えられたバージョンをリリースしました。私はそれが前のバージョンが持っていて、そしてうまく働くすべてのエラーを持っていないと言わなければなりません!

60
Malachiasz

@Paul answerは優れた解決策へのリンクですが、コードでは項目の子にonClickListenersを使用することはできません(コールバック関数は呼び出されません)。私は解決策を見つけるためにしばらく苦労していて、そのコードで修正する必要があるものをここに投稿することにしました(誰かがそれを必要とする場合に備えて)。

dispatchTouchEventをオーバーライドする代わりに、onTouchEventをオーバーライドします。 dispatchTouchEventの同じコードを使用してメソッドを削除します(この2つの違いはここで読むことができます 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;
28
Xavi Gil

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に関するさらに詳しい情報:

23
klimat

これは少し(非常に)遅れています、しかし、後で誰かがこれによってやってくる場合に備えて、私はこれを投稿します。

Android Lプレビュー版のサポートライブラリには RecyclerView があり、それはあなたが望むことを正確に行います。

現時点では、LプレビューSDKからしか入手できないため、minSdkLに設定する必要があります。しかし、必要なファイルをすべてプロジェクトにコピーして、Lが正式にリリースされるまでそのように使用することができます。

あなたはプレビュードキュメントをダウンロードすることができます ここ

警告:Recycler View用のAPIは変更されるかもしれず、それはバグを持つかもしれません。

更新済み

水平リストビューのソースコードは次のとおりです。

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

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

Jarファイルを here からダウンロードします。

今すぐあなたのlibsフォルダにそれを置き、それを右クリックして「ライブラリとして追加」を選択してください

今main.xmlにこのコードを入れて

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

画像付きの水平リストビューが必要な場合は、このコードを入力して、Activityクラスに入ります。

  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;
}
17
Siddhpura Amit

実際はとてもシンプルです:リストビューを回転させて横にします

mlistView.setRotation(-90);

それから子を膨らませると、それはgetViewメソッドの中にあるはずです。あなたは子供たちをまっすぐに立ち上がるように回転させます:

 mylistViewchild.setRotation(90);

編集:あなたのリストビューが回転後にうまく収まらない場合は、この中にリストビューを配置してください 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>
12
kc ochibili

私の解決策は単に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;
    }
}

その結果、次のようにアダプタ付きの水平方向にスクロール可能なウィジェットができます。 enter image description here

9
fraggjkee

注:AndroidはRecyclerViewを使用した水平リストビューをサポートするようになりました。RecyclerViewについては、この回答は推奨されなくなりました。 https://developer.Android.com/reference/Android/) support/v7/widget/RecyclerView

私は、外部の水平スクロールビューライブラリを使用せずにそれを実行するためのロジックを開発しました。これが私が達成した水平ビューです。ここに私の回答を投稿しました。 https://stackoverflow.com/a/33301582/547986

私の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'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に割り当てたIDです "imgView.setId(v)"そしてそれに私は再びビューのIDを取っていますそれにonClickListenerを適用しています。それが理解しやすいこと、私はこれが非常に役に立つかもしれないことを願っています...ハッピーコーディング... :)

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

8
Abdul Aziz

サポートライブラリでRecyclerViewを使用できます。 RecyclerViewは、ListViewを一般化したもので、以下をサポートしています。

  • アイテムを配置するためのレイアウトマネージャ
  • 一般的なアイテム操作のためのデフォルトのアニメーション

Androidのリサイクル業者用ドキュメントを表示

これはあまり答えではありませんが、 Horizo​​ntal Scroll View を使ってはどうでしょうか。

4
Faisal

私はこの問題に対する解決策を探すために多くのことをしました。簡単な答えは、プライベートメソッドやその種のものを上書きしない限り、良い解決策はないということです。私が見つけた最良のことはAdapterViewを拡張することによって最初からそれを自分で実装することでした。かなり悲惨です。私の 水平リストビューについての質問 を参照してください。

3
Neil Traft

私は自分のプロジェクトの一つに対して同じことをしなければならず、そして私も自分自身のものを書くことになった。 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

3
Sileria

私のアプリケーションでは、内部にLinearLayoutを含むHorizo​​ntalScrollViewを使用します。これは、方向が水平に設定されています。内部に画像を追加するために、アクティビティの中にImageViewを作成し、それを私の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); 

私が言ったようにそれが私のために働く、そして私はそれが同様にこれを達成しようとしている誰かに役立つことを願っています。

1
Jorge Cespedes

テキストビューなどを動的に作成したり、アダプタを使用したときのようにonclicklistenerを設定したりできます。

0
weakwire

私は自分のプロジェクトで 水平リストビューリンク を使っていましたが、良い結果が得られました。私は devsmart libraryを使っていましたが、いくつか問題がありました。それで私の問題を回復したように---そして(私は最近このライブラリを使ってGoogle PlayStoreで私のアプリを立ち上げ&ユーザーからいい反応を得ましたので) 水平リストビューリンク を使う最も良い方法です。だから私はあなたが水平にリストビューを表示するために私が上で述べたのと同じライブラリを使うことを勧めます。楽しい :)

0
Tiger

TwoWayView という素晴らしいライブラリがあります。実装するのは非常に簡単です。プロジェクトライブラリを作業スペースに含めて、それを元のプロジェクトのライブラリプロジェクトとして追加してから、次の手順に従ってください。もともとあるステップ ここで言及

まず、(res/values/styles.xml)にListViewの向き(水平または垂直)を示すスタイルを追加しましょう。

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

その後、

レイアウトXMLで、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のすべてのメソッドは通常どおりここで機能しますが、気付いた違いは1つだけです。選択モードを設定するとき、メソッドsetChoiceModeint値を取りませんが、 enumの値はChoiceModeと呼ばれるので、list_view.setChoiceMode(ListView.CHOICE_MODE_SINGLE);lvTest.setChoiceMode(ChoiceMode.SINGLE); // or MULTIPLE or NONEになります。

0
Muhammed Refaat