树形结构

package com.isoftston.issuser.conchapp.views.security;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;

import com.corelibs.base.BaseActivity;
import com.isoftston.issuser.conchapp.R;
import com.isoftston.issuser.conchapp.adapters.NodeTreeAdapter;
import com.isoftston.issuser.conchapp.constants.Constant;
import com.isoftston.issuser.conchapp.model.bean.OrgBean;
import com.isoftston.issuser.conchapp.model.bean.SafeListBean;
import com.isoftston.issuser.conchapp.model.bean.SecuritySearchBean;
import com.isoftston.issuser.conchapp.model.bean.UserInfoBean;
import com.isoftston.issuser.conchapp.presenter.SecurityPresenter;
import com.isoftston.issuser.conchapp.utils.Node;
import com.isoftston.issuser.conchapp.utils.NodeHelper;
import com.isoftston.issuser.conchapp.views.interfaces.SecuryView;
import com.isoftston.issuser.conchapp.weight.NavBar;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import butterknife.Bind;

/**
 * Created by issuser on 2018/4/26.
 */

public class OrgActivity extends BaseActivity<SecuryView,SecurityPresenter> implements SecuryView  {
    private Context context = OrgActivity.this;
    private NodeTreeAdapter mAdapter;

    private LinkedList<Node> mLinkedList = new LinkedList<>();
    private List<Node> data = new ArrayList<>();

    private static final String TAG = OrgActivity.class.getSimpleName();

    private final Integer FIND_RESULT_CODE = 130;

    private final Integer HIDDEN_RESULT_CODE = 131;

    private int code;

    private int pos;

    //记录已请求的记录
    private List<Integer> posList = new ArrayList<>();

    public static Intent getLaucnher(Context context,int i){//根据code设置头部标题文字
        Intent intent =new Intent(context,OrgActivity.class);
        intent.putExtra("code",i);
        return intent;
    }

    @Bind(R.id.id_tree)
    ListView mListView;

    @Bind(R.id.nav)
    NavBar nav;

    @Override
    protected int getLayoutId() {
        return R.layout.org_select_dept_layout;
    }

    @Override
    protected void init(Bundle savedInstanceState) {
        code = getIntent().getIntExtra("code",-1);
        nav.setColorRes(R.color.white);
        nav.setTitleColor(getResources().getColor(R.color.black));
        setBarColor(getResources().getColor(R.color.transparent_black));
        nav.showBack(2);
        if(0 == code)
        {
            nav.setNavTitle(getString(R.string.find_company));
        }
        else if(1 == code)
        {
            nav.setNavTitle(getString(R.string.trouble_company));
        }else if (2==code){
            nav.setNavTitle(getString(R.string.work_company));
        }

        mAdapter = new NodeTreeAdapter(context,mListView,mLinkedList);
        mListView.setAdapter(mAdapter);
        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
                Node node = (Node)mAdapter.getItem(position);
                //Toast.makeText(getApplicationContext(),"选中2:"+ node.get_label(),Toast.LENGTH_SHORT).show();
                Log.i(TAG,"node pos:" + position + ",node name:" + node.get_label() + ",node id:" + node.get_id() + ",node child:" + node.hasChild());

                //下一级请求
                if(node.hasChild())
                {
                    pos = position;
                    if(!posList.contains(pos))
                    {
                        presenter.getCompanyChoiceNextList((String)node.get_id());
                        posList.add(pos);
                    }
                    else
                    {
                        mAdapter.expandOrCollapse(pos);
                    }
                }
                else
                {
                    //选中单位
                    Intent intent =new Intent();
                    if(0 == code||2==code)
                    {
                        intent.putExtra(Constant.FIND_COMPANY_NAME,node.get_label());
                        intent.putExtra(Constant.FIND_COMPANY_ID,(String)node.get_id());
                        setResult(FIND_RESULT_CODE,intent);
                    }
                    else if(1 == code)
                    {
                        intent.putExtra(Constant.DANGER_COMPANY_NAME,node.get_label());
                        intent.putExtra(Constant.DANGER_COMPANY_ID,(String)node.get_id());
                        setResult(HIDDEN_RESULT_CODE,intent);
                    }
                    finish();
                }
            }
        });

        presenter.getCompanyChoiceList();

    }

    @Override
    protected SecurityPresenter createPresenter() {
        return new SecurityPresenter();
    }

    @Override
    public void onLoadingCompleted() {

    }

    @Override
    public void onAllPageLoaded() {

    }

    @Override
    public void addSuccess() {

    }

    @Override
    public void getSafeListSuccess(SafeListBean data) {

    }

    @Override
    public void addFailed() {

    }

    @Override
    public void getSafeChoiceList(SecuritySearchBean bean) {
        data.addAll(bean.ORG);
        mLinkedList.addAll(NodeHelper.sortNodes(data));
        mLinkedList = NodeHelper.sortLinkedNodes(mLinkedList);
        data.clear();
        mAdapter.notifyDataSetChanged();

    }

    @Override
    public void getOrgList(List<OrgBean> bean) {
        data.addAll(bean);
        mLinkedList.addAll(NodeHelper.sortNodes(data));
        mLinkedList = NodeHelper.sortLinkedNodes(mLinkedList);
        mAdapter.notifyDataSetChanged();
        mAdapter.expandOrCollapse(pos);
    }

    @Override
    public void getOrgId(String orgId) {

    }

    @Override
    public void getWorkError() {

    }

    @Override
    public void setUserInfo(UserInfoBean userInfo) {

    }

}
 

==================工具类==============

package com.isoftston.issuser.conchapp.utils;

import com.isoftston.issuser.conchapp.R;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * Created by HQOCSHheqing on 2016/8/2.
 *
 * @description 节点帮助类
 */
public class NodeHelper {

    public static LinkedList<Node> sortLinkedNodes(LinkedList<Node> tmpNodeList){

        LinkedList<Node> nodeList = new LinkedList<>();
        nodeList.addAll(tmpNodeList);

        LinkedList<Node> rootNodes = new LinkedList<>();
        int size = nodeList.size();
        Node m;
        Node n;
        //两个for循环整理出所有数据之间的斧子关系,最后会构造出一个森林(就是可能有多棵树)
        for (int i = 0;i < size;i++){
            m = nodeList.get(i);
            for (int j = i+1;j < size;j++){
                n = nodeList.get(j);
                if (m.parent(n)){
                    m.get_childrenList().add(n);
                    n.set_parent(m);
                }else if (m.child(n)){
                    n.get_childrenList().add(m);
                    m.set_parent(n);
                }
            }
        }
        //找出所有的树根,同事设置相应的图标(后面你会发现其实这里的主要
        // 作用是设置叶节点和非叶节点的图标)
        for (int i = 0;i < size;i++){
            m = nodeList.get(i);
            if (m.isRoot()){
                rootNodes.add(m);
            }
            setNodeIcon(m);
        }
        nodeList.clear();//此时所有的关系已经整理完成了
        // ,森林构造完成,可以清空之前的数据,释放内存,提高性能
        // ,如果之前的数据还有用的话就不清空
        nodeList = rootNodes;//返回所有的根节点
        rootNodes = null;
        return nodeList;
    }

    /**
     * 传入所有的要展示的节点数据
     * @param tmpNodeList  返回值是所有的根节点
     * @return
     */
    public static List<Node> sortNodes(List<Node> tmpNodeList){

        List<Node> nodeList = new ArrayList<>();
        nodeList.addAll(tmpNodeList);

        List<Node> rootNodes = new ArrayList<>();
        int size = nodeList.size();
        Node m;
        Node n;
        //两个for循环整理出所有数据之间的斧子关系,最后会构造出一个森林(就是可能有多棵树)
        for (int i = 0;i < size;i++){
            m = nodeList.get(i);
            for (int j = i+1;j < size;j++){
                n = nodeList.get(j);
                if (m.parent(n)){
                    m.get_childrenList().add(n);
                    n.set_parent(m);
                }else if (m.child(n)){
                    n.get_childrenList().add(m);
                    m.set_parent(n);
                }
            }
        }
        //找出所有的树根,同事设置相应的图标(后面你会发现其实这里的主要
        // 作用是设置叶节点和非叶节点的图标)
        for (int i = 0;i < size;i++){
            m = nodeList.get(i);
            if (m.isRoot()){
                rootNodes.add(m);
            }
            setNodeIcon(m);
        }
        nodeList.clear();//此时所有的关系已经整理完成了
        // ,森林构造完成,可以清空之前的数据,释放内存,提高性能
        // ,如果之前的数据还有用的话就不清空
        nodeList = rootNodes;//返回所有的根节点
        rootNodes = null;
        return nodeList;
    }

    /**
     * 设置图标
     * @param node
     */
    private static void setNodeIcon(Node node){
        if (!node.isLeaf()){
            if (node.isExpand()){
                node.set_icon(R.mipmap.collapse);
            }else{
                node.set_icon(R.mipmap.expand2);
            }
        }else{
            node.set_icon(-1);
        }
    }
}

===========javabean===========================

package com.isoftston.issuser.conchapp.model.bean;

import android.util.Log;

import com.isoftston.issuser.conchapp.utils.Node;

/**
 * Created by issuser on 2018/4/26.
 */

public class OrgBean extends Node<String> {

    private static final String TAG = OrgBean.class.getSimpleName();

    /**
     * 此处返回节点ID
     * @return
     */
    @Override
    public String get_id() {
        return ID_;
    }

    /**
     * 此处返回父亲节点ID
     * @return
     */
    @Override
    public String get_parentId() {
        return PARENT_ID_;
    }

    @Override
    public String get_label() {
        return ORG_NAME_;
    }

    @Override
    public boolean parent(Node dest) {
        if(ID_ == null)
        {
            return false;
        }

        if (ID_ .equals(dest.get_parentId())){
            return true;
        }
        return false;
    }

    @Override
    public boolean child(Node dest) {

        if(PARENT_ID_ == null)
        {
            return  false;
        }

        if (PARENT_ID_.equals(dest.get_id())){
            return true;
        }
        return false;
    }

    @Override
    public boolean hasChild() {
        return HASCHILD.equals("1");
    }

    private String ID_;

    public String getPARENT_ID_() {
        return PARENT_ID_;
    }

    public void setPARENT_ID_(String PARENT_ID_) {
        this.PARENT_ID_ = PARENT_ID_;
    }

    private String PARENT_ID_;
    private String ORG_NAME_;
    private String ISCOMPANY_;
    private String HASCHILD = "1";

    public String getID_() {
        return ID_;
    }

    public void setID_(String ID_) {
        this.ID_ = ID_;
    }

    public String getORG_NAME_() {
        return ORG_NAME_;
    }

    public void setORG_NAME_(String ORG_NAME_) {
        this.ORG_NAME_ = ORG_NAME_;
    }


    public String getISCOMPANY_() {
        return ISCOMPANY_;
    }

    public void setISCOMPANY_(String ISCOMPANY_) {
        this.ISCOMPANY_ = ISCOMPANY_;
    }

    public String getHASCHILD() {
        return HASCHILD;
    }

    public void setHASCHILD(String HASCHILD) {
        this.HASCHILD = HASCHILD;
    }
}

===============适配器adpter==================

package com.isoftston.issuser.conchapp.adapters;

import android.app.ActionBar;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import com.isoftston.issuser.conchapp.R;
import com.isoftston.issuser.conchapp.utils.Node;
import com.isoftston.issuser.conchapp.utils.NodeHelper;

import java.util.LinkedList;
import java.util.List;

/**
 * Created by HQOCSHheqing on 2016/8/3.
 *
 * @description 适配器类,就是listview最常见的适配器写法
 */
public class NodeTreeAdapter extends BaseAdapter{

    //大家经常用ArrayList,但是这里为什么要使用LinkedList
    // ,后面大家会发现因为这个list会随着用户展开、收缩某一项而频繁的进行增加、删除元素操作,
    // 因为ArrayList是数组实现的,频繁的增删性能低下,而LinkedList是链表实现的,对于频繁的增删
    //操作性能要比ArrayList好。
    private LinkedList<Node> nodeLinkedList;
    private LayoutInflater inflater;
    private int retract;//缩进值
    private Context context;

    public NodeTreeAdapter(Context context,ListView listView,LinkedList<Node> linkedList){
        inflater = LayoutInflater.from(context);
        this.context = context;
        nodeLinkedList = linkedList;
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                expandOrCollapse(position);
            }
        });
        //缩进值,大家可以将它配置在资源文件中,从而实现适配
        retract = (int)(context.getResources().getDisplayMetrics().density*10+0.5f);
    }

    /**
     * 展开或收缩用户点击的条目
     * @param position
     */
    public void expandOrCollapse(int position){
        Node node = nodeLinkedList.get(position);
        if (node != null && !node.isLeaf()){
            boolean old = node.isExpand();
            if (old){
                List<Node> nodeList = node.get_childrenList();
                int size = nodeList.size();
                Node tmp = null;
                for (int i = 0;i < size;i++){
                    tmp = nodeList.get(i);
                    if (tmp.isExpand()){
                        collapse(tmp,position+1);
                    }
                    nodeLinkedList.remove(position+1);
                }
            }else{
                nodeLinkedList.addAll(position + 1, node.get_childrenList());
            }
            node.setIsExpand(!old);
            notifyDataSetChanged();
        }
    }
    /**
     * 递归收缩用户点击的条目
     * 因为此中实现思路是:当用户展开某一条时,就将该条对应的所有子节点加入到nodeLinkedList
     * ,同时控制缩进,当用户收缩某一条时,就将该条所对应的子节点全部删除,而当用户跨级缩进时
     * ,就需要递归缩进其所有的孩子节点,这样才能保持整个nodeLinkedList的正确性,同时这种实
     * 现方式避免了每次对所有数据进行处理然后插入到一个list,最后显示出来,当数据量一大,就会卡顿,
     * 所以这种只改变局部数据的方式性能大大提高。
     * @param position
     */
    private void collapse(Node node,int position){
        node.setIsExpand(false);
        List<Node> nodes = node.get_childrenList();
        int size = nodes.size();
        Node tmp = null;
        for (int i = 0;i < size;i++){
            tmp = nodes.get(i);
            if (tmp.isExpand()){
                collapse(tmp,position+1);
            }
            nodeLinkedList.remove(position+1);
        }
    }

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

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

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final ViewHolder holder;
        if (convertView == null){
            convertView = inflater.inflate(R.layout.org_tree_listview_item,null);
            holder = new ViewHolder();
            holder.imageView = (ImageView)convertView.findViewById(R.id.id_treenode_icon);
            holder.label = (TextView)convertView.findViewById(R.id.id_treenode_label);
            holder.confirm = (LinearLayout)convertView.findViewById(R.id.id_confirm);
            convertView.setTag(holder);
        }else{
            holder = (ViewHolder)convertView.getTag();
        }
        Node node = nodeLinkedList.get(position);
        holder.label.setText(node.get_label());
        if(node.get_icon() == -1){
            holder.imageView.setVisibility(View.INVISIBLE);
        }else{
            ViewGroup.LayoutParams params = holder.imageView.getLayoutParams();
            holder.imageView.setLayoutParams(params);
            holder.imageView.setVisibility(View.VISIBLE);
            holder.imageView.setImageResource(node.get_icon());
        }
        holder.confirm.setTag(position);
//        holder.confirm.setOnClickListener(new View.OnClickListener() {
//            @Override
//            public void onClick(View v) {
//                Toast.makeText(context,"选中:"+v.getTag(),Toast.LENGTH_SHORT).show();
//                Node node = (Node)getItem((Integer)v.getTag());
//                Toast.makeText(context,"选中:"+node.get_label(),Toast.LENGTH_SHORT).show();
//
//            }
//        });
        convertView.setPadding(node.get_level()*retract,5,5,5);
        return convertView;
    }

    static class ViewHolder{
        public ImageView imageView;
        public TextView label;
        public LinearLayout confirm;
    }

}

========================node==============

package com.isoftston.issuser.conchapp.utils;

import com.isoftston.issuser.conchapp.R;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by HQOCSHheqing on 2016/8/2.
 *
 * @description  节点抽象类(泛型T主要是考虑到ID和parentID有可能是int型也有可能是String型
 * 即这里可以传入Integer或者String,具体什么类型由子类指定
,因为这两种类型比较是否相等的方式不同:一个是用 “==”,一个是用  equals() 函数)
 */
public abstract class Node<T> {



    private int _level = -1;//当前节点的层级,初始值-1 后面会讲到
    private List<Node> _childrenList = new ArrayList<>();//所有的孩子节点
    private Node _parent;//父亲节点
    private int _icon;//图标资源ID
    private boolean isExpand = false;//当前状态是否展开


    public abstract T get_id();//得到当前节点ID
    public abstract T get_parentId();//得到当前节点的父ID
    public abstract String get_label();//要显示的内容
    public abstract boolean parent(Node dest);//判断当前节点是否是dest的父亲节点
    public abstract boolean child(Node dest);//判断当前节点是否是dest的孩子节点
    public abstract boolean hasChild(); //判断当前节点是否是叶子节点

    public int get_level() {
        if (_level == -1){//如果是 -1 的话就递归获取
            //因为是树形结构,所以此处想要得到当前节点的层级
            //,必须递归调用,但是递归效率低下,如果每次都递归获取会严重影响性能,所以我们把第一次
            //得到的结果保存起来避免每次递归获取
            int level = _parent == null ? 1 : _parent.get_level()+1;
            _level = level;
            return _level;
        }
        return _level;
    }

    public void set_level(int _level) {
        this._level = _level;
    }

    public List<Node> get_childrenList() {
        return _childrenList;
    }

    public void set_childrenList(List<Node> _childrenList) {
        this._childrenList = _childrenList;
    }

    public Node get_parent() {
        return _parent;
    }

    public void set_parent(Node _parent) {
        this._parent = _parent;
    }

    public int get_icon() {
        return _icon;
    }

    public void set_icon(int _icon) {
        this._icon = _icon;
    }

    public boolean isExpand() {
        return isExpand;
    }

    public void setIsExpand(boolean isExpand) {
        this.isExpand = isExpand;
        if (isExpand){
            _icon = R.mipmap.collapse;
        }else{
            _icon = R.mipmap.expand2;
        }
    }

    public boolean isRoot(){
        return _parent == null;
    }

    public boolean isLeaf(){
        return !hasChild();
    }

}

===org_tree_listview_item===========

<?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="wrap_content">

    <ImageView
        android:id="@+id/id_treenode_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:src="@mipmap/expand2" />

    <!--保证整块区域可点,使用户好点击-->
    <LinearLayout
        android:id="@+id/id_confirm"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:clickable="true"
        android:paddingBottom="8dp"
        android:paddingLeft="15dp"
        android:paddingRight="15dp"
        android:paddingTop="8dp">

        <ImageView
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:scaleType="centerInside" />
    </LinearLayout>


    <TextView
        android:id="@+id/id_treenode_label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_toLeftOf="@id/id_confirm"
        android:layout_toRightOf="@id/id_treenode_icon"
        android:textColor="@android:color/black"
        android:textSize="12sp" />

</RelativeLayout>

====activity布局========

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.isoftston.issuser.conchapp.weight.NavBar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/nav"
        />

    <ListView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:divider="@color/line"
        android:dividerHeight="1dp"
        android:scrollbars="none"
        android:id="@+id/id_tree"
        />

</LinearLayout>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值