zoukankan      html  css  js  c++  java
  • android ——ListView

    谷歌官方文档的介绍:https://developer.android.com/reference/android/widget/ListView.html

    显示可垂直滚动的视图集合,其中每个视图都立即位于列表中的上一个视图的下方。 为了更现代化,更灵活和更有效地显示列表,请使用RecyclerView。。。

    现在活动布局中加入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="match_parent"
        android:orientation="vertical">
    
    
       <ListView
           android:id="@+id/list_view"
           android:layout_width="match_parent"
           android:layout_height="match_parent"/>
    
    </LinearLayout>

    这里做一个定制的列表,就是自己定制列表中的布局。新建一个hero_item.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="horizontal">
    
        <ImageView
            android:id="@+id/hero_img"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    
        <TextView
            android:id="@+id/hero_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:textSize="20sp"/>
    
    </LinearLayout>

    再然后是这次想要使用的数据,http://ow.blizzard.cn/heroes/,数据来自暴雪的守望先锋官网的英雄介绍页面

    旁边的html代码中<img src="..." class="portrait">是英雄头像的url,</span><span class="portrait-title">末日铁拳</span></span>是英雄的名字。

    所以新建一个H

    public class Hero {
    
        private String imageUrl;
    
        private String name;
    
        public Hero(String imageUrl, String name) {
            this.imageUrl = imageUrl;
            this.name = name;
        }
    
        public String getUrl() {
            return imageUrl;
        }
    
        public void setUrl(String url) {
            this.imageUrl = url;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }

    然后就是ListView的Adapter,新建一个HeroAdapter.class,这个Adapter继承自ArrayAdapter,并将泛型指定为Hero

    public class HeroAdapter extends ArrayAdapter<Hero> {
    
        private int resourceId;
    
        public HeroAdapter(Context context, int textViewResourceId, List<Hero> objects){
            super(context,textViewResourceId,objects);
            resourceId = textViewResourceId;
        }
    
        @NonNull
        @Override
        public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
            Hero hero = getItem(position);
            View view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
            ImageView heroImg = (ImageView) view.findViewById(R.id.hero_img);
            TextView heroName = (TextView) view.findViewById(R.id.hero_name);
            Glide.with(getContext()).load(hero.getUrl()).into(heroImg);
            heroName.setText(hero.getName());
            return view;
        }
    }

    HeroAdapter重写了父类的构造函数,可以获得上下文,ListView的子布局的id和数据,然后重写getView()方法,这个方法会在每个子项被滚动到屏幕时调用,在getItem()中根据position获得当前的Hero实例,然后使用LayoutInflater来为这个子项加载布局,再然后设置布局中的ImageView 和TextView,最后返回布局。

    最后活动中的代码

    public class MainActivity extends AppCompatActivity {
    
        private List<Hero> heroList = new ArrayList<>();
        private Handler handler;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            final ListView listView = (ListView) findViewById(R.id.list_view);
            initHeroes();
            handler = new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    if(msg.what == 1){
                        HeroAdapter adapter = new HeroAdapter(MainActivity.this, R.layout.hero_item, heroList);
                        listView.setAdapter(adapter);
                    }
                }
            };
        }
    
        //读取数据
        private void initHeroes(){
            String weatherUrl = "http://ow.blizzard.cn/heroes/";
            HttpUtil.sendOkHttpRequest(weatherUrl, new Callback() {
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    final String responseText = response.body().string();
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            Document doc = Jsoup.parse(responseText);//将String类型的html转换为Document
                            Elements elements1 = doc.select(".portrait"); //读取图片url
                            Elements elements2 = doc.select(".portrait-title");//读取英雄名字
                            for (int j = 0; j < elements1.size(); j++) {
                                Hero hero = new Hero(elements1.get(j).attr("src"), elements2.get(j).text());
                                heroList.add(hero);
                            }
                            Message msg = new Message();
                            msg.what = 1;
                            handler.sendMessage(msg);
                        }
                    }).start();
                }
    
                @Override
                public void onFailure(Call call, IOException e) {
                    e.printStackTrace();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(MainActivity.this, "数据获取失败", Toast.LENGTH_SHORT).show();
                        }
                    });
                }
            });
        }
    }

    创建一个HeroAdapter,传入上下文,子布局和数据,再将这个适配器传递给ListView就好了

     代码优化:

       public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
            Hero hero = getItem(position);
            View view;
            ViewHolder viewholder;
            //检验之前是否已经加载好布局
            if(convertView != null) {
                view = convertView;
                viewholder = (ViewHolder) view.getTag();
            }else {
                view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false);
                viewholder = new ViewHolder();
                viewholder.heroImg = (ImageView) view.findViewById(R.id.hero_img);
                viewholder.heroName = (TextView) view.findViewById(R.id.hero_name);
                view.setTag(viewholder);
            }
            Glide.with(getContext()).load(hero.getUrl()).into(viewholder.heroImg);
            viewholder.heroName.setText(hero.getName());
            return view;
        }
    
        class  ViewHolder{
            ImageView heroImg;
            TextView heroName;
        }
    }

    根据如果之前加载过的布局就重用之前的,不再使用LayoutInflater去加载布局,然后还把之前获取的布局控件的id也保存了下来。这样做的话。。像这次这样简单的布局和数据就有点加载得快过头了。。。

    ListView的点击事件

        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            final ListView listView = (ListView) findViewById(R.id.list_view);
            ....
            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                    Hero hero = heroList.get(i);
                    Toast.makeText(MainActivity.this,hero.getName(),Toast.LENGTH_SHORT).show();
                }
            });
        }
  • 相关阅读:
    构建之法阅读笔记03
    构建之法阅读笔记02
    构建之法读书笔记01
    梦断代码读书笔记03
    背包九讲问题
    C-01背包问题
    C-最长回文子串(2)
    C-最长回文子串(1)
    C语言顺序栈实现
    带头结点头部插入创建链表
  • 原文地址:https://www.cnblogs.com/xxbbtt/p/7526540.html
Copyright © 2011-2022 走看看