zoukankan      html  css  js  c++  java
  • Android 手风琴效果实现

    ExpandableListView 基础知识  
    1. ExpandableListView 的总体概述  
      ExpandableListView 是 android 中可以实现下拉 list 的一个控件,是一个垂直滚动的心事两个级  
    别列表项手风琴试图,列表项是来自 ExpandableListViewaAdapter,组可以单独展开。  
    2.重要的方法:  
      expandGroup (int groupPos) ;//在分组列表视图中 展开一组,  
      setSelectedGroup (int groupPosition) ;//设置选择指定的组。  
      setSelectedChild (int groupPosition, int childPosition, boolean shouldExpandGroup);  
      getPackedPositionGroup (long packedPosition);//返回所选择的组  
      isGroupExpanded (int groupPosition);//判断此组是否展开  
      expandableListView.setDivider();这个是设定每个 Group 之间的分割线。  
      expandableListView.setGroupIndicator();这个是设定每个 Group 之前的那个图标。  
      expandableListView.collapseGroup(int group); 将第 group 组收起  
    3. 适配器的介绍  
      ExpandableListAdapter,一个接口,将基础数据链接到一个 ExpandableListView。 此接  
    口的实施将提供访问 Child 的数由组分类实例化的 Child 和 Group配器中常用的重  
    要方法:  
      getChildId (int groupPosition, int childPosition) 获取与在给定组给予孩子相关的数据。  
      getChildrenCount (int groupPosition) 返回在指定 Group 的 Child 数目  
    4. 属性和事件  
    1) 在 Android 中对子条目的点击事件是通过 onChildClick()来实现  
     
    2) 对组的点击事件是通过 onGroupClick()来实现的  
     Gson 框架:
    它是谷歌推出的一个请求网络数据的一个框架,常用的用法如下:  
      1) GSON 的两个重要方法  
    在 GSON 的 API 中,提供了两个重要的方法:toJson()和 fromJson()方法。其中,toJson()方法  
    用来实现将 Java 对象转换为相应的 JSON 数据,fromJson()方法则用来实现将 JSON 数据转换为  
    相应的 Java 对象。  
      2) toJson()方法,toJson()方法用于将 Java 对象转换为相应的 JSON 数据,主要有以下几种形式:  
      String toJson(JsonElement jsonElement);  
      String toJson(Object src);  
      String toJson(Object src, Type typeOfSrc);  
    其中,方法(1.1)用于将 JsonElement 对象(可以是 JsonObjectJsonArray 等)转换成 JSON  
    数据;方法(1.2)用于将指定的 Object 对象序列化成相应的 JSON 数据;方法(3)用于将指定  
    的 Object 对象(可以包括泛型类型)序列化成相应的 JSON 数据。  
    3) 1.2 fromJson()方法  
    fromJson()方法用于将 JSON 数据转换为相应的 Java 对象,主要有以下几种形式:  
    1<T> T fromJson(JsonElement json, Class<T> classOfT);  
    2<T> T fromJson(JsonElement json, Type typeOfT);  
    3<T> T fromJson(JsonReader reader, Type typeOfT);  
    5<T> T fromJson(Reader reader, Type typeOfT);  
    6<T> T fromJson(String json, Class<T> classOfT);  
    7<T> T fromJson(String json, Type typeOfT);  
    以上的方法用于将不同形式的 JSON 数据解析成 Java 对象。  
     
    所以说 gson 是一个很好的请求网络数据的框架,既可以在服务器端生成一个 json 字符串,然后  
    客户端通过发送请求向服务器端,进行数据解析。  
    5. Picasso 框架  
      这也是本课程中涉及的一个第三方的框架,它主要是用于网络请求图片时的一种框架,它的  
    代码量少,自带缓存,是一个值得使用的框架。首先 Picasso 也是 Afinal 这个框架的一种,  
    Afinal 是一个 android 的 iocorm 框架,内置了四大模块功能:  
    FinalAcitivity,FinalBitmap,FinalDb,FinalHttp。通过 finalActivity,我们可以通过注解的方式进  
    行绑定 ui 和事件。通过 finalBitmap,我们可以方便的加载 bitmap 图片,而无需考虑 oom 等  
    问题。通过 finalDB 模块,我们一行代码就可以对 android 的 sqlite 数据库进行增删改查。通过  
    FinalHttp 模块,我们可以以 ajax 形式请求 http 数据。  

    ExpandableListView 和 ExpandableListActivity

    如何获取 ExpandableListView对象
    1.可以直接在xml布局中添加 ExpandableListView 在activity中通过id绑定控件
    2.activity 继承 ExpandableListActivity 通过 getExpandableListView 方法获取

    ExpandableListView的常用属性
    android:groupIndicator="" 设置可扩展组图标提示

    点击事件
      //设置组点击事件
            //
            melv.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
                @Override
                public boolean onGroupClick(ExpandableListView expandableListView, View view, int i, long l) {
                    return false;
                }
            });
            //设置字条目点击事件
            melv.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
                @Override
                public boolean onChildClick(ExpandableListView expandableListView, View view, int i, int i1, long l) {
                    return false;
                }
            });

     下面进入demo环节

    1.实现手风琴效果  获取本地数据

     效果展示

    (1).设置xml布局

    <?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=".MainActivity">
    <ExpandableListView
        android:id="@+id/elv_local"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:groupIndicator="@null"
        android:divider="@null"
        android:dividerHeight="10dp"
        >
    
    </ExpandableListView>
    
    </LinearLayout>

    (2).获取本地数据

    //获取列表组的数据
        public static List<String> getGroupData(){
            List<String> groupList = new ArrayList<>();
            groupList.add("Android课程");
            groupList.add("JAVA课程");
            return groupList;
        }
    
    
        //获取字条目的数据
        public static List<List<String>> getChildData(){
            List<List<String>> childList = new ArrayList<>();
            List<String> item1 = new ArrayList<>();
            item1.add("activity生命周期");
            item1.add("Android 属性动画");
            childList.add(item1);
            List<String> item2 = new ArrayList<>();
            item2.add("JAVA集合");
            item2.add("JAVA 多态");
            childList.add(item2);
            return  childList;
        }

    (3)配置适配器

    package com.example.squeezebox.Adapter;
    
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseExpandableListAdapter;
    
    import java.util.List;
    
    /**
     * 适配器封装
     */
    public abstract class MyAdapter extends BaseExpandableListAdapter {
        Context context;
        LayoutInflater minflater;
        public MyAdapter(Context context) {
            this.context = context;
            minflater = LayoutInflater.from(context);
        }
        List<String> group;
        List<List<String>> child;
        public void addNewData(List<String> group,List<List<String>> child){
            this.group = group;
            this.child = child;
        }
        //获取组的数量
        @Override
        public int getGroupCount() {
            return group.size();
        }
        //获取字条目的数量
        @Override
        public int getChildrenCount(int i) {
            return child.get(i).size();
        }
        //获取组的具体的内容
        @Override
        public String getGroup(int i) {
            return group.get(i);
        }
        //获取字条目具体的内容
        @Override
        public String getChild(int i, int i1) {
            return child.get(i).get(i1);
        }
        //获取组的id
        @Override
        public long getGroupId(int i) {
            return i;
        }
        //获取字条目的id
        @Override
        public long getChildId(int i, int i1) {
            return i1;
        }
    
        @Override
        public boolean hasStableIds() {
            return false;
        }
    
        //可扩展的字条目是否可以被点击
        @Override
        public boolean isChildSelectable(int i, int i1) {
            return true;
        }
    
        //获取组的视图
        @Override
        public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup) {
            return MyGroupView(i,view);
        }
    
        //获取字条目的视图
        @Override
        public View getChildView(int i, int i1, boolean b, View view, ViewGroup viewGroup) {
            return MyGroupView(i,i1,view);
        }
        public abstract View MyGroupView(int i, View groupView);
        public abstract View MyGroupView(int i, int i1,View childView);
    
    }
    package com.example.squeezebox.Adapter;
    
    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.view.View;
    import android.widget.TextView;
    
    import com.example.squeezebox.R;
    
    /**
     * 本地数据适配器
     */
    public class LocalAdapter extends MyAdapter {
    
        public LocalAdapter(Context context) {
            super(context);
        }
    
        @Override
        public View MyGroupView(int i, View groupView) {
            View view = minflater.inflate(R.layout.group_layout,null);
            TextView textView = view.findViewById(R.id.group_txt);
            textView.setText(getGroup(i));
    
            textView.setPadding(30,0,0,0);
            return view;
        }
    
    
        @Override
        public View MyGroupView(int i, int i1, View childView) {
            View view = minflater.inflate(R.layout.item_layout,null);
            TextView textView = view.findViewById(R.id.item_txt);
            textView.setTextColor(context.getResources().getColor(R.color.steelblue));
            textView.setText(getChild(i,i1));
    //        textView.setPadding(30,0,0,0);
            return view;
        }
    }

    (4)在UI线程中调用

        public void loadLocal(){
            LocalAdapter adapter = new LocalAdapter(this);
            adapter.addNewData(LocalData.getGroupData(),LocalData.getChildData());
            melv.setAdapter(adapter);
        }

    2.获取数据库数据  使用 CursorTreeAdapter 类

    (1) 创建数据库并建表 以及 添加 查询方法

    public class DBOpenHelper extends SQLiteOpenHelper {
        public DBOpenHelper(Context context) {
            super(context, "hejun.db", null, 1);
        }
    
        public DBOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
            super(context, "hejun.db", null, 1);
        }
    
        @Override
        public void onCreate(SQLiteDatabase sqLiteDatabase) {
            sqLiteDatabase.execSQL("create table group1(_id integer primary key autoIncrement," +
                    "kind text,type text )");
            sqLiteDatabase.execSQL("create table child(_id integer primary key autoIncrement," +
                    "kind text,name text,type text )");
    
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
    
        }
    }
    package com.example.squeezebox.DBOpenHelper;
    
    import android.content.ContentValues;
    import android.content.Context;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    
    public class DBHelp {
    
        private DBOpenHelper dbOpenHelper;
    
        public DBHelp(Context context) {
            dbOpenHelper = new DBOpenHelper(context);
        }
    
        //向组视图添加数据
        public void insertGroup(String kind, String type) {
            SQLiteDatabase sqLiteDatabase = dbOpenHelper.getWritableDatabase();
            ContentValues values = new ContentValues();
            values.put("kind",kind);
            values.put("type",type);
            sqLiteDatabase.insert("group1", null, values);
        }
    
        //查询组数据
        public Cursor selectGroup() {
            SQLiteDatabase sqLiteDatabase = dbOpenHelper.getReadableDatabase();
            return sqLiteDatabase.query("group1", null, null,null , null, null, null);
    
        }
        //向字条目添加数据
        public void insertChild(String kind, String leaner,String type) {
            SQLiteDatabase sqLiteDatabase = dbOpenHelper.getWritableDatabase();
            ContentValues values = new ContentValues();
            values.put("kind", kind);
            values.put("name", leaner);
            values.put("type",type);
            sqLiteDatabase.insert("child", null, values);
        }
    
        //查询组数据
        public Cursor selectChild(String type) {
            SQLiteDatabase sqLiteDatabase = dbOpenHelper.getReadableDatabase();
            return sqLiteDatabase.query("child", null, "type=?", new String[]{type}, null, null, null);
    
        }
    }

    (2)设置适配器

    package com.example.squeezebox.Adapter;
    
    import android.content.Context;
    import android.database.Cursor;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.CursorTreeAdapter;
    import android.widget.TextView;
    
    import com.example.squeezebox.DBOpenHelper.DBHelp;
    import com.example.squeezebox.R;
    
    /**
     * 数据库适配器
     * cursor  group and child
     */
    public class DBAdapter extends CursorTreeAdapter {
        /**
         *
         * @param cursor 组的游标
         * @param context
         */
        DBHelp dbHelp;
        public DBAdapter(Cursor cursor, Context context) {
            super(cursor, context);
            dbHelp = new DBHelp(context);
        }
    
        //获取字条目的游标
        @Override
        protected Cursor getChildrenCursor(Cursor cursor) {
            return dbHelp.selectChild(cursor.getString(cursor.getColumnIndex("type")));
        }
        //创建组的视图
        @Override
        protected View newGroupView(Context context, Cursor cursor, boolean b, ViewGroup viewGroup) {
            View view = LayoutInflater.from(context).inflate(R.layout.group_layout,null);
            return view;
        }
        //绑定组的视图
        @Override
        protected void bindGroupView(View view, Context context, Cursor cursor, boolean b) {
            TextView textView = view.findViewById(R.id.group_txt);
            textView.setText(cursor.getString(cursor.getColumnIndex("kind")));
    
        }
        //创建字条目的视图
        @Override
        protected View newChildView(Context context, Cursor cursor, boolean b, ViewGroup viewGroup) {
            return LayoutInflater.from(context).inflate(R.layout.item2_layout,null);
        }
        //绑定字条目的视图
        @Override
        protected void bindChildView(View view, Context context, Cursor cursor, boolean b) {
            TextView textView1 = view.findViewById(R.id.item_txt2);
            TextView textView2 = view.findViewById(R.id.item_leaner);
            textView1.setText(cursor.getString(cursor.getColumnIndex("kind")));
            textView2.setText(cursor.getString(cursor.getColumnIndex("name")));
        }
    }

    (4) 在UI线程调用,插入数据 并为 ExpandableListView 添加Adapter

     public void loadDB(){
            DBHelp db = new DBHelp(this);
            db.insertGroup("Android课程","android");
            db.insertGroup("JAVA课程","java");
            db.insertChild("activity生命周期","1564156","android");
            db.insertChild("Android 属性动画","89798","android");
            db.insertChild("JAVA集合","98789","java");
            db.insertChild("JAVA 多态","7988","java");
    
            Cursor cursor = db.selectGroup();
            DBAdapter dbAdapter = new DBAdapter(cursor,this);
            melv.setAdapter(dbAdapter);
        }

    3.获取网络数据实现手风琴效果

    效果展示:

     (1) 异步下载网络数据,并使用接口回调,传出数据

    package com.example.squeezebox.util;
    
    import android.os.AsyncTask;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;
    
    public class HttpRequest {
    
        public static void request(String path,onResponseLister onResponseLister){
            new MyAsycnTask(onResponseLister).execute(path);
    
        }
    
        static class  MyAsycnTask extends AsyncTask<String,Void,String>{
            private onResponseLister onResponseLister;
            public MyAsycnTask(onResponseLister onResponseLister) {
                this.onResponseLister = onResponseLister;
            }
    
            @Override
            protected String doInBackground(String... strings) {
                try {
                    URL url = new URL(strings[0]);
                    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(5000);
                    if (connection.getResponseCode() == HttpURLConnection.HTTP_OK){
                        InputStream in = connection.getInputStream();
                        byte[] bytes = new byte[1024];
                        int len = 0;
                        StringBuilder builder = new StringBuilder();
                        while ((len = in.read(bytes))!= -1){
                            String str = new String(bytes,0,len);
                            builder.append(str);
                        }
                        return builder.toString();
                    }
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }
    
            @Override
            protected void onPostExecute(String s) {
                super.onPostExecute(s);
                if (s != null){
                    onResponseLister.onResponseListerSuccess(s);
                }else {
                    onResponseLister.onResponseListerSFail("网络请求错误");
                }
            }
        }
    
        public interface onResponseLister{
            void onResponseListerSuccess(String result);
            void onResponseListerSFail(String result);
        }
    }

    (2) 解析json数据 创建两个实体类

    public class BaseEntity<T> {
    
        public String msg;
        public int status;
        public T data;
    }
    public class Cuesor {
        public String name;
        public String picSmall;
        public String learner;
    }
    /**
     * 解析数据
     */
    public class Parser {
    
        public static BaseEntity<List<Cuesor>> parserData(String json){
            Gson gson = new Gson();
           return gson.fromJson(json,new TypeToken<BaseEntity<List<Cuesor>>>(){}.getType());
        }
    }

    (3)配置适配器

    package com.example.squeezebox.Adapter;
    
    import android.content.Context;
    import android.database.Cursor;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseExpandableListAdapter;
    
    import java.util.List;
    
    public abstract class MyBaseAdapter<T> extends BaseExpandableListAdapter {
        Context context;
        LayoutInflater layoutInflater;
        public MyBaseAdapter(Context context) {
            this.context = context;
            layoutInflater = LayoutInflater.from(context);
        }
        private List<String> group;
        private List<List<T>> child;
        public void addNewData(List<String> group, List<List<T>> child){
            this.group =group;
            this.child =child;
    
        }
    
        @Override
        public int getGroupCount() {
            return group.size();
        }
    
        @Override
        public int getChildrenCount(int i) {
            return child.get(i).size();
        }
    
        @Override
        public String getGroup(int i) {
            return group.get(i);
        }
    
        @Override
        public T getChild(int i, int i1) {
            return child.get(i).get(i1);
        }
    
        @Override
        public long getGroupId(int i) {
            return i;
        }
    
        @Override
        public long getChildId(int i, int i1) {
            return i1;
        }
    
        @Override
        public boolean hasStableIds() {
            return false;
        }
    
        @Override
        public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup) {
            return addGroupView(i,view);
        }
    
        @Override
        public View getChildView(int i, int i1, boolean b, View view, ViewGroup viewGroup) {
            return addChildView(i,i1,view);
        }
    
        @Override
        public boolean isChildSelectable(int i, int i1) {
            return true;
        }
    
        public abstract View addGroupView(int i ,View groupView);
        public abstract View addChildView(int i ,int i1,View groupView);
    }
    package com.example.squeezebox.Adapter;
    
    import android.content.Context;
    import android.view.View;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    import com.example.squeezebox.R;
    import com.example.squeezebox.util.Cuesor;
    
    import it.sephiroth.android.library.picasso.Picasso;
    
    public class NetAdapter extends MyBaseAdapter<Cuesor> {
    
        public NetAdapter(Context context) {
            super(context);
        }
    
        @Override
        public View addGroupView(int i, View groupView) {
            TextView textView = new TextView(context);
            textView.setText(getGroup(i));
            return textView;
        }
    
        @Override
        public View addChildView(int i, int i1, View groupView) {
            View view = layoutInflater.inflate(R.layout.net_item,null);
            ImageView imageView =view.findViewById(R.id.net_img);
            TextView textView1 = view.findViewById(R.id.net_txt1);
            TextView textView2 = view.findViewById(R.id.net_txt2);
            Cuesor cuesor = getChild(i,i1);
            Picasso.with(context).load(cuesor.picSmall).into(imageView);
            textView1.setText(cuesor.name);
            textView2.setText("学习人数:"+cuesor.learner);
            return view;
        }
    }

    (4) 在UI线程中调用方法并实现接口

       private void loadNet() {
            HttpRequest.request(PATH, new HttpRequest.onResponseLister() {
                @Override
                public void onResponseListerSuccess(String result) {
                    BaseEntity<List<Cuesor>> baseEntity = Parser.parserData(result);
                    //获取课程信息
                    List<Cuesor> cuesors = baseEntity.data;
    
                    NetAdapter netAdapter = new NetAdapter(MainActivity.this);
                    netAdapter.addNewData(LocalData.getGroupData(),LocalData.getNet(cuesors));
                    melv.setAdapter(netAdapter);
                }
    
                @Override
                public void onResponseListerSFail(String result) {
    
                }
            });
        }
     
  • 相关阅读:
    Spring源码构建 报错exception during working with external system: java.lang.AssertionError
    EDI_了解
    前端-正则表达式-收集
    Spring Boot必备知识点
    SSM开发在线考试系统-完整版+视频教程
    基于WEB的车票预订信息系统设计
    IDEA开发Maven构建SSM项目遇到的坑,action
    Linux教程-修炼
    2020年Java 成长路线-flag
    Redis教程
  • 原文地址:https://www.cnblogs.com/conglingkaishi/p/9458795.html
Copyright © 2011-2022 走看看