Android学习——UI高级组件一

Android学习——UI高级组件一

GridView(网格布局)

GridView是一个在二维可滚动的网格中展示内容的控件。网格中的内容通过使用adapter自动插入到布局中。

1.GridView常用属性与自定义适配器

GridView组件

  • 1.自定义适配器
  • (1)创建一个类,继承BaseAdapter类
  • (2)实现4个方法
  • getCount 获取要显示的选项总数
  • getItem 获取当前每一个选项
  • getItemId 选项ID
  • getView 该方法用来为每一个选项生成视图(ImageView),该方法会被多次调用
<GridView
        android:id="@+id/gridView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:numColumns="auto_fit"
        android:columnWidth="90dp"
        android:horizontalSpacing="20dp"
        android:verticalSpacing="20dp"
        android:stretchMode="columnWidth"
        android:gravity="center"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" />

在这里插入图片描述
Activity类中自定义适配器

//自定义适配器(静态内部类)
    static class MyAdapter extends BaseAdapter{
        private int[] images={R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher};
        private Context context;
        public MyAdapter(Context context){
            this.context=context;
        }
        @Override
        public int getCount() {
            return images.length;
        }

        @Override
        public Object getItem(int position) {
            return images[position];
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ImageView iv=new ImageView(context);
            iv.setImageResource(images[position]);
            return iv;
        }
    }

调用

 private GridView gridView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main4);
        gridView =findViewById(R.id.gridView);
        //设置适配器
        gridView.setAdapter(new MyAdapter(this));
    }

在这里插入图片描述
2.GridView图文排列
建立一个布局文件,已配置图文排列的样式。

<?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="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:gravity="center">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher"/>
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView"/>
</LinearLayout>

在这里插入图片描述
Activity类中配置适配器

 private  GridView gridView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main5);
        gridView=findViewById(R.id.gridView2);
        gridView.setAdapter(new MyAdapter(this));
        //点击事件
        gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                //System.out.println("parent="+parent);//GridView的对象
                //System.out.println("view="+view);//每一个选项的布局
                //System.out.println("position="+position);//所在的位置
                //System.out.println("id="+id);//所在的编号值id
                TextView tv = view.findViewById(R.id.textView);
                Toast.makeText(Main5Activity.this,tv.getText(),Toast.LENGTH_SHORT).show();
            }
        });
    }
    //静态内部类
    static class MyAdapter extends BaseAdapter{
        private String[] names={"转账","查询","金融","基金","国债","信用卡","商场","充值","红包"};
        private int[] images={R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher,
                R.mipmap.ic_launcher};
        private Context context;
        public MyAdapter(Context context){
            this.context=context;
        }
        @Override
        public int getCount() {
            return names.length;
        }

        @Override
        public Object getItem(int position) {
            return names[position];
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            //实例化布局
            LayoutInflater inflater = LayoutInflater.from(context);
            View view = inflater.inflate(R.layout.item_layout,null);
            ImageView iv=view.findViewById(R.id.imageView);
            TextView tv=view.findViewById(R.id.textView);
            iv.setImageResource(images[position]);
            tv.setText(names[position]);
            return view;
        }
    }

在这里插入图片描述
在这里插入图片描述

  • android:columnWidth
    相关方法setColumnWidth(int)。定义每一列的固定宽度。
    必须是dimension值(浮点数后面拼接单位,例如“14.5sp”)。有效的单位有:px,dp,sp,in,mm。
    它也可以是一个资源的引用(@[package:]type:name)或主题属性(?[package:][type:]name)。
  • android:gravity
    相关方法setGravity(int)。定义每一个单元格的重心。
    必须是一个或多个(使用“|”分隔)下面的常量
  • android:horizontalSpacing
    相关方法setHorizontalSpacing(int)。定义了两列之间的水平间隔。
    属性设置要求同android:columnWidth
  • android:numColumns
    相关方法setNumColumns(int)。定义了展示的列数。
    可以是一个整形值,如“100”。也可以是一个资源的引用(@[package:]type:name)或主题属性(?[package:][type:]name)。
  • android:stretchMode
    相关方法setStretchMode(int)。定义了列拓展填充有限闲置空间的方式。
  • android:verticalSpacing
    相关方法setVerticalSpacing(int)。定义两行之间的垂直间隔。
    属性设置要求同android:columnWidth

ListView(列表布局)

1.ListView基本属性配置、ListActivity

  • android:dividerHeight=“30dp”//设置listview view之间的高度
  • android:divider="@color/colorAccent"//listview view之间的背景或颜色
  • android:fadingEdge=“vertical”//上下边有黑色阴影,none的话就没有阴影
  • android:cacheColorHint="#000000"//设置拖动背景色为透明
  • android:drawSelectorOnTop=“true”//点击某条记录不放时,颜色会记录在后面成为背景色
  • android:scrollbars=“horizontal”//只有值为horizontal|vertical时,才会显示滚动条
  • android:fastScrollEnabled=“true”//滚动时会有小方块提示
  • android:listSelector="@color/design_default_color_primary"//listview选中时的颜色
  • android:entries="@array/name"//设置列表填充内容
<ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:id="@+id/listView"
        android:dividerHeight="30dp"
        android:divider="@color/colorAccent"
        android:fadingEdge="vertical"
        android:fastScrollEnabled="true"
        android:listSelector="@color/design_default_color_primary"
        android:entries="@array/name"/>

Activity中事件设置

 private ListView listView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main5);
        listView=findViewById(R.id.listView);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                TextView tv= (TextView) view;
                Toast.makeText(Main5Activity.this, tv.getText(), Toast.LENGTH_SHORT).show();
            }
        });
    }

选中状态
在这里插入图片描述
ListActivity:
不另外配置布局文件,直接在activity文件中进行设置,而且需要修改继承类为ListActivity

public class Main5Activity extends ListActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ArrayAdapter<CharSequence> arrayAdapter=ArrayAdapter.createFromResource(
                this,R.array.name,android.R.layout.simple_expandable_list_item_1);
        setListAdapter(arrayAdapter);
    }
    //单击事件
     @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        Toast.makeText(this, ((TextView)v).getText(), Toast.LENGTH_SHORT).show();
    }

在这里插入图片描述
2.ListView-单选多选

单选列表

public class Main5Activity extends AppCompatActivity {
    private ListView listView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main5);
        listView=(ListView) findViewById(R.id.listView2);

        //设置值
        String[] arr=getResources().getStringArray(R.array.name);
        //单选模式
        ArrayAdapter<String> aa=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_single_choice,arr);
        listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        listView.setAdapter(aa);
        
        listView=findViewById(R.id.listView2);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                TextView tv= (TextView) view;
                Toast.makeText(Main5Activity.this, tv.getText(), Toast.LENGTH_SHORT).show();
            }
        });
  }

在这里插入图片描述
多选列表

//多选模式
        ArrayAdapter<String> aa2=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_multiple_choice,arr);
        listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        listView.setAdapter(aa2);

在这里插入图片描述
3.ListView-SimpleAdapter(实现图文列表)

单独定义一个布局文件

<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="wrap_content"
    android:gravity="center_vertical"
    android:padding="16dp">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher"/>

    <TextView
        android:id="@+id/textView_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:text="TextView" />
</LinearLayout>

布局样式
在这里插入图片描述
改变图文内容

private ListView listView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main5);

        listView=findViewById(R.id.listView3);
        //准备数据,每一个HashMap作为是一条记录
       HashMap<String,Object> title1=new HashMap<>();
        title1.put("title","title-1");
        title1.put("icon",android.R.drawable.alert_dark_frame);
        HashMap<String,Object> title2=new HashMap<>();
        title2.put("title","title-2");
        title2.put("icon",android.R.drawable.alert_light_frame);
        HashMap<String,Object> title3=new HashMap<>();
        title3.put("title","title-3");
        title3.put("icon",android.R.drawable.arrow_down_float);
        //将记录放入list当中
        ArrayList<Map<String,String>> list=new ArrayList<>();
        list.add(title1);
        list.add(title2);
        list.add(title3);
        //把数据填充到Adapter中(上下文,数据,布局文件,传入上面定义键名称传入对应的值,指定传入的控件id)
       SimpleAdapter sa=new SimpleAdapter(this,list,R.layout.list_item,new String[]{"title","icon"},new int[]{R.id.textView_title,R.id.imageView});
        listView.setAdapter(sa);
  }

在这里插入图片描述
4.ListView-自定义适配器(BaseAdapter)
BaseAdapter 自己进行控制,更加灵活
建立一个listview

<ListView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:id="@+id/listView4"/>

新建布局文件

<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="wrap_content"
    android:gravity="center_vertical"
    android:padding="16dp">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher"/>

    <TextView
        android:id="@+id/textView_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:text="TextView" />
</LinearLayout>

Activity中设置BaseAdapter

 private ListView listView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main5);

        listView=findViewById(R.id.listView4);
        listView.setAdapter(new MyAdapter(this));

    }

    static class MyAdapter extends BaseAdapter{
    //文字列表
        private String[] titles={"title-1","title-2","title-3","title-4","title-5"};
    //图片列表
        private int[] icons={android.R.drawable.ic_dialog_email,
                android.R.drawable.ic_delete,
                android.R.drawable.ic_input_add,
                android.R.drawable.ic_dialog_info,
                android.R.drawable.ic_dialog_map};
        //构造方法
        private Context context;
        public MyAdapter(Context context){
            this.context=context;
        }
        @Override
        public int getCount() {
            return titles.length;
        }

        @Override
        public Object getItem(int position) {
            return titles[position];
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            LayoutInflater inflater=LayoutInflater.from(context);
            View view = inflater.inflate(R.layout.list_item,null);
            TextView tv_title=view.findViewById(R.id.textView_title);
            ImageView iv_icon=view.findViewById(R.id.imageView);
            tv_title.setText(titles[position]);
            iv_icon.setImageResource(icons[position]);
            return view;
        }
    }
 }

在这里插入图片描述
5.优化ListVew(避免浪费内存)

  • ListView的宽高要相对固定
    避免内容变化到时ListView 重新渲染
  • 重复使用convertView:
    convertView为空闲可用的对象,是一个作为缓存的view,通过使用这个缓存可以替换掉用Inflater加载组件这一步,也是通过重复利用这个对象,以避免重复创建对象,减少内存的消耗。
    具体使用代码如下:
 @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            //党convertView为空时,才实例化view
            if (convertView==null){
                LayoutInflater inflater=LayoutInflater.from(context);
                //实例化一个布局文件
                convertView = inflater.inflate(R.layout.list_item,null);
            }

            TextView tv_title=convertView.findViewById(R.id.textView_title);
            ImageView iv_icon=convertView.findViewById(R.id.imageView);

            tv_title.setText(titles[position]);
            iv_icon.setImageResource(icons[position]);

            return convertView;
        }
  • 使用ViewHolder提高在容器中查找组件的效率:
    convertView和ViewHolder一起用;ViewHolder中持有的组件和converView中的组件指向同一个对象,所以这里使用ViewHolder就是替换掉findViewById,减少对象的查找
@Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder vh = null;
            //当convertView为空时,才实例化view
            if (convertView==null){
                LayoutInflater inflater=LayoutInflater.from(context);
                //实例化一个布局文件
                convertView = inflater.inflate(R.layout.list_item,null);
                vh=new ViewHolder();
                vh.iv_icon=convertView.findViewById(R.id.imageView);
                vh.tv_title=convertView.findViewById(R.id.textView_title);
                convertView.setTag(vh);
            }else{
                vh= (ViewHolder) convertView.getTag();
            }
            vh.tv_title.setText(titles[position]);
            vh.iv_icon.setImageResource(icons[position]);

            return convertView;
        }
        //内部类,用于保存第一次查找的组件,避免下一次重复查找
        static class ViewHolder{
            ImageView iv_icon;
            TextView tv_title;
        }

6.ListView分页
新建一个News类

public class News {
    String title;
    String content;
}

设置加载状态的布局文件
loadin.xml

<ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:text="正在玩命加载中。。。" />

设置ListView

<ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:id="@+id/listView5"/>

在Activity类中

/*
* 分页
* */
public class Main6Activity extends AppCompatActivity implements AbsListView.OnScrollListener {
    private ListView listView;
    private Vector<News> news=new Vector<>();//容器,装对象
    private MyAdapter myAdapter;
    private static final int DATA_UPDATE=0x1;//数据更新完成后的标记
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main6);
        listView=findViewById(R.id.listView5);
        //注册滚动条事件
        listView.setOnScrollListener(this);
        View footerView=getLayoutInflater().inflate(R.layout.loading,null);
        listView.addFooterView(footerView);
        initDate();
        myAdapter = new MyAdapter();
        listView.setAdapter(myAdapter);
    }

    private int index=1;
    /*
     * 初始化数据
     * */
    private void initDate(){
        for (int i=0;i<10;i++){
            News n=new News();
            n.title="title--"+index;
            n.content="content--"+index;
            index++;
            news.add(n);
        }
    }

    private int visibleLastIndex;//用来可显示的最后一条数据的索引值
    @Override//滚动状态改变的方法
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        //滚动事件,停止状态
        if (myAdapter.getCount()==visibleLastIndex&&scrollState== AbsListView.OnScrollListener.SCROLL_STATE_IDLE){
            new LoadDateThread().start();
        }
    }

    @Override//滚动的方法
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        visibleLastIndex=firstVisibleItem+visibleItemCount-1;
    }

    //线程之间进行通讯的机制 Hander(处理器) 处理消息用
    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case DATA_UPDATE:
                    myAdapter.notifyDataSetChanged();
                    break;
            }
        }
    };

    //模拟加载数据的线程
    class LoadDateThread extends Thread{
        @Override
        public void run() {
            initDate();
            try {
                Thread.sleep(2000);//休眠两秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //通过Handler给主线程发送一个消息标记
            handler.sendEmptyMessage(DATA_UPDATE);
        }
    }

    //自定义适配器填充数据
    class MyAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            return news.size();
        }

        @Override
        public Object getItem(int position) {
            return news.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder vh;
            if (convertView==null){
                convertView=getLayoutInflater().inflate(R.layout.list_item,null);
                vh=new ViewHolder();
                vh.tv_title=convertView.findViewById(R.id.textView_title);
                vh.tv_content=convertView.findViewById(R.id.textView_content);
                convertView.setTag(vh);
            }else{
                vh= (ViewHolder) convertView.getTag();
            }
            News n=news.get(position);
            vh.tv_title.setText(n.title);
            vh.tv_content.setText(n.content);
            return convertView;
        }
        class ViewHolder{
            TextView tv_title;
            TextView tv_content;
        }
    }
}

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/UUUUUltraman/article/details/88661872