1 章节目录

2 适配器

2.1 适配器简介

2.2 适配器类别

3 Spinner下拉

3.1 Spinner的两种展示样式

3.2 Spinner相关方法

3.3 Spinner用法

3.4 加载XML文件以及选择项

3.5 动态加载的选择项(使用ArrayAdapter适配器)

3.6 dropdown模式下的列表分割线

4 Dialog对话框

4.1 普通对话框

4.2 列表对话框

4.3 单选列表对话框

4.4 多选列表对话框

4.5 半自定义对话框

4.6 自定义对话框

4.7 圆形进度条对话框

4.8 水平进度条对话框

4.9 BottomSheetDialog(可以上下拖动的对话框)

5 ListView列表

5.1 ListView简介

5.2 列表的显示需要三个元素

5.3 ListView + ArrayAdapter

5.4 ListView + SimpleAdapter

5.5 ListView的监听函数

6 GridView网格

6.1 GridView简介

6.2 GridView + ArrayAdapter

6.3 GridView + SimpleAdapter


2 适配器

2.1 适配器简介

适配器是一个连接数据源和AdapterView的桥梁,通过它能有效的实现数据源与AdapterView的分离设置,使AdaptereView与数据的绑定更加简便,修改更加方便。

2.2 适配器类别

根据列表的适配器类型,列表分为三种,ArrayAdapter,SimpleAdapter和SimpleCursorAdapter

  1. ArrayAdapter最为简单,只能展示一行字。

  2. SimpleAdapter有最好的扩充性,可以自定义出各种效果。

  3. SimpleCursorAdapter可以认为是SimpleAdapter对数据库的简单结合,可以方面的把数据库的内容以列表的形式展示出来。

3 Spinner下拉

3.1 Spinner的两种展示样式

下拉列表的展示方式有两种,一种是在当前下拉框的正下方展示列表,此时把spinnerMode属性设置为dropdown;另一种是在页面中部以对话框形式展示列表,此时把SpinnerMode属性设置为dialog。

3.2 Spinner相关方法

  • setPrompt:设置标题文字。

  • setAdapter:设置下拉列表的适配器。

  • setSelection:设置当前选中哪项。注意该方法要在setAdapter方法之后调用。

  • setOnItemSelectedListener:设置下拉列表的选择监听器,该监听器要实现接口OnItemSelectedListener。

3.3 Spinner用法

  • 渲染一个Spinner在XML,并通过加载XML文件以及选择项。

  • 呈现另一种Spinner的XML,并通过代码动态加载的选择项

3.4 加载XML文件以及选择项

1. 打开“res/values/strings.xml” 文件,定义将在Spinner(下拉列表)显示的项目列表。

<?xml version="1.0" encoding="utf-8"?>
<resources>
 
    <string name="app_name">选择一个国家</string>
    <string name="country_prompt">Choose a country</string>
 
    <string-array name="country_arrays">
        <item>China</item>
        <item>United States</item>
        <item>Indonesia</item>
        <item>France</item>
        <item>Italy</item>
        <item>Singapore</item>
        <item>New Zealand</item>
        <item>India</item>
    </string-array>
 
</resources>
2. 打开XML布局文件**activity_main.xml** 
  • “android:entries” 代表 spinner 的选择项目。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
 
    <Spinner
        android:id="@+id/spinner1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:entries="@array/country_arrays"
        android:prompt="@string/country_prompt" />
</LinearLayout>

3.5 动态加载的选择项(使用ArrayAdapter适配器)

  1. XML布局文件activity_main.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">
  
    <Spinner
        android:layout_width="200dp"
        android:id="@+id/spinner"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:spinnerMode="dropdown"
        android:dropDownVerticalOffset="45dp"
        android:background="@null"/>
</LinearLayout>
  1. 选中文字样式item_select.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="45dp"
    android:background="@android:color/holo_blue_dark"
    android:textSize="14sp"
    android:textColor="@android:color/holo_red_light"
    android:gravity="center"/>
  1. 列表其他文字样式item_dropdown.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="45dp"
    android:textColor="@android:color/black"
    android:textSize="14sp"
    android:gravity="center"/>
  1. Java代码MainActivity.java

public class MainActivity extends AppCompatActivity{
 
    private String[] starArray = {"水星","金星","地球","火星","木星","土星"};
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initSpinner();
    }
 
    private void initSpinner(){
        //声明一个下拉列表的数组适配器
        ArrayAdapter<String> starAdapter = new ArrayAdapter<String>(this,R.layout.item_select,starArray);
        //设置数组适配器的布局样式
        starAdapter.setDropDownViewResource(R.layout.item_dropdown);
        //从布局文件中获取名叫sp_dialog的下拉框
        Spinner sp = findViewById(R.id.spinner);
        //设置下拉框的标题,不设置就没有难看的标题了
        sp.setPrompt("请选择行星");
        //设置下拉框的数组适配器
        sp.setAdapter(starAdapter);
        //设置下拉框默认的显示第一项
        sp.setSelection(0);
        //给下拉框设置选择监听器,一旦用户选中某一项,就触发监听器的onItemSelected方法
        sp.setOnItemSelectedListener(new MySelectedListener());
    }
 
    class MySelectedListener implements AdapterView.OnItemSelectedListener{
 
        @Override
        public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
            Toast.makeText(MainActivity.this,"您选择的是:"+starArray[i],Toast.LENGTH_SHORT).show();
        }
 
        @Override
        public void onNothingSelected(AdapterView<?> adapterView) {
 
        }
    }
}

3.6 dropdown模式下的列表分割线

只需要在style中添加如下代码即可

添加样式

<style name="XSpinnerStyle" parent="android:Widget.ListView.DropDown">
        <!-- 分隔线颜色 -->
        <item name="android:divider">#000000</item>
        <item name="android:dividerHeight">1dp</item>
</style>

然后在AppTheme中调用

<item name="android:dropDownListViewStyle">@style/XSpinnerStyle</item>

4 Dialog对话框

对话框一般我们就用来提示一些信息给用户,让用户自主选择,或者在一些操作不可逆的情况下我们提示用户是否继续操作

4.1 普通对话框

AlertDialog dialog = new AlertDialog.Builder(this)
                .setIcon(R.mipmap.icon)//设置标题的图片
                .setTitle("我是对话框")//设置对话框的标题
                .setMessage("我是对话框的内容")//设置对话框的内容
                //设置对话框的按钮
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Toast.makeText(MainActivity.this, "点击了取消按钮", Toast.LENGTH_SHORT).show();
                        dialog.dismiss();
                    }
                })
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Toast.makeText(MainActivity.this, "点击了确定的按钮", Toast.LENGTH_SHORT).show();
                        dialog.dismiss();
                    }
                }).create();
        dialog.show();

AlertDialog类中有一个静态内部类Builder。所以可以看出对话框使用了一个建造者模式在调用函数的时候就可以一直直点点点链式调用。 需要注意的是:NegativeButton这个按钮是在对话框的左边,PositiveButton在对话框的右边;如果你还想再加一个按钮也是可以的只需要在调用.setNeutralButton("第三个按钮",listener)即可。

4.2 列表对话框

当给用户的选择就那么几条路的时候,就可在对话框上放置一个列表供用户自己选择

final String items[] = {"我是Item一", "我是Item二", "我是Item三", "我是Item四"};
        AlertDialog dialog = new AlertDialog.Builder(this)
                .setIcon(R.mipmap.icon)//设置标题的图片
                .setTitle("列表对话框")//设置对话框的标题
                .setItems(items, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Toast.makeText(MainActivity.this, items[which], Toast.LENGTH_SHORT).show();
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                })
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                }).create();
        dialog.show();

源码已经预留好了设置方法,所以只需要调用.setItems()即可,第一个参数即要显示item的数组,第二个参数也就是点击item后的监听事件还是so easy的。

4.3 单选列表对话框

单选列表对话框与列表对话框差不多是一样的,只是它是单选

final String items[] = {"我是Item一", "我是Item二", "我是Item三", "我是Item四"};
        AlertDialog dialog = new AlertDialog.Builder(this)
                .setIcon(R.mipmap.icon)//设置标题的图片
                .setTitle("单选列表对话框")//设置对话框的标题
                .setSingleChoiceItems(items, 1, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Toast.makeText(MainActivity.this, items[which], Toast.LENGTH_SHORT).show();
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                })
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                }).create();
        dialog.show();

.setSingleChoiceItems(items, 1, listener)第一个参数:设置单选的资源数组;第二个参数:设置默认选中哪一项。

4.4 多选列表对话框

既然有单选列表,那自然而然也就肯定有多选列表啦

final String items[] = {"我是Item一", "我是Item二", "我是Item三", "我是Item四"};
        final boolean checkedItems[] = {true, false, true, false};
        AlertDialog dialog = new AlertDialog.Builder(this)
                .setIcon(R.mipmap.icon)//设置标题的图片
                .setTitle("多选对话框")//设置对话框的标题
                .setMultiChoiceItems(items, checkedItems, new DialogInterface.OnMultiChoiceClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which, boolean isChecked) {
                        checkedItems[which] = isChecked;
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                })
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        for (int i = 0; i < checkedItems.length; i++) {
                            if (checkedItems[i]) {
                                Toast.makeText(MainActivity.this, "选中了" + i, Toast.LENGTH_SHORT).show();
                            }
                        }
                        dialog.dismiss();
                    }
​
                }).create();
​
        dialog.show();

.setMultiChoiceItems(items, checkedItems, listener)//第一个参数:设置单选的资源;第二个参数:设置默认选中哪几项(数组);

4.5 半自定义对话框

或许上面几种对话框的款式都不是你需要或者喜欢的,那你肯定就需要开始自定义了;源码为我们提供了一个.setView()函数,这样我们就可以自定义对话框显示的内容了

 View view = getLayoutInflater().inflate(R.layout.half_dialog_view, null);
        final EditText editText = (EditText) view.findViewById(R.id.dialog_edit);
        AlertDialog dialog = new AlertDialog.Builder(this)
                .setIcon(R.mipmap.icon)//设置标题的图片
                .setTitle("半自定义对话框")//设置对话框的标题
                .setView(view)
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                })
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        String content = editText.getText().toString();
                        Toast.makeText(MainActivity.this, content, Toast.LENGTH_SHORT).show();
                        dialog.dismiss();
                    }
                }).create();
        dialog.show();

上面代码中half_dialog_view.xml中我就放置了一个EditText;在这里好多人在找自己布局中的控件时候经常报NullpointException,原因也很简单就是没有使用加载的布局.findViewbyId()。到了这一步基本上就能满足开发中80%的需求了,看官如果还不能满足那别急慢慢往下看。

4.6 自定义对话框

上面我们说了可以通过调用.setView(view)方法,自定义其显示的内容;但是你会觉得这远远不够我还想把他的标题或者底部按钮给改了,那么就需要来个完全自定义了

  1. 首先我们需要自定义Dialog的style,让他自己本有的东西全部透明,然后在设置我们自己的内容就可以达到完全自定义的效果了。

 <!--对话框的样式-->
    <style name="NormalDialogStyle">
        <!--对话框背景 -->
        <item name="android:windowBackground">@android:color/transparent</item>
        <!--边框 -->
        <item name="android:windowFrame">@null</item>
        <!--没有标题 -->
        <item name="android:windowNoTitle">true</item>
        <!-- 是否浮现在Activity之上 -->
        <item name="android:windowIsFloating">true</item>
        <!--背景透明 -->
        <item name="android:windowIsTranslucent">false</item>
        <!-- 是否有覆盖 -->
        <item name="android:windowContentOverlay">@null</item>
        <!--进出的显示动画 -->
        <item name="android:windowAnimationStyle">@style/normalDialogAnim</item>
        <!--背景变暗-->
        <item name="android:backgroundDimEnabled">true</item>
    </style>
    <!--对话框动画-->
    <style name="normalDialogAnim" parent="android:Animation">
        <item name="@android:windowEnterAnimation">@anim/normal_dialog_enter</item>
        <item name="@android:windowExitAnimation">@anim/normal_dialog_exit</item>
    </style>
  1. 接下来就可以为对话框设置我们自定义的style了

/**
     * 自定义对话框
     */
    private void customDialog() {
        final Dialog dialog = new Dialog(this, R.style.NormalDialogStyle);
        View view = View.inflate(this, R.layout.dialog_normal, null);
        TextView cancel = (TextView) view.findViewById(R.id.cancel);
        TextView confirm = (TextView) view.findViewById(R.id.confirm);
        dialog.setContentView(view);
        //使得点击对话框外部不消失对话框
        dialog.setCanceledOnTouchOutside(true);
        //设置对话框的大小
        view.setMinimumHeight((int) (ScreenSizeUtils.getInstance(this).getScreenHeight() * 0.23f));
        Window dialogWindow = dialog.getWindow();
        WindowManager.LayoutParams lp = dialogWindow.getAttributes();
        lp.width = (int) (ScreenSizeUtils.getInstance(this).getScreenWidth() * 0.75f);
        lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
        lp.gravity = Gravity.CENTER;
        dialogWindow.setAttributes(lp);
        cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dialog.dismiss();
            }
        });
        confirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dialog.dismiss();
            }
        });
        dialog.show();
    }

同样我门通过调用这个dialog.setContentView(view);就可以设置我们自己的布局了。所以现在关键就是码我们的布局了一起来看看效果图

既然是自定义对话框,那么就肯定要来弄一弄他的方方面面;

  • 这里使用到了一个工具类用来计算手机屏幕的宽高,如下代码:

public class ScreenSizeUtils {
    private static ScreenSizeUtils instance = null;
    private int screenWidth, screenHeight;
​
    public static ScreenSizeUtils getInstance(Context mContext) {
        if (instance == null) {
            synchronized (ScreenSizeUtils.class) {
                if (instance == null)
                    instance = new ScreenSizeUtils(mContext);
            }
        }
        return instance;
    }
​
    private ScreenSizeUtils(Context mContext) {
        WindowManager manager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics dm = new DisplayMetrics();
        manager.getDefaultDisplay().getMetrics(dm);
        screenWidth = dm.widthPixels;// 获取屏幕分辨率宽度
        screenHeight = dm.heightPixels;// 获取屏幕分辨率高度
    }
​
    //获取屏幕宽度
    public int getScreenWidth() {
        return screenWidth;
    }
​
    //获取屏幕高度
    public int getScreenHeight() {
        return screenHeight;
    }
}
  • 我们现在可以自定义对话框了,那么我们就来实现一个经常用到的一个底部选择对话框,来看下效果图吧:

  • 先来码这个对话框的布局,dialog_bottom.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:background="@android:color/transparent"
    android:orientation="vertical">
​
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/round_corner"
        android:text="拍照" />
​
    <TextView
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:background="#ddd" />
​
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/round_corner"
        android:text="相册" />
​
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:background="@drawable/round_corner"
        android:text="取消" />
​
    <View
        android:layout_width="match_parent"
        android:layout_height="15dp" />
</LinearLayout>
  • 接下来就可以为我们的对话框加载这个布局了

Dialog dialog = new Dialog(this, R.style.NormalDialogStyle);
View view = View.inflate(this, R.layout.dialog_bottom, null);
dialog.setContentView(view);
dialog.setCanceledOnTouchOutside(true);
view.setMinimumHeight((int) (ScreenSizeUtils.getInstance(this).getScreenHeight() * 0.23f));
Window dialogWindow = dialog.getWindow();
WindowManager.LayoutParams lp = dialogWindow.getAttributes();
lp.width = (int) (ScreenSizeUtils.getInstance(this).getScreenWidth() * 0.9f);
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
lp.gravity = Gravity.BOTTOM;
dialogWindow.setAttributes(lp);
dialog.show();

上面这一段带代码的关键就是将Dialog放置在屏幕底部lp.gravity = Gravity.BOTTOM;并设置他的宽度为屏幕的90%lp.width = (int) (ScreenSizeUtils.getInstance(this).getScreenWidth() * 0.9f);。

4.7 圆形进度条对话框

ProgressDialog dialog = new ProgressDialog(this);
dialog.setMessage("正在加载中");
dialog.show();

4.8 水平进度条对话框

水平的进度条并显示当前进度,只需要把他的样式设置为ProgressDialog.STYLE_HORIZONTAL即可。

final ProgressDialog dialog = new ProgressDialog(this);
        dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        dialog.setMessage("正在加载中");
        dialog.setMax(100);
        final Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            int progress = 0;
​
            @Override
            public void run() {
                dialog.setProgress(progress += 5);
                if (progress == 100) {
                    timer.cancel();
                }
            }
        }, 0, 1000);
        dialog.show();

4.9 BottomSheetDialog(可以上下拖动的对话框)

BottomSheetDialog dialog = new BottomSheetDialog(this);
View view = getLayoutInflater().inflate(R.layout.activity_main, null);
dialog.setContentView(view);//设置显示的内容,我这为了方便就直接把主布局设置进去了。
dialog.show();

BottomSheetDialog会根据你设置的View大小来计算默认显示出来的高度,内容越多显示的越多反之则越少。当显示的内容比较少的时候他默认显示一点,这个时候就比较蛋疼了所以我们就要让他一显示就默认全部展开。

/**
         * 默认展开对话框
         */
        final FrameLayout frameLayout = (FrameLayout) dialog.findViewById(android.support.design.R.id.design_bottom_sheet);
        frameLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                //获得BottomSheetBehavior
                BottomSheetBehavior behavior = BottomSheetBehavior.from(frameLayout);
                //设置对话框的的状态
                behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
            }
        });

BottomSheetDialog的操作基本上都是通过Behavior来设置的,所以关键就是获得他的Behavior; 这里还有小坑就是:当你向下滑动让他消失的时候,对话框是看不见了但是他却并没有dismiss需要在点击一次屏幕才能完全消失。下面给出解决办法:通过监听他的状态来手动dismiss();

behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
             @Override
             public void onStateChanged(@NonNull View bottomSheet, int newState) {
                   if (newState == BottomSheetBehavior.STATE_HIDDEN)
                       dialog.dismiss();
             }
             @Override
             public void onSlide(@NonNull View bottomSheet, float slideOffset) {
​
             }
         });

5 ListView列表

5.1 ListView简介

在android开发中ListView是比较常用的组件,它以列表的形式展示具体内容,并且能够根据数据的长度自适应显示。

5.2 列表的显示需要三个元素

  1. ListVeiw 用来展示列表的View。

  2. 适配器 用来把数据映射到ListView上的中介。

  3. 数据 具体的将被映射的字符串,图片,或者基本组件。

5.3 ListView + ArrayAdapter

  • ArrayAdapter的使用

    ArrayAdapter(Context context, int textViewResourceId, List<T> objects)来装配数据

参数 1:当前的上下文环境

参数 2:当前列表项所加载的布局文件 ​ (android.R.layout.simple_list_item_1)这里的布局文件是Android内置的,里面只有一个textview控件用来显示简单的文本内容

参数 3:数据源

  • 代码实现

public  class  MyListView  extends  AppCompatActivity {
 
     private  ListView listView;
     //private List<String> data = new ArrayList<String>();
     @Override
     public  void  onCreate(Bundle savedInstanceState){
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_my_list);
         
         listView =  findViewById(R.id.lv);
         ArrayAdapter adapter =  new  ArrayAdapter<String>( this, android.R.layout.simple_expandable_list_item_1,getData());
         listView.setAdapter(adapter);
     }
    
     
     
     private  List<String> getData(){
         
         List<String> data =  new  ArrayList<String>();
         data.add( "测试数据1" );
         data.add( "测试数据2" );
         data.add( "测试数据3" );
         data.add( "测试数据4" );
         
         return  data;
     }
}
  • 实现效果

  • 小结:

    1. ArrayAdapter适用于数组或数据ArrayList(动态数组)。

    2. ArrayAdapter可以通过泛型来指定要适配的数据类型,然后在构造凼数中把要适配的数据传入。

    3. ArrayAdapter有多个构造函数的重载,可以根据实际情况选择最合适的一种。

5.4 ListView + SimpleAdapter

simpleAdapter的扩展性最好,可以定义各种各样的布局出来,可以放上ImageView(图片),还可以放上Button(按钮),CheckBox(复选框)等等。下面的代码都直接继承了ListActivity,ListActivity和普通的Activity没有太大的差别,不同就是对显示ListView做了许多优化,方面显示而已。

  • 使用步骤

    1. 在布局文件中加载ListView控件,并设置一系列属性

    2. 在布局文件夹中创建item组件,即用于每项布局输出的xml文件

    3. 数据结构(容器),即用于持有单个Item的数据,可以是简单的String,也可以通过抽象Items所需字段组成一个类,抽象的原则是与Item中的组件对应

    4. 确定是使用何种适配器。决定每行Item中具体显示什么内容,以怎样的样式显示等。

    5. 定义数据源,并对数据源进行初始化

    6. 将适配器设置给ListView

  • SimpleAdapter的使用

    SimpleAdapter(Context context, List<? extends Map<String,>>data,int resource,String[ ] from, int[ ] to)
    1. 第一个参数:上下文,这个不用多说,写this即可。

    2. 第二个参数:该参数应该是一个 List< Map> 类型的集合对象,该集合中每个Map<String>对象生成一个列表项。

    3. 第三个参数:该参数指定一个界面布局的ID,这里使用的自己创建的xml布局文件。

    4. 第四个参数:该参数是一个String[]类型的参数,该参数决定提取Map对象中哪些key对应的value来生成列表项,所以填写map.put(key,Value)对应的key即可。

    5. 第五个参数:该参数是一个int[]类型的参数,该参数决定填充哪些组件,填写自定义的xml布局文件中控件的ID即可,相当于把第四个参数指定的数据填充到第五个控件指定的控件中,与第四个参数形成对应关系*/

  • 代码实现

    • activity_main2.xml

      在布局文件中定义一个ListView

    <?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="wrap_content"
        android:orientation="horizontal">
        <ListView
            android:id="@+id/mylist"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:divider="#000"
            android:dividerHeight="2dp"
            android:listSelector="#600" />
    ​
    </LinearLayout>
    • item.xml

      在布局文件夹新建Item文件

    <?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="wrap_content"
        android:orientation="horizontal">
        <!-- 定义一个TextView -->
        <TextView
            android:id="@+id/text"
            android:layout_width="300dp"
            android:layout_height="wrap_content"
            android:padding="25dp"
            android:textSize="20sp"
            android:textColor="#000" />
        <!-- 定义一个ImageView -->
        <ImageView
            android:id="@+id/image"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:padding="10dp" />
    ​
    </LinearLayout>
    • MainActivity2.java

    package com.hopu.demo;
    import androidx.appcompat.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.ListView;
    import android.widget.SimpleAdapter;
    import android.widget.Toast;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    ​
    public class MainActivity extends AppCompatActivity {
        private String[] names = new String[]{"Lion", "Tiger", "Monkey", "Dog", "Cat", "Elephant"};
        private int[] imagesIds = new int[]{R.drawable.lion, R.drawable.tiger, R.drawable.monkey, R.drawable.dog, R.drawable.cat, R.drawable.elephant};
    ​
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            //创建一个List集合,List集合的元素是Map
            List<Map<String, Object>> listitems = new ArrayList<Map<String, Object>>();
            for (int i = 0; i < names.length; i++) {
                Map<String, Object> listitem = new HashMap<String, Object>();
                //键值对
                listitem.put("textview", names[i]);
                listitem.put("imageview", imagesIds[i]);
                listitems.add(listitem);
            }
            //创建一个SimpleAdapter
            SimpleAdapter simpleAdapter = new SimpleAdapter(this, listitems, R.layout.item, new String[]{"textview", "imageview"}, new int[]{R.id.text, R.id.image});
            ListView list = findViewById(R.id.mylist);
            // 为ListView设置Adapter
            list.setAdapter(simpleAdapter);
            // 为ListView的单击事件绑定事件监听器
            list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    // 创建一个Toast提示信息
                    Toast toast = Toast.makeText(MainActivity.this, names[position], Toast.LENGTH_SHORT); // 设置该Toast提示信息的持续时间
                    toast.show();
                }
            });
        }
    }

  • 实现效果

5.5 ListView的监听函数

OnItemClickListener – 可以处理视图中单个条目的点击事件

parent: 指定哪个AdapterView(可能会有多个ListView,区分多个ListView)

view: 为你点击的Listview的某一项的内容,来源于adapter。如用((TextView)view).getText().toString(),可以取出点击的这一项的内容,转为string 类型。

position: 指的是adapter的某一项的位置,如点击了listview第2项,而第2项对应 的是adapter的第2个数值,那此时position的值就为1了。注:这些数值都是从0开 始的。

id:id的值为点击了Listview的哪一项对应的数值,点击了listview第2项,那id就等于1。一般和position相同。

//注册ListView条目点击监听器对象
        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            /**
             * 当ListView 条目被点击时自动执行的方法
             * @param parent 事件源,当前就是ListView控件对象
             * @param view  用户点击条目对应的TextView控件对象
             * @param position  用户点击条目控件对应的索引值,索引从0开始
             * @param id    行号,一般和position相等
             *  需求:得到用户点击条目对应的内容
             */
 
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                //方式一:通过数据源中的索引值和ListView 控件中条目的索引值一一对应的关系获取数据
                //String item = data.get(position);
 
                //方式二:通过调用适配器对象的getItem(position)获取数据
                //String item = adapter.getItem(position);
 
                //方式三:通过调用适配器控件对象的getItemAtPosition(position)方法获取数据
                //String item = parent.getItemAtPosition(position).toString();
 
                //方式四:通过用户点击条目对应的控件对象获取数据
                String item = ((TextView)view).getText().toString();
 
                Toast.makeText(MainActivity.this,"item="+item,Toast.LENGTH_LONG).show();
                System.out.println("===OnItemClick(AdapterView<?> parent="+parent+",View view="+view+",int position="+position+",long id ="+id+")====");
 
            }
         });
        //注册长按ListView_names.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener(){
        /**
         * 当用户长按ListView 控件对象条目时自动调用的方法
         * @param parent 事件源,当前就是ListView控件对象
         * @param view 用户点击条目对应的TextView控件对象
         * @param postion 用户点击条目控件对应的索引值,索引从0开始
         * @parm id 行号,一般和postion相等
         * @return 如果事件被消费则返回true,相反则返回false
         */
 
       /* @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
            //删除用户点击条目对象
            data.remove(position);
            adapter.notifyDataSetChanged();//更新用户界面
            System.out.println("=====onItemLongClick(AdapterView<?> parent="+parent+", View view="+view+", int position="+position+", long id="+id+")=====");
            return  true;//事件是否被消费掉,如果消费掉则返回true,此时就不会在触发OnItemClick 方法了
            }
        });*/

6 GridView网格

6.1 GridView简介

在Android程序设计中GridView跟ListView都是比较常用的多控件布局,而GridView更是实现九宫图的首选! GridView的用法很多,主要凸显的是那种网格式布局,既有横向也有纵向的数据显示。

android:columnWidth:设置列的宽度
android:gravity:组件对其方式
android:horizontalSpacing:水平方向每个单元格的间距
android:verticalSpacing:垂直方向每个单元格的间距
android:numColumns:设置列数
android:stretchMode:设置拉伸模式,可选值如下: none:不拉伸;spacingWidth:拉伸元素间的间隔空隙 columnWidth:仅仅拉伸表格元素自身 spacingWidthUniform:既拉元素间距又拉伸他们之间的间隔空隙

6.2 GridView + ArrayAdapter

6.3 GridView + SimpleAdapter

  • 使用步骤

    1. 在布局文件中加载GridView控件,并设置一系列属性

    2. 在布局文件夹中创建item组件,即用于每项布局输出的xml文件

    3. 数据结构(容器),即用于持有单个Item的数据,可以是简单的String,也可以通过抽象Items所需字段组成一个类,抽象的原则是与Item中的组件对应

    4. 确定是使用何种适配器。决定每行Item中具体显示什么内容,以怎样的样式显示等。

    5. 定义数据源,并对数据源进行初始化

    6. 将适配器设置给GridView

  • 代码实现

    • activity_main3.xml

      在布局文件中定义一个ListView

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity3">
    ​
        <GridView
            android:id="@+id/gv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:numColumns="3"/>
    </LinearLayout>
    • item2.xml

      在布局文件夹新建Item文件

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:orientation="vertical"
        android:layout_height="match_parent">
    ​
        <ImageView
            android:id="@+id/image"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:padding="10dp" />
    ​
        <TextView
            android:id="@+id/text"
            android:layout_width="80dp"
            android:gravity="center"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:textColor="#000" />
    </LinearLayout>
    • MainActivity3.java

    package com.hopu.demo;
    ​
    import androidx.appcompat.app.AppCompatActivity;
    ​
    import android.os.Bundle;
    import android.widget.GridView;
    import android.widget.ListView;
    import android.widget.SimpleAdapter;
    ​
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    ​
    public class MainActivity3 extends AppCompatActivity {
    ​
        private String[] names = new String[]{"Lion", "Tiger", "Monkey", "Dog", "Cat", "Elephant"};
        private int[] imagesIds = new int[]{R.drawable.lion, R.drawable.tiger, R.drawable.monkey, R.drawable.dog, R.drawable.cat, R.drawable.elephant};
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main3);
    ​
            //创建一个List集合,List集合的元素是Mapd
            List<Map<String, Object>> listitems = new ArrayList<Map<String, Object>>();
            for (int i = 0; i < names.length; i++) {
                Map<String, Object> listitem = new HashMap<String, Object>();
                //键值对
                listitem.put("textview", names[i]);
                listitem.put("imageview", imagesIds[i]);
                listitems.add(listitem);
            }
            //创建一个SimpleAdapter
            SimpleAdapter simpleAdapter = new SimpleAdapter(this, listitems, R.layout.item2, new String[]{"textview", "imageview"}, new int[]{R.id.text, R.id.image});
            GridView list = findViewById(R.id.gv);
            // 为ListView设置Adapter
            list.setAdapter(simpleAdapter);
        }
    }

  • 实现效果

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐