如何在安卓中使网格视图横向滚动

35
我已经编写了一个GridView的代码,其中可以显示图片和文本,但我想将所有图片显示在单个可滚动行中,就像Pulse新闻应用程序一样。
我在xml中为GridView实现了HorizontalScrollView,但它根本不起作用。
我正在使用PageViewer来制作选项卡,并且正在使用Fragments。
以下是我的xml代码:
<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>

这是我的图片适配器代码

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

我想要显示一个可以向右滚动的内容,类似于这样: enter image description here

各位,有人知道这个问题的解决方案吗? - Swap-IOS-Android
可能是水平滚动网格视图的重复问题。 - Mehmet K
8个回答

24

从现在开始,在Android中有一个好的解决方案(正如Zainodis在评论中所说):HorizontalGridView

1. Gradle依赖项

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

2. 将其添加到您的布局中

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. 布局网格元素

为您的网格元素(grid_element.xml)创建一个布局。我已经创建了一个简单的布局,里面只有一个按钮。


<?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. 创建适配器

灵感来自于此链接: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. 在您的活动中进行初始化:

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

4
不错。这正是我在寻找的,但有一个大问题:如果您设置 horizontalGridView.setNumRows(2);,它也会使网格在垂直方向上无限滚动。设置行高没有帮助。 - Jakub Michalko
这个解决方案存在一个问题,完成后,AndroidManifest.xml 会出现一个错误,我必须使用 <uses-feature android:name="android.software.leanback" android:required="false"/> 来修复它。我正在使用 v17:23.2.1。 - Logan Guo
1
天哪,为什么HORIZONTALgridView也会无限垂直滚动。我浪费了4个小时在这个破事上,真是气死我了。 - Someone Somewhere
2
浪费时间,需要太多的依赖项并迫使您提高SDK级别,还迫使appcompat更改主题,请避免使用此功能。 - Odaym
上传最新的依赖版本以编译'com.android.support:leanback-v17:25.3.1'。 - Terranology
显示剩余5条评论

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>

1
很好的答案,但是这会在右侧留下空白。有什么解决办法吗?@Ashish Soni - Dhiraj Devkar
1
@DhirajDevkar 你需要确保@+id/linearLayout_gridtableLayout的宽度等于numColumns * columnWidth + gridView padding - mtfk

11

我在github上发现Two-way GridView很有用。

它有一些方法:

scrollDirectionPortrait (垂直 | 水平)

scrollDirectionLandscape (垂直 | 水平)

numRows()

等等


2
你在你的应用程序中实现了它吗? - Junaid
@Junaid是的,太有趣了!!!! :D 顺便说一句,难道Facebook不够好吗!?? :D - IronBlossom
1
是的,Facebook是一个很好的社交平台,但它与开发有什么关系? :-/ :P - Junaid

5
我已经测试过一种更好的、不需要任何额外依赖的清洁工作解决方案,只需更改您的布局xml,类似于以下内容。
  <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>

同时在分配网格布局管理器时,根据您的需求设置 setSpan 计数。

这个对我有效,但你应该用更多的代码改进你的答案,这样它将是最佳答案而不使用外部库。 - Crono

1

我认为GridView不能横向滚动。Android提供了GalleryView来实现这个目的。您可以使用它。这里有一个帖子可以帮助您将GalleryView作为水平GridView使用:- 在Android GridView中实现水平滚动


3
更好的选择可能是基于 RecyclerView 的新 HorizontalGridView。http://developer.android.com/reference/android/support/v17/leanback/widget/HorizontalGridView.html - AgentKnopf

0

如果使用GridView比较困难,您可以将recyclerView用作GridView。请参考以下内容。

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

您可以通过 app:spanCount = " " 设置列数。不要忘记将 layoutManager 设置为 GridLayoutManager,方向设置为“水平”


0

Justin(zzhouj)开发的Android-DraggableGridViewPager

提供以下功能:

  • 将网格视图布局分成多个页面。
  • 像support-v4库中的ViewPager一样水平滑动页面。
  • 设置列数和行数。
  • 为页面更改、项目单击、项目长按、重新排列设置监听器。

帮助我创建了一个带有页面指示器的水平可滚动网格,希望能帮助那些尝试实现类似功能的人。


-3
对于少量数据,使用以下布局作为您的容器是一个很好的选择:

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

为您的列表项(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>

然后根据需要以编程方式添加视图:

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

通过这样做,您不再使用适配器。如果您确实需要使用适配器,则应该使用ViewPager,在Android文档中有大量关于如何使用它的信息,或者您可以从StackOverflow开始:

在我的应用程序中使用viewpager android viewPager 实现

如果我漏掉了任何要点,请询问更多信息。


5
根据数据大小的不同,情况可能非常糟糕。 ListView 提供视图回收功能,而不是同时将所有视图存储在内存中,采用这种方法会失去该功能,并很快耗尽内存,性能也会变得糟糕。 - rharter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接