精华内容
下载资源
问答
  • GridView嵌套GridView

    2019-07-06 07:30:57
    下一个示例演示如何在单个网格中显示一个完整的分组产品列表,如下图所示:使用的基本技术是为附表创建一个GridView,它的每行又嵌入一个GridView,这些子GridView使用TemplateField来插入到父GridView中。...
          GridView嵌套可以显示当前选定的父记录组织同时显示所有子记录。例如,你可以用它创建一个完整的按类别组织的产品列表。下一个示例演示如何在单个网格中显示一个完整的分组产品列表,如下图所示:
          

          使用的基本技术是为附表创建一个GridView,它的每行又嵌入一个GridView,这些子GridView使用TemplateField来插入到父GridView中。唯一需要注意的是,不能在绑定父GridView的同时绑定子GridView,因为此时父行还没有被创建。相反,需要等待父GridView的DataBound时间发生。
          在这个示例中父GridView定义了两个列,它们都是TemplateField类型。第一个列组合了类别名称和类型
                
    <asp:TemplateField HeaderText="Category">
                    
                        
    <ItemStyle  VerticalAlign="Top" Width="20%"></ItemStyle>
                        
    <ItemTemplate>
                            
    <br>
                            
    <b>
                                
    <%Eval("CategoryName"%>
                            
    </b>
                            
    <br>
                            
    <br>
                            
    <%Eval("Description" ) %>
                            
    <br>
                        
    </ItemTemplate>
                    
    </asp:TemplateField>

          第二个列包含嵌入的产品的GridView,它有两个绑定列。下面是略去相关样式特性后简要的代码:
          
        <asp:TemplateField HeaderText="Products">
                        
    <ItemStyle VerticalAlign="Top"></ItemStyle>
                        
    <ItemTemplate>
                            
    <asp:GridView id="gridChild" runat="server" Font-Size="XX-Small" BackColor="White" AutoGenerateColumns="False"
                                CellPadding
    ="4" BorderColor="#CC9966" BorderWidth="1px" Width="100%" BorderStyle="None">
                        
                        
    <RowStyle ForeColor="#330099" BackColor="White"></RowStyle>
                                
    <HeaderStyle Font-Bold="True" ForeColor="#FFFFCC" BackColor="#990000"></HeaderStyle>
                                                                
                                
    <Columns>
                                    
    <asp:BoundField DataField="ProductName" HeaderText="Product Name">
                                    
    <ItemStyle Width="250px" />
                                    
    </asp:BoundField>
                                    
    <asp:BoundField DataField="UnitPrice" HeaderText="Unit Price" DataFormatString="{0:C}" />
                                
    </Columns>        
                                
                            
    </asp:GridView>
                        
    </ItemTemplate>
                    
    </asp:TemplateField>

          注意第二个GridView的标记并没有设置DataSourceID属性。那是因为当父网格被绑定到它的数据源时,这些网格的数据源都通过编程来提供。
          现在创建两个数据源,一个用于获取产品类别,另一个用于获取特定类别的产品。第一个查询填充父GridView:     
     <asp:SqlDataSource ID="sourceCategories" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
                ProviderName
    ="System.Data.SqlClient" SelectCommand="SELECT * FROM Categories"></asp:SqlDataSource>
     
          可以把第一个网格直接绑定到数据源:
          
    <asp:GridView id="gridMaster" runat="server" GridLines="None" BorderWidth="1px" BorderColor="Tan"
                Font-Names
    ="Verdana" CellPadding="2" AutoGenerateColumns="False" BackColor="LightGoldenrodYellow"
                ForeColor
    ="Black" DataKeyNames="CategoryID" Font-Size="X-Small" DataSourceID="sourceCategories" OnRowDataBound="gridMaster_RowDataBound">

          这段代码非常典型,奥妙在于如何绑定子GridView。第二个数据源包含被多次调用以填充于GridView的查询。每次它获取不同类别中的产品。CategoryID作为一个参数被提供:
          
    <asp:SqlDataSource ID="sourceProducts" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
                ProviderName
    ="System.Data.SqlClient" SelectCommand="SELECT * FROM Products WHERE CategoryID=@CategoryID">
                
    <SelectParameters>
                    
    <asp:Parameter Name="CategoryID" Type="Int32" />
                
    </SelectParameters>
            
    </asp:SqlDataSource>

          为了绑定子GridView,必须相应GridView.RowDataBound事件,它在每次行生成并绑定到父GridView时产生。此时,可以从第二列获取子GridView。并通过编程调用数据源的Select()方法把它绑定到产品信息。为了确保只显示当前类别的产品,还必须获取当前项的CategoryID字段并把它作为参数传递。代码如下:
          
    protected void gridMaster_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            
    // Look for GridView items.
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                
    // Retrieve the GridView control in the second column.
                GridView gridChild = (GridView)e.Row.Cells[1].Controls[1];

                sourceProducts.SelectParameters[
    0].DefaultValue = gridMaster.DataKeys[e.Row.DataItemIndex].Value.ToString();
                
    object data = sourceProducts.Select(DataSourceSelectArguments.Empty);
                
                
    // Bind the grid.
                gridChild.DataSource = data;
                gridChild.DataBind();
                

            }
        }
          

    转载于:https://www.cnblogs.com/zjz008/archive/2009/10/07/1578798.html

    展开全文
  • Android:控件GridView的使用

    万次阅读 多人点赞 2018-06-05 23:17:16
    如果是列表(单列多行形式)的使用ListView,如果是多行多列网状形式的优先使用GridView。 <?xml version="1.0" encoding="utf-8"?> <GridView xmlns:android=...

    如果是列表(单列多行形式)的使用ListView,如果是多行多列网状形式的优先使用GridView。

     

    <?xml version="1.0" encoding="utf-8"?>
    <GridView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
    <!-- android:horizontalSpacing="10dp"水平拮据 -->
      <!-- android:verticalSpacing="10dp"垂直拮据 -->
        
    </GridView>

     

    GirdView的一些属性:

    android:numColumns="auto_fit" --------列数设置为自动
    android:columnWidth="90dp",----------每列的宽度,也就是Item的宽度
    android:stretchMode="columnWidth"------缩放与列宽大小同步
    android:verticalSpacing="10dp"----------垂直边距
    android:horizontalSpacing="10dp"-------水平边距

    1、准备数据源

    2、新建适配器

    3、加载适配器

    GridView(网格视图)是按照行列的方式来显示内容的,一般用于显示图片,图片等内容,比如实现九宫格图,用GridView是首选,也是最简单的,下面来个实例,

    下载实例>>>

    效果图:

    MainActivity.java

    package com.example.testgridview;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.GridView;
    import android.widget.SimpleAdapter;
    
    public class MainActivity extends Activity {
        private GridView gview;
        private List<Map<String, Object>> data_list;
        private SimpleAdapter sim_adapter;
        // 图片封装为一个数组
        private int[] icon = { R.drawable.address_book, R.drawable.calendar,
                R.drawable.camera, R.drawable.clock, R.drawable.games_control,
                R.drawable.messenger, R.drawable.ringtone, R.drawable.settings,
                R.drawable.speech_balloon, R.drawable.weather, R.drawable.world,
                R.drawable.youtube };
        private String[] iconName = { "通讯录", "日历", "照相机", "时钟", "游戏", "短信", "铃声",
                "设置", "语音", "天气", "浏览器", "视频" };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.test);
            gview = (GridView) findViewById(R.id.gview);
            //新建List
            data_list = new ArrayList<Map<String, Object>>();
            //获取数据
            getData();
            //新建适配器
            String [] from ={"image","text"};
            int [] to = {R.id.image,R.id.text};
            sim_adapter = new SimpleAdapter(this, data_list, R.layout.item, from, to);
            //配置适配器
            gview.setAdapter(sim_adapter);
        }
    
        
        
        public List<Map<String, Object>> getData(){        
            //cion和iconName的长度是相同的,这里任选其一都可以
            for(int i=0;i<icon.length;i++){
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("image", icon[i]);
                map.put("text", iconName[i]);
                data_list.add(map);
            }
                
            return data_list;
        }
        
    
    }

    test.xml

    <?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:background="#000"
        >
        
    <GridView 
            android:id="@+id/gview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:numColumns="auto_fit"    
            android:columnWidth="80dp"
            android:stretchMode="columnWidth"
            ></GridView>
    </LinearLayout>

    item.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical" 
        android:gravity="center"
        android:padding="10dp"
        >
        
        
    <ImageView 
        android:src="@drawable/ic_launcher"
        android:id="@+id/image"
        android:layout_width="60dp"
        android:layout_height="60dp"
        
        />
    
    <TextView 
        android:id="@+id/text"
        android:layout_marginTop="5dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#ffffff"
        android:text="文字"
        />
    </LinearLayout>

     

    概述

    GridView是Android的另一个列表容器,用法也跟ListView类似,它的布局是一个网格,一行可以有多个项,并且整个视图可以滚动,我们常见的应用有手机中的图库、launcher里面的应用列表、类似微信多张图片等,总的来说,ListView主要应用于单列多行的列表,然而GridView主要应用于多行多列的网状布局。

    案例

    GridView

    GridView

    上面的运行结果就是GridView的典型效果,每个item是一张固定大小的图片,这里让它自适应屏幕来填充完整个屏幕的宽度。

    实现过程

    GridView布局
    layout/activity_gridview.xml

    <?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">
    
    
        <GridView
            android:id="@+id/gridView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:columnWidth="90dp"
            android:numColumns="auto_fit"
            android:verticalSpacing="10dp"
            android:horizontalSpacing="10dp"
            android:stretchMode="columnWidth"
            android:cacheColorHint="#00000000"
            android:listSelector="#00000000"
            android:scrollbars="none"
            android:fadeScrollbars="true"
            android:fastScrollEnabled="true"
            android:fadingEdge="none"
            android:fadingEdgeLength="10dp"
            android:stackFromBottom="true"
            android:transcriptMode="alwaysScroll"
            android:drawSelectorOnTop="false"
            android:gravity="center"/>
    </LinearLayout>
    

    相关属性解析:
    1.android:numColumns=”auto_fit” //GridView的列数设置为自动
    2.android:columnWidth=”90dp " //每列的宽度,也就是Item的宽度
    3.android:stretchMode=”columnWidth"//缩放与列宽大小同步
    4.android:verticalSpacing=”10dp” //两行之间的边距
    5.android:horizontalSpacing=”10dp” //两列之间的边距
    6.android:cacheColorHint="#00000000" //去除拖动时默认的黑色背景
    7.android:listSelector="#00000000" //去除选中时的黄色底色
    8.android:scrollbars="none" //隐藏GridView的滚动条
    9.android:fadeScrollbars="true" //设置为true就可以实现滚动条的自动隐藏和显示
    10.android:fastScrollEnabled="true" //GridView出现快速滚动的按钮(至少滚动4页才会显示)
    11.android:fadingEdge="none" //GridView衰落(褪去)边缘颜色为空,缺省值是vertical。(可以理解为上下边缘的提示色)
    12.android:fadingEdgeLength="10dip" //定义的衰落(褪去)边缘的长度
    13.android:stackFromBottom="true" //设置为true时,你做好的列表就会显示你列表的最下面
    14.android:transcriptMode="alwaysScroll" //当你动态添加数据时,列表将自动往下滚动最新的条目可以自动滚动到可视范围内
    15.android:drawSelectorOnTop="false" //点击某条记录不放,颜色会在记录的后面成为背景色,内容的文字可见(缺省为false)

    子项
    layout/layout_grid_item.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
    
        <ImageView
            android:id="@+id/iv_head"
            android:layout_width="90dp"
            android:layout_height="90dp"
            android:layout_centerInParent="true"
            android:scaleType="centerCrop"
            />
    
    
    </RelativeLayout>
    

    Activity代码

    
    package com.devilwwj.androiddevelopcourse.activities;
    
    import android.content.Context;
    import android.os.Bundle;
    import android.support.v7.app.ActionBarActivity;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.AdapterView;
    import android.widget.AdapterView.OnItemClickListener;
    import android.widget.BaseAdapter;
    import android.widget.GridView;
    import android.widget.ImageView;
    
    import com.devilwwj.androiddevelopcourse.R;
    import com.nostra13.universalimageloader.core.ImageLoader;
    
    
    public class GridViewTestActivity extends ActionBarActivity implements OnItemClickListener {
        private GridView gridView;
        private Context mContext;
        private ImageLoader imageLoader;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_gridview);
            mContext = GridViewTestActivity.this;
    
            imageLoader = ImageLoader.getInstance();
    
            gridView = (GridView) this.findViewById(R.id.gridView);
    
    
            gridView.setAdapter(new ImageAdapter(this));
    
        }
    
        // references to our images
        private Integer[] mThumbIds = {
                R.drawable.sample_2, R.drawable.sample_3,
                R.drawable.sample_4, R.drawable.sample_5,
                R.drawable.sample_6, R.drawable.sample_7,
                R.drawable.sample_0, R.drawable.sample_1,
                R.drawable.sample_2, R.drawable.sample_3,
                R.drawable.sample_4, R.drawable.sample_5,
                R.drawable.sample_6, R.drawable.sample_7,
                R.drawable.sample_0, R.drawable.sample_1,
                R.drawable.sample_2, R.drawable.sample_3,
                R.drawable.sample_4, R.drawable.sample_5,
                R.drawable.sample_6, R.drawable.sample_7
        };
    
    
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            // TODO: 点击列表跳转到其他页面
    
        }
    
    
        private class ImageAdapter extends BaseAdapter {
    
            private Context mContext;
    
            public ImageAdapter(Context context) {
                this.mContext = context;
            }
    
    
            @Override
            public int getCount() {
                return mThumbIds.length;
            }
    
            @Override
            public Object getItem(int position) {
                return null;
            }
    
            @Override
            public long getItemId(int position) {
                return position;
            }
    
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                ViewHolder viewHolder = null;
    
    
                if (convertView == null) {
                    convertView = LayoutInflater.from(mContext).inflate(R.layout.layout_grid_item, parent, false);
                    viewHolder = new ViewHolder();
                    viewHolder.itemImg = (ImageView) convertView.findViewById(R.id.iv_head);
    
                    convertView.setTag(viewHolder);
    
                } else {
                    viewHolder = (ViewHolder) convertView.getTag();
                }
    
                // 这里只是模拟,实际开发可能需要加载网络图片,可以使用ImageLoader这样的图片加载框架来异步加载图片
                imageLoader.displayImage("drawable://" + mThumbIds[position], viewHolder.itemImg);
    
    
                return convertView;
            }
    
    
            class ViewHolder {
                ImageView itemImg;
            }
        }
    }
    
    

    在Activity中我们做了以下几件事:
    1、初始化控件
    2、定义图片资源mThumbIds
    3、定义ImageAdapter

    上面代码中我们用到了ImageLoader这个图片加载框架,使用它来加载本地drawable资源,实际开发中一般不会这样用,我们传进去的uri是一个图片网络地址,具体的使用方法可以百度学习,这里简单介绍步骤:
    1、 初始化ImageLoader配置
    2、获取ImageLoader实例,调用其displayImage方法异步加载图片

    展开全文
  • Flutter GridView详解

    千次阅读 2018-11-16 23:44:15
    GridView

    GridView常用构造

    GridView

    构造函数
    GridView({Key key, Axis scrollDirection: Axis.vertical, bool reverse: false,
     ScrollController controller, bool primary, 
     ScrollPhysics physics, bool shrinkWrap: false,
      EdgeInsetsGeometry padding, 
     @required SliverGridDelegate gridDelegate, 
     bool addAutomaticKeepAlives: true,
      bool addRepaintBoundaries: true, 
     bool addSemanticIndexes: true,
      double cacheExtent, List<Widget> children: const [], 
      int semanticChildCount })
      
    Creates a scrollable, 2D array of widgets with a custom SliverGridDelegate. [...]
    

    GridView.count

    构造函数
    GridView.count({Key key, Axis scrollDirection: Axis.vertical, 
    bool reverse: false, ScrollController controller, 
    bool primary, ScrollPhysics physics, bool shrinkWrap: false, 
    EdgeInsetsGeometry padding, @required int crossAxisCount,
     double mainAxisSpacing: 0.0, double crossAxisSpacing: 0.0, 
     double childAspectRatio: 1.0, bool addAutomaticKeepAlives: true,
      bool addRepaintBoundaries: true, 
      bool addSemanticIndexes: true,
       double cacheExtent, List<Widget> children: const [], 
       int semanticChildCount })
       
    Creates a scrollable, 2D array of widgets with a fixed number of 
    tiles in the cross axis. [...]
    
    分析和使用
     Widget gridViewDefaultCount(List<BaseBean> list) {
        return GridView.count(
    //      padding: EdgeInsets.all(5.0),
          //一行多少个
          crossAxisCount: 5,
          //滚动方向
          scrollDirection: Axis.vertical,
          // 左右间隔
          crossAxisSpacing: 10.0,
          // 上下间隔
          mainAxisSpacing: 10.0,
          //宽高比
          childAspectRatio: 2 / 5,
    
          children: initListWidget(list),
        );
      }
    
    List<Widget> initListWidget(List<BaseBean> list) {
        List<Widget> lists = [];
        for (var item in list) {
          lists.add(new Container(
            height: 50.0,
            width: 50.0,
            color: Colors.yellow,
            child: new Center(
                child: new Text(
              item.age.toString(),
            )),
          ));
        }
        return lists;
      }
    

    GridView.extent

    构造函数
    GridView.extent({Key key, Axis scrollDirection: Axis.vertical,
     bool reverse: false, ScrollController controller,
      bool primary, ScrollPhysics physics, 
      bool shrinkWrap: false, EdgeInsetsGeometry padding,
       @required double maxCrossAxisExtent,
        double mainAxisSpacing: 0.0, double crossAxisSpacing: 0.0,
         double childAspectRatio: 1.0, 
         bool addAutomaticKeepAlives: true,
          bool addRepaintBoundaries: true, 
          bool addSemanticIndexes: true,
           List<Widget> children: const [], 
           int semanticChildCount })
           
    Creates a scrollable, 2D array of widgets with tiles that 
    each have a maximum cross-axis extent. [...]
    
    分析和使用
     ///GridView.extent 允许您指定项的最大像素宽度
      Widget gridViewDefaultExtent(List<BaseBean> list) {
        return GridView.extent(
          ///设置item的最大像素宽度  比如 130
          maxCrossAxisExtent: 130.0,
    
          ///其他属性和count一样
          children: initListWidget(list),
        );
      }
    

    GridView.builder

    构造函数
    GridView.builder({Key key, Axis scrollDirection: Axis.vertical,
     bool reverse: false, ScrollController controller, 
     bool primary, ScrollPhysics physics,
      bool shrinkWrap: false, EdgeInsetsGeometry padding, 
      @required SliverGridDelegate gridDelegate, 
      @required IndexedWidgetBuilder itemBuilder,
       int itemCount, bool addAutomaticKeepAlives: true,
        bool addRepaintBoundaries: true, 
        bool addSemanticIndexes: true, 
        double cacheExtent, int semanticChildCount })
        
    Creates a scrollable, 2D array of widgets that are created on demand. [...]
    
    分析和使用
     ///GridView.builder  可以定义gridDelegate的模式
      Widget gridViewDefaultBuilder(List<BaseBean> list) {
        return GridView.builder(
            gridDelegate: MyGridViewDefaultCustom(
              crossAxisCount: 2,
              mainAxisSpacing: 10.0,
              crossAxisSpacing: 10.0,
              childAspectRatio: 1.0,
            ),
            itemBuilder: (context, i) => new Container(
                  child: new Row(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    children: <Widget>[
                      new Text(
                        "${list[i].name}",
                        style: new TextStyle(fontSize: 18.0, color: Colors.red),
                      ),
                      new Text(
                        "${list[i].age}",
                        style: new TextStyle(fontSize: 18.0, color: Colors.green),
                      ),
                      new Text(
                        "${list[i].content}",
                        style: new TextStyle(fontSize: 18.0, color: Colors.blue),
                      ),
                    ],
                  ),
                ));
      }
    
    ///自定义SliverGridDelegate
    class MyGridViewDefaultCustom extends SliverGridDelegate {
      ///横轴上的子节点数。  一行多少个child
      final int crossAxisCount;
    
      ///沿主轴的每个子节点之间的逻辑像素数。 默认垂直方向的子child间距  这里的是主轴方向 当你改变 scrollDirection: Axis.vertical,就是改变了主轴发方向
      final double mainAxisSpacing;
    
      ///沿横轴的每个子节点之间的逻辑像素数。默认水平方向的子child间距
      final double crossAxisSpacing;
    
      ///每个孩子的横轴与主轴范围的比率。 child的宽高比  常用来处理child的适配
      final double childAspectRatio;
    
      bool _debugAssertIsValid() {
        assert(mainAxisSpacing >= 0.0);
        assert(crossAxisSpacing >= 0.0);
        assert(childAspectRatio > 0.0);
        return true;
      }
    
      const MyGridViewDefaultCustom({
        @required this.crossAxisCount,
        this.mainAxisSpacing = 0.0,
        this.crossAxisSpacing = 0.0,
        this.childAspectRatio = 1.0,
      })  : assert(crossAxisCount != null && crossAxisCount > 0),
            assert(mainAxisSpacing != null && mainAxisSpacing >= 0),
            assert(crossAxisSpacing != null && crossAxisSpacing >= 0),
            assert(childAspectRatio != null && childAspectRatio > 0);
    
      ///  返回值有关网格中图块大小和位置的信息。这里就是处理怎么摆放 我们可以自己定义
      ///   SliverGridLayout是抽象类  SliverGridRegularTileLayout继承于SliverGridLayout是抽象类
      @override
      SliverGridLayout getLayout(SliverConstraints constraints) {
        // TODO: implement getLayout
        assert(_debugAssertIsValid());
    
        ///对参数的修饰 自定义
        final double usableCrossAxisExtent =
            constraints.crossAxisExtent - crossAxisSpacing * (crossAxisCount - 1);
        final double childCrossAxisExtent = usableCrossAxisExtent / crossAxisCount;
        final double childMainAxisExtent = childCrossAxisExtent / childAspectRatio;
        return MySliverGridLayout(
          crossAxisCount: crossAxisCount,
          mainAxisStride: childMainAxisExtent + mainAxisSpacing,
          crossAxisStride: childCrossAxisExtent + crossAxisSpacing,
          childMainAxisExtent: childMainAxisExtent,
          childCrossAxisExtent: childCrossAxisExtent,
          reverseCrossAxis: axisDirectionIsReversed(constraints.crossAxisDirection),
        );
      }
    
      /// 和ListView的 shouldRebuild 作用一样   之前的实例和新进来的实例是相同的就返回true
      @override
      bool shouldRelayout(SliverGridDelegate oldDelegate) {
        // TODO: implement shouldRelayout
        return true;
      }
    }
    

    GridView.custom

    构造函数
    GridView.custom({Key key, Axis scrollDirection: Axis.vertical,
     bool reverse: false, ScrollController controller, 
     bool primary, ScrollPhysics physics, 
     bool shrinkWrap: false, 
     EdgeInsetsGeometry padding,
      @required SliverGridDelegate gridDelegate,
      @required SliverChildDelegate childrenDelegate, 
      double cacheExtent,
       int semanticChildCount })
       
    Creates a scrollable, 2D array of widgets with both a custom
     SliverGridDelegate and a custom SliverChildDelegate. [...]
    
    分析和使用
     ///GridView.custom 就是自己定制规则
      /// 这里说一下 GridView.count gridDelegate 其实就是内部实现 SliverGridDelegateWithFixedCrossAxisCount
      /// GridView.extent gridDelegate 其实就是内部实现 SliverGridDelegateWithMaxCrossAxisExtent
      Widget gridViewDefaultCustom(List<BaseBean> list) {
        return GridView.custom(
          gridDelegate: MyGridViewDefaultCustom(
            crossAxisCount: 2,
            mainAxisSpacing: 10.0,
            crossAxisSpacing: 10.0,
            childAspectRatio: 1.0,
          ),
          childrenDelegate: MyGridChildrenDelegate(
            (BuildContext context, int i) {
              return new Container(
                  child: new Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  new Text(
                    "${list[i].name}",
                    style: new TextStyle(fontSize: 18.0, color: Colors.red),
                  ),
                  new Text(
                    "${list[i].age}",
                    style: new TextStyle(fontSize: 18.0, color: Colors.green),
                  ),
                  new Text(
                    "${list[i].content}",
                    style: new TextStyle(fontSize: 18.0, color: Colors.blue),
                  ),
                ],
              ));
            },
            childCount: list.length,
          ),
        );
      }
    
    /**
     * 继承SliverChildBuilderDelegate  可以对列表的监听
     */
    class MyGridChildrenDelegate extends SliverChildBuilderDelegate {
      MyGridChildrenDelegate(
        Widget Function(BuildContext, int) builder, {
        int childCount,
        bool addAutomaticKeepAlive = true,
        bool addRepaintBoundaries = true,
      }) : super(builder,
                childCount: childCount,
                addAutomaticKeepAlives: addAutomaticKeepAlive,
                addRepaintBoundaries: addRepaintBoundaries);
    
      ///监听 在可见的列表中 显示的第一个位置和最后一个位置
      @override
      void didFinishLayout(int firstIndex, int lastIndex) {
        print('firstIndex: $firstIndex, lastIndex: $lastIndex');
      }
    
      ///可不重写 重写不能为null  默认是true  添加进来的实例与之前的实例是否相同 相同返回true 反之false
      ///listView 暂时没有看到应用场景 源码中使用在 SliverFillViewport 中
      @override
      bool shouldRebuild(SliverChildBuilderDelegate oldDelegate) {
        // TODO: implement shouldRebuild
        print("oldDelegate$oldDelegate");
        return super.shouldRebuild(oldDelegate);
      }
    }
    
    展开全文
  • GridView例子

    2010-04-02 13:35:18
    很全的GridView例子 例子 GridView自动编号 GridView增删改 GridView隐藏列 GridView行背景颜色 GridView突显单元格 GridView省略字符 GridView求和平均值 GridView排序 GridView结合控件 GridView合并表头 GridView...
  • 今天我们来模仿一下支付宝钱包首页中带有分割线的GridView,俗称九宫格。 详情:http://blog.csdn.net/finddreams 其实实现这种效果并不难,原理就是让每个item都设置成带有分割线的背景,这样就很容易实现了。
  • Android GridView完美横向滑动 ,并且可限制Gridview显示行数!
  • GridView使用详解

    万次阅读 多人点赞 2018-01-25 16:33:51
    GridView基本使用方法  GridView是一个在二维可滚动的网格中展示内容的控件。网格中的内容通过使用adapter自动插入到布局中。  下面通过实现一个简单的显示省份名的demo,介绍GridView控件的基本使用方法: 在...

    GridView基本使用方法

      GridView是一个在二维可滚动的网格中展示内容的控件。网格中的内容通过使用adapter自动插入到布局中。
      下面通过实现一个简单的显示省份名的demo,介绍GridView控件的基本使用方法:

    在布局中使用GridView控件,实现activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.example.sunxiaodong.androidgridview.MainActivity">
    
        <GridView
            android:id="@+id/grid_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:columnWidth="90dp"
            android:gravity="center"
            android:horizontalSpacing="10dp"
            android:numColumns="auto_fit"
            android:stretchMode="columnWidth"
            android:verticalSpacing="10dp" />
    
    </RelativeLayout>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

      这个GridView会填充满整个屏幕,关于使用属性的说明,在下一节“GridView主要属性详解”中将进行说明。

    MainActivity.java中,获取GridView控件,并进行初始化设置

    public class MainActivity extends AppCompatActivity {
    
        private GridView mGridView;
        private ProvinceAdapter mProvinceAdapter;
        private String[] provinceNames = new String[]{"北京", "上海", "广东", "广西", "天津", "重庆", "湖北", "湖南", "河北", "河南", "山东"};
        private int[] bgColor = new int[]{R.color.color_00ff00, R.color.color_ff0000, R.color.color_ff0000, R.color.color_ffff00,
                R.color.color_8e35ef, R.color.color_303F9F, R.color.color_00ff00, R.color.color_ff0000, R.color.color_ff0000,
                R.color.color_ffff00, R.color.color_8e35ef};
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initView();
        }
    
        private void initView() {
            mGridView = (GridView) this.findViewById(R.id.grid_view);
            List<ProvinceBean> provinceBeanList = new ArrayList<>();
            for (int i = 0; i < provinceNames.length; i++) {
                ProvinceBean provinceBean = new ProvinceBean();
                provinceBean.setName(provinceNames[i]);
                provinceBean.setColor(bgColor[i]);
                provinceBeanList.add(provinceBean);
            }
            mProvinceAdapter = new ProvinceAdapter(this, provinceBeanList);
            mGridView.setAdapter(mProvinceAdapter);
        }
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

      程序中,首先使用findViewById方法获取到了GridView控件,接下来使用setAdapter方法给它设置提供数据的适配器。程序中,引入了两份数据provinceNames 和bgColor,其中provinceNames定义了依次显示在GridView各网格中的省份名称,bgColor定义了依次显示在GridView网格中的省份名称的背景色,这些只是为了更方便读者从视觉上认识GridView。

    创建ProvinceAdapter.java文件,实现数据在GridView中的展示

    public class ProvinceAdapter extends BaseAdapter {
    
        private List<ProvinceBean> provinceBeanList;
        private LayoutInflater layoutInflater;
    
        public ProvinceAdapter(Context context, List<ProvinceBean> provinceBeanList) {
            this.provinceBeanList = provinceBeanList;
            layoutInflater = LayoutInflater.from(context);
        }
    
        @Override
        public int getCount() {
            return provinceBeanList.size();
        }
    
        @Override
        public Object getItem(int position) {
            return provinceBeanList.get(position);
        }
    
        @Override
        public long getItemId(int position) {
            return 0;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;
            if (convertView == null) {
                convertView = layoutInflater.inflate(R.layout.province_grid_view_item_layout, null);
                holder = new ViewHolder();
                holder.text = (TextView) convertView.findViewById(R.id.text);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
            ProvinceBean provinceBean = provinceBeanList.get(position);
            if (provinceBean != null) {
                holder.text.setText(provinceBean.getName());
                holder.text.setBackgroundResource(provinceBean.getColor());
            }
            return convertView;
        }
    
        class ViewHolder {
            TextView text;
        }
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

      ProvinceAdapter继承自BaseAdapter,有几个必须实现的方法getCount()getItem(int position)getItemId(int position)getView(int position, View convertView, ViewGroup parent)。其中,getCount()返回需要展示的GridView的项数。getItem(int position)返回给定位置的数据对象。getItemId(int position)返回该项的行id。getView(int position, View convertView, ViewGroup parent)是必须要实现的方法,该方法控制GridView中数据项的显示,方法中的convertView视图是被复用的视图,在实现时对其进行判断,如果为null,则新建视图,否则直接复用视图。

      上面程序的执行效果如下图所示:
    这里写图片描述

    GridView的属性和方法详解

    GridView的主要属性

    • android:columnWidth
      相关方法setColumnWidth(int)。定义每一列的固定宽度。
      必须是dimension值(浮点数后面拼接单位,例如“14.5sp”)。有效的单位有:px,dp,sp,in,mm。
      它也可以是一个资源的引用(@[package:]type:name)或主题属性(?[package:][type:]name)。
    • android:gravity
      相关方法setGravity(int)。定义每一个单元格的重心。
      必须是一个或多个(使用“|”分隔)下面的常量
    常量 描述
    top 0x30 将对象放在它的容器的顶部,不会改变它的大小
    bottom 0x50 将对象放在它的容器的底部,不会改变它的大小
    left 0x03 将对象放在它的容器的左面,不会改变它的大小
    right 0x05 将对象放在它的容器的右面,不会改变它的大小
    center_vertical 0x10 将对象放在它的容器垂直方向的中心,不会改变它的大小
    fill_vertical 0x70 如果需要改变对象的垂直大小以完全填充它的容器
    center_horizontal 0x01 将对象放在它的容器水平方向的中心,不会改变它的大小
    fill_horizontal 0x07 如果需要改变对象的水平大小以完全填充它的容器
    center 0x11 将对象放在它的容器的中心,不会改变它的大小
    fill 0x77 如果需要改变对象的水平和垂直方向的大小以完全填充它的容器
    clip_vertical 0x80 附加选项被设置用来将子视图的上面或下面边缘裁剪到它的容器的边界。这个裁剪基于垂直方向的重心:top重心将会裁剪底部边缘,bottom重心将会裁剪顶部边缘,不会同时裁剪两边
    clip_horizontal 0x08 附加选项被设置用来将子视图的左面或右面边缘裁剪到它的容器的边界。这个裁剪基于水平方向的重心:left重心将会裁剪右面边缘,right重心将会裁剪左面边缘,不会同时裁剪两边
    start 0x00800003 将对象放在它的容器的起始位置,不会改变它的大小
    end 0x00800005 将对象放在它的容器的末尾位置,不会改变它的大小
    • android:horizontalSpacing
      相关方法setHorizontalSpacing(int)。定义了两列之间的水平间隔。
      属性设置要求同android:columnWidth
    • android:numColumns
      相关方法setNumColumns(int)。定义了展示的列数。
      可以是一个整形值,如“100”。也可以是一个资源的引用(@[package:]type:name)或主题属性(?[package:][type:]name)。或者下面的这个常量:
    常量 描述
    auto_fit -1 在有效空间展示尽量多的列数
    • android:stretchMode
      相关方法setStretchMode(int)。定义了列拓展填充有限闲置空间的方式。
      必须是下面常量值中的一个:
    常量 描述
    none 0 扩展无效
    spacingWidth 1 列与列之间的空间被扩展
    columnWidth 2 每一列被相等的拓展
    spacingWidthUniform 3 列与列之间的空间被均匀的扩展
    • android:verticalSpacing
      相关方法setVerticalSpacing(int)。定义两行之间的垂直间隔。
      属性设置要求同android:columnWidth

    GridView的主要方法

    Public方法
    • ListAdapter:getAdapter()
      返回关联的Adapter
    • int:getColumnWidth()
      返回列的宽度
    • int:getGravity()
      返回描述子视图被放置的方式的标识。默认为Gravity.LEFT
    • int:getHorizontalSpacing()
      返回列间的水平间隔大小。
      仅会计算当前布局。如果调用了setHorizontalSpacing(int)来设置间隔,但布局还没有完成,这个方法会返回一个旧值。如果想要明确地获取这个间隔,使用getRequestedHorizontalSpacing()方法请求。
    • int:getNumColumns()
      返回列数。如果网格没有被布局,则返回AUTO_FIT
    • int:getRequestedColumnWidth()
      返回请求的列宽度。
      这可能不是真实的列宽度。使用getColumnWidth()获取当前真实的列宽度。
    • int:getRequestedHorizontalSpacing()
      返回请求的列间的水平间隔。
      这个值可能是布局期间的局部样式,也可能是默认的样式,或是使用setHorizontalSpacing(int)方法设置的值。如果布局尚未完成或GridView计算得到了一个和请求的不同的水平间隔,它与getHorizontalSpacing()将有不同的返回值。
    • int:getStretchMode()
      返回扩展模式。
    • int:getVerticalSpacing()
      返回行间的垂直间隔。
    • onInitializeAccessibilityNodeInfoForItem(View view, int position, AccessibilityNodeInfo info)
      使用列表中实际项的信息初始化一个AccessibilityNodeInfo
    参数 描述
    View 呈现列表项的视图
    position 在Adapter中列表项的位置
    info 需要初始化的信息项(Node Info)
    • boolean:onKeyDown(int keyCode, KeyEvent event)
      KeyEvent.Callback.onKeyDown()的默认实现:如果视图可点击,当KEYCODE_DPAD_CENTERKEYCODE_ENTER被释放时,执行视图按下事件。
      软键盘上的按键事件通常不会触发这个监听,尽管有些条件下可能会触发,但不要依赖它去捕获关键盘按键事件。
      返回值:处理返回true,否则返回false。
    • boolean:onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)
      KeyEvent.Callback.onKeyMultiple()的默认实现:一直返回false。
      软键盘上的按键事件通常不会触发这个监听,尽管有些条件下可能会触发,但不要依赖它去捕获关键盘按键事件。
      返回值:处理返回true,否则返回false。
    • boolean:onKeyUp(int keyCode, KeyEvent event)
      KeyEvent.Callback.onKeyUp()的默认实现:当KEYCODE_DPAD_CENTERKEYCODE_ENTER被释放时,执行视图点击事件。
      软键盘上的按键事件通常不会触发这个监听,尽管有些条件下可能会触发,但不要依赖它去捕获关键盘按键事件。
      返回值:处理返回true,否则返回false。
    • setAdapter(ListAdapter adapter)
      为GridView设置数据。
    • setColumnWidth(int columnWidth)
      设置宽度。
    • setGravity(int gravity)
      设置网格的中重心。重心描述了子视图的摆放方式。默认是Gravity.LEFT
    • setHorizontalSpacing(int horizontalSpacing)
      设置列间的水平间隔。
    • setNumColumns(int numColumns)
      设置列数。
    • setRemoteViewsAdapter(Intent intent)
      设置该AbsListView使用远程视图适配器,该适配器通过特定的Intent连接到一个RemoteViewsService。
    • setSelection(int position)
      设置当前选中项。
    • setStretchMode(int stretchMode)
      设置列表项如何拓展填充闲置空间的方式。
      可以设置下面常量值中的一个:
    常量 描述
    NO_STRETCH 0 扩展无效
    STRETCH_COLUMN_WIDTH 2 扩展列
    STRETCH_SPACING 1 扩展列间的空间
    STRETCH_SPACING_UNIFORM 3 均匀地扩展列间的空间
    • setVerticalSpacing(int verticalSpacing)
      设置行间的垂直间隔。
    • smoothScrollByOffset(int offset)
      平滑地滚动到具体的适配器位置的偏移位置。视图会滚动到指定位置显示出来。
    • smoothScrollToPosition(int position)
      平滑地滚动到具体的适配器位置。视图会滚动到指定位置显示出来。
    Protected方法
    • attachLayoutAnimationParameters(View child, ViewGroup.LayoutParams params, int index, int count)
      子视图可以覆写该方法来在提供的child上设置布局动画参数。
    参数 描述
    child 和动画参数关联的子视图
    params 持有动画参数的子视图的布局参数
    index 子视图在视图组中的索引
    count 视图组中子视图的数量
    • computeVerticalScrollExtent()
      计算滚动条把手在纵向滚动范围内占用的幅度。该值用于计算滚动条把手在滚动条滑道中的长度。
      范围使用与computeVerticalScrollRange()computeVerticalScrollOffset()相同的任意单位。
      默认的长度是视图的可绘制高度。
      返回值:滚动条把手在纵向滚动范围内占用的幅度。
    • computeVerticalScrollOffset()
      计算滚动条把手在纵向滚动范围内的位置。该值用于计算滚动条把手在滚动条滑道中的位置。
      范围使用与computeVerticalScrollRange()computeVerticalScrollExtent()相同的任意单位。
      默认位置是视图的滚动条位置。
      返回值:滚动条把手的纵向位置
    • computeVerticalScrollRange()
      计算垂直滚动条的垂直范围。
      范围使用与computeVerticalScrollExtent()computeVerticalScrollOffset()相同的任意单位。
      返回值:纵向滚动条代表的整个纵向范围。默认纵向范围时视图的绘制高度。
    • layoutChildren()
      子类必须实现该方法,来布局子视图
    • onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect)
      当视图焦点状态改变时,视图系统调用该方法。由定向导航导致的焦点变更时,direction和previouslyFocusedRect提供了焦点是从那里来的进一步信息。
    参数 描述
    gainFocus 如果视图具有焦点,值为真;否则为假
    direction 当调用requestFocus()为该视图设置焦点时,该值为焦点移动的方向。其值为FOCUS_UP、FOCUS_DOWN、FOCUS_LEFT或者FOCUS_RIGHT
    previouslyFocusedRect 失去焦点的视图的矩形坐标,使用该视图的坐标系统.如果指定了,它将传入可以知道焦点来自哪里的详细信息(作为对direction 的补充)。否则,其值为null
    • onMeasure(int widthMeasureSpec, int heightMeasureSpec)
      对视图及其内容进行测量,来决定布局的宽和高。
    展开全文
  • GridView详解

    千次阅读 2016-03-26 03:01:28
    GridView详解
  • Android自定义较为精美的GridView

    万次阅读 2020-09-05 18:00:49
    与ListView主要以列表形式显示数据不同,GridView是以网格形式显示数据,本文实现了一个较为精美的GridView
  • ViewPager + GridView实现GridView分页

    千次阅读 2016-11-04 14:37:07
    通过ViewPager实现GridView的分页 实现 ViewPager通过设置PagerAdapter实现分页。每一页的布局是一个GridViewGridView通过设置自己adapter渲染GridView。 ViewPager:分页器。 GridViewPageAdapter:继承自...
  • Android GridView

    千次阅读 2018-06-22 14:42:51
    其实GridView跟LlistView是一样一样的用法LIstView 是线性排列的GridView是网格排列的其中设置它的烈属的属性是numColumns,除此之外没有别的网格布局的话是不可以添加头布局的...
  • 于是使用一个GridView,显示3*4块内容;而每块内容又是一个GridView,这里面则显示5*4个图片 可是现在显示出现了问题:  每块都只显示一行,因为这一行内容不知道为什么,被莫名的拉长了 请问有知道...
  • Flutter网格控件GridView

    千次阅读 2019-02-28 19:09:18
    Flutter GridView用法详解。Flutter GridView异步加载
  • 多个GridView, 用一个事件 Protected Sub GridView_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView2.RowDataBound 在线等
  • GridView布局

    2017-10-03 15:27:47
    2017.10.03今天下午学习了Gridview布局,大体上和ListView是一样的,但它有几个特殊的属性 android:numColumns=”3” android:verticalSpacing=”10dp” 竖直间距 android:horizontalSpacing=”10dp”水平间距...
  • gridview
  • GridView排序

    2017-11-16 16:52:31
    this._GridView1.Columns[0].FieldNameSortGroup = "SORT_ASC";
  • 自定义GridView:解决ScrollView嵌套GridViewGridView只显示两行,自定义GridView完全展开 package cn.powerthink.djt.utils; import android.content.Context; import android.util.AttributeSet; import ...
  • GridView固定表头和列 实例(GridView冻结表头和列)

    千次下载 热门讨论 2013-05-05 11:39:57
    这个与asp.net中GridView相关的一个实例,实现GridView冻结表头和列,挺好用的。
  • 这个功能主要是在数据结构这一块,先上图看看效果:重点 是放在左边这个listview嵌套gridview,可删除gridview中item,也可点击最后一项手动增加item数据,这里看几行重要的代码,源码放在底部,可供下载android...
  • gridview横向布局(gridView嵌套HorizontalScrollView场景)
  • Android ScrollView嵌套GridView导致GridView只显示一行itemAndroid ScrollView在嵌套GridView时候,会导致一个问题发生:GridView只显示一行。比如,在一个大的根ScrollView里面套一个根、大的垂直线性布局,此线性...
  •  /** * 获取GridView的高度 * @param gridView ...private int getGridViewHeight(GridView gridView){ ListAdapter adapter = gridView.getAdapter(); int height = 0; int ite
  • 想了解更多关于Flutter的知识,可以关注: ...在上一篇文章 GridView.count 中讲过 GridView.count的用法,这里讲一下GridView.extent的用法。 GridView.count 是在交叉轴上创建固定个数的Item,cross...
  • GridViewAdapter

    千次阅读 2017-02-08 15:19:05
    留着以后备用/** * Created by pig on 2017/2/7. ... public class GridViewAdapter extends BaseAdapter{ private Context context; private List<ResultBeanData.ResultBean.ChannelInfoBean> channel_info;
  • android:listSelector="@null" 作用很大,可以去掉GridView左和上的空白区域 <GridView android:id="@+id/source_photo_one_grid" android:layout_width="wrap_content" android:layout_height="wrap_content" ...
  • ScrollView嵌套GridViewGridView显示不全

    千次阅读 2016-04-06 20:10:05
    在ScrollView里布局GridView时,GridView显示往往是以单行显示出来。这是由于GridView和ScrollView里都有滑动属性。ScrollView无法判断GridView里的item高度是多少,于是只显示单个Item的高度,也就是单行显示了,...
  • 在一次做三级导航的过程中,我将第三级列表(GridView)放入到了一个RecyclerView的条目中,但是无论测试多少次,我的GridView都是只能显示一行,显示不全,屡试屡败,最终这个问题才得以解决: 创建自定义View...
  • gridview回顾

    千次阅读 热门讨论 2013-12-18 22:03:43
    第一看asp.net是在做项目之前,感觉收获也很大,第二次看gridview是在做完项目之后对GridView的回顾,这次的感觉是:我需要多想点,知识直到用时方觉少。直入正题吧,看gridview。 一、主要的事件 (1)...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 49,854
精华内容 19,941
关键字:

gridview