【问题标题】:Horizontal scrolling grid view水平滚动网格视图
【发布时间】:2011-04-20 05:03:58
【问题描述】:

我知道在 Android 中水平滚动网格视图是不可能的。但我正在做的是像这样在水平滚动视图中动态添加图像按钮:

public class HorizontalScroller extends Activity {
    static int l=0;
     private Rect mTempRect = new Rect();

    static int r1=0;
    static int t=0;
    static int b=0;
    static int x=0;
    static int y=0;
 //Button[]  b1 = new Button[100];
    ImageButton btn[][] = new ImageButton[10][10];

 //ImageButton b1 = new ImageButton(this);
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        LinearLayout rl = (LinearLayout)findViewById(R.id.widget92);

        LinearLayout.LayoutParams params1 = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);

        for(int i=0;i<4;i++)
        {
            for(int j=0;j<10;j++)
            {System.out.println("helo");
        /*      l=l+100;
                r1=r1+100;
                t=t+100;
                b=b+100;*/
            //button();
       //ImageButton btn=new ImageButton(this);
   /*    Rect r = mTempRect;
           r.left=10;
           r.top=10;
           r.right=10;
           r.bottom=10;
       btn[i][j].getDrawingRect(r);*/

            //btn[i][j].setId(j);

              Rect r = mTempRect;
              r.set(0,0,0,0);
              Rect r2 = mTempRect;
              r2.set(0,20,0,20);

                btn[i][j]=new ImageButton(this);
                btn[i][j]. setBackgroundResource(R.drawable.icon);
                btn[i][j].setMinimumWidth(20);
                btn[i][j].setMinimumHeight(20);
                params1.setMargins(5, 5, 5,5); 
                rl.addView(btn[i][j],params1); 

               System.out.println("1="+btn[i][j].getTop());
               System.out.println("2="+btn[i][j].getLeft());
               System.out.println("3="+btn[i][j].getRight());
               System.out.println("4="+btn[i][j].getBottom());
            }
        }
    }
}

但我将所有图像按钮放在一行中。如何在网格状结构中实现它们?

【问题讨论】:

    标签: android gridview scroll


    【解决方案1】:

    实现水平滚动的 GridView 涉及将一些 Android 源代码类复制到您的代码库(AdapterView、AbsListView、GridView、ScrollBarDrawable)并添加处理水平代码的代码。这主要是复制一些代码并更改从上到左,从下到右等。必须复制而不是扩展的主要原因是这些类的最终性质。

    前段时间我实现了一个水平滚动的 GridView,终于有时间推送到 github: https://github.com/jess-anders/two-way-gridview

    【讨论】:

    • 谢谢!这很好用。除了感谢之外,我还想提醒您,无论您与之交谈的人似乎都删除了他们的 cmets,从而进行了非常片面的对话。也很抱歉这个答案和类似的回答很糟糕,它绝对这里很多问题的一个很好的答案。
    • 真的很酷。但是图像质量很差。任何方式我都可以工作......非常感谢...... :)
    • 图像质量是您在gridview中放置的任何图像。网格视图不会改变它。
    • Jess,你知道如何在切换滚动方向时为单元格排列变化设置动画吗?我的应用程序有两种模式,一种是全屏垂直网格模式,另一种是主/详细视图,顶部有大图像细节,底部有单行水平网格视图栏。我已经在 iOS 中实现了这一点,动画很容易被系统处理......随着全屏网格视图向下滑动,滚动方向也发生变化,成为边缘栏,我希望单元格的排列也会动画。任何想法?真的很感激。
    • 效果很好,有没有办法同时使用水平和垂直滚动?我需要将它用作可以双向滚动的大型图像网格。
    【解决方案2】:

    你可以

    • HorizontalScrollView 中使用TableLayout,或
    • 坚持使用水平的LinearLayout,但添加垂直的LinearLayouts,而不是直接添加图像。例如,在纵向每个垂直 LinearLayout 添加三到四张图像,然后重绘以仅在横向添加两张。

    我会先尝试TableLayout 方法。

    PS1:下次尽量把不相关的代码都去掉(代码越少越容易理解你做了什么)。

    PS2:请记住,System.out 通常会重定向到/dev/null,因此会丢失,因此我强烈建议您改用Log.d

    完整示例

    将此适应 onCreate() 方法或任何你需要的地方:

    public void horizontalScrollGalleryLayout () {
        HorizontalScrollView sv = new HorizontalScrollView(this);
        LinearLayout llh = new LinearLayout(this);
        llh.setOrientation(LinearLayout.HORIZONTAL);
        LinearLayout.LayoutParams layoutParamsTV = new LinearLayout.LayoutParams(40, 40);
        LinearLayout.LayoutParams layoutParamsLL = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        for (int i=0; i<20; i++) {
            LinearLayout llv = new LinearLayout(this);
            llv.setOrientation(LinearLayout.VERTICAL);
            TestView testView1 = new TestView(this, Color.rgb(i*12, 0, 0));
            TestView testView2 = new TestView(this, true, Color.rgb(i*12, i*12, 0));
            TestView testView3 = new TestView(this, true, Color.rgb(0, i*12, 0));
            llv.addView(testView1, layoutParamsTV);
            llv.addView(testView2, layoutParamsTV);
            llv.addView(testView3, layoutParamsTV);
            llh.addView(llv, layoutParamsLL);
        }
        sv.addView(llh, layoutParamsLL);
        setContentView(sv);
    }
    

    我以一个非常简单的 View 为例:

    public class TestView extends View {
    Context context;
    int color;
    
    public TestView(Context context, int color) {
        super(context);
        this.context = context;
        this.color = color;
    }
    
    @Override
    public void onDraw (Canvas canvas) {
        super.onDraw(canvas);
        this.setBackgroundColor(Color.LTGRAY);
        Paint paint = new Paint (Paint.ANTI_ALIAS_FLAG);
        paint.setColor(color);
        canvas.drawCircle(20, 20, 20, paint);
    }
    }
    

    【讨论】:

    • 使用表格布局并没有解决我的问题。然后我尝试使用线性布局概念,但也没有成功,还是一样。
    • 你是什么意思?单行还是不滚动?
    • 单行水平滚动
    • 哥们,你不耐烦了!我刚刚在模拟器上测试了这个,你会得到三行可滚动的彩色圆圈。将它们替换为您想要的图像。
    • 使用这种方法时要小心。布局不处理视图的回收。在布局中放置许多项目,您可能会遇到内存不足的错误。您应该寻找一个正确实现的水平列表/网格视图(使用适配器类的视图)。
    【解决方案3】:

    有一个非常简单的技巧。

    1. 将网格视图旋转 270 度并将列数设置为 2。
    2. 将每个项目旋转 90 度(以便项目显示为原始方向)。

    这可能对某些人有用!

    【讨论】:

    • 我为 ListView 做了同样的事情(列表旋转 -90,项目 90)。效果很好。感谢您的想法!
    • 如果我用 -90 度旋转它,我丢失了一半的元素:/
    • @David 您可以更改行数/列数以使所有元素可见。您可以显示您的代码,也许我/有人可以提供帮助! :)
    【解决方案4】:

    我是这样做的:

    activity_main.xml

    <HorizontalScrollView
       android:layout_width="match_parent"
       android:layout_height="wrap_content">
    
          <LinearLayout
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="horizontal">
    
              <GridView
                 android:id="@+id/gridView"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content">
              </GridView>
    
          </LinearLayout>
    
    </HorizontalScrollView>
    

    MainActivity.java

    GridView gridView = (GridView) findViewById(R.id.gridView);
    
    gridView.setNumColumns(arrayList.size());
    
    GridViewAdapter gridViewAdapter = new GridViewAdapter(mContext, arrayList);
    gridView.setAdapter(gridViewAdapter); 
    
    // Set dynamic width of Gridview
    setDynamicWidth(gridView);
    

    添加以下方法

    private void setDynamicWidth(GridView gridView) {
            ListAdapter gridViewAdapter = gridView.getAdapter();
            if (gridViewAdapter == null) {
                return;
            }
            int totalWidth;
            int items = gridViewAdapter.getCount();
            View listItem = gridViewAdapter.getView(0, null, gridView);
            listItem.measure(0, 0);
            totalWidth = listItem.getMeasuredWidth();
            totalWidth = totalWidth*items;
            ViewGroup.LayoutParams params = gridView.getLayoutParams();
            params.width = totalWidth;
            gridView.setLayoutParams(params);
     }
    

    希望这会对你有所帮助。

    【讨论】:

    • 谢谢,真的帮了我!顺便说一句,我需要将 LinearLayout 的 layout_width 更改为 wrap_content,并且 setDynamicWidth() 中的 getMeasuredWidth() 也给了我错误的结果,所以我只是在这个方法中使用了一个项目宽度的硬编码值。
    【解决方案5】:

    我已经发布了这个答案here,但这两个问题都是 一样的……


    从现在开始,Android 中有一个不错的解决方案: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);
    }
    

    【讨论】:

    • 请注意,这需要 API 级别 17+。
    【解决方案6】:

    使用 recyclerview 将其 gridlayout 设置为布局管理器并将其设置为水平滚动

    your recycle view.setLayoutManager(new GridLayoutManager(getActivity(),2, LinearLayoutManager.HORIZONTAL, false))
    

    这里 2 是网格的列跨度

    【讨论】:

      猜你喜欢
      • 2015-02-20
      • 1970-01-01
      • 2017-07-06
      • 2016-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多