您的位置:首页 > 其它

TreeView---利用RecyclerView打造高性能树形控件

2017-07-04 15:39 363 查看
   已经很久没更新博客了,主要是最近太忙了,现在app终于发布了,这也使小编有了一点时间把前一段时间,遇到的问题总结一下,记录下来,以便日后查看,也希望能帮到有需要的道友!话不多说,进入正题 :TreeView---利用RecyclerView打造高性能树形控件

  TreeView顾名思义就是树状界面,刚开始看到这种界面的时候,觉得通过RecyclerView的嵌套完全可以实现,只不过自己增加一些判断而已,后来随着树状节点的增加,就发现再用RecycleView嵌套工作量就会非常巨大而且效果不佳。TreeView是Girhub上一位大神提供的一种通过自定义RecyclerView实现的可以多级嵌套的树状结构,这里提供源码地址:https://github.com/shineM/TreeView

先看下效果:

 

    

  

  

 
   


实现步骤:

1,下载TreeView代码

2,将下载的TreeView中treeview_lib中的代码拷贝到自己的demo中(或者添加依赖,我是直接拷贝了需要的额demo)

3,添加RecyclerView依赖,这个是TreeView需要用的;

4,上述工作完成后,就可以开始写代码了:

a.先看主页面的Xml,非常简单,就一个ViewGroup:

<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="com.example.administrator.mytreemode.MainActivity">

<LinearLayout
android:id="@+id/myView_first"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>

</LinearLayout>

b.MainActivity中代码:

public class MainActivity extends AppCompatActivity {

private LinearLayout myfirstViwe;
private List<String> list1 = new ArrayList<>();
private FirstNameView fistNameView;
private TreeNode rootNode;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

list1.add("西游记");
list1.add("三国演义");
list1.add("水浒传");
list1.add("红楼梦");
list1.add("金瓶梅");
list1.add("山海经");

init();
}

private void init() {
myfirstViwe = (LinearLayout) findViewById(R.id.myView_first);
fistNameView = new FirstNameView();
loadData();
TreeView treeView = new TreeView(rootNode,this,new FirstItemViewFactory());

View view = treeView.getView();
view.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
myfirstViwe.addView(view);
//得到选择的类目
List<TreeNode> mTreeNodes = treeView.getSelectedNodes();

}

private void loadData(){

//跟节点
rootNode = TreeNode.root();
TreeNode treeNode1 = new TreeNode("图书馆");
treeNode1.setLevel(0);
treeNode1.setExpanded(false);
treeNode1.setItemClickEnable(true);
for(int i = 0; i < list1.size(); i++){
TreeNode treeNode2 = new TreeNode(list1.get(i).toString());
treeNode2.setLevel(1);//设置级数
treeNode2.setExpanded(false);//设置是否展开
treeNode2.setItemClickEnable(true);//是否可点击

treeNode1.addChild(treeNode2);
for(int k = 0; k < 12; k++){
TreeNode treeNode3 = new TreeNode(new String(list1.get(i) + k));
treeNode3.setLevel(2);
treeNode3.setItemClickEnable(false);
treeNode2.addChild(treeNode3);
}

}
rootNode.addChild(treeNode1);

}

}

 接下来,我们一步一步来介绍写作思路:

1、首先声明ViewGroup,
并创建一个List<String>,用来存放要显示数据(当然,也可以不创建,这个根据实际需求来做)

2、在loadData()方法中着重写了树状层级关系

第一级:treeNode1 只有一个图书馆

第二级:treeNode2这里显示了我们之前写的ist集合

第三级:treeNode3这里面就是一些示例数据。

3、很重要的一句话:treeNode.addChild()这一句是级联的关键,当然只有这些是不够,

4、创建一个工厂,继承自TreeView中的:BaseNodeViewFactory,这个工厂用来根据level得到每一级的BaseNodeViewBinder

public class FirstItemViewFactory extends BaseNodeViewFactory {
@Override
public BaseNodeViewBinder getNodeViewBinder(View view, int level) {
switch (level){
case 0:
return new AllList(view);
case 1:
return new FirstAllList(view);

case 2:
return new FirstItemList(view);
}
return null;
}
}


5、到这一步,你会看到level,这就是MainActivity中treeNode.setLevel()中,你说设置的level,分别有,0,1,2说明这个树状结构易购有三级,每一级都相当于Recyclerview中的一个item。通过return 方法,可以看到不同级的布局

6、这里不再多说,只展示三级布局和代码:

AllList布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="46dp">
<View android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#f5f5f5"/>
<RelativeLayout
android:id="@+id/relative_classify"
android:layout_width="match_parent"
android:layout_height="46dp"
android:background="#ffffff">
<ImageView
android:id="@+id/image_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:layout_marginRight=[b]"12dp"
android:layout_centerVertical="true"
android:src="@mipmap/img_catergory_icon"/>
<TextView
android:id="@+id/all_name"
android:layout_toRightOf="@id/image_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_centerVertical="true"/>
</RelativeLayout>

</LinearLayout>

AllList代码:

public class AllList extends BaseNodeViewBinder{

private ImageView image_arrow;
private TextView all_name;
public AllList(View itemView) {
super(itemView);
image_arrow = (ImageView) itemView.findViewById(R.id.image_arrow);
all_name = (TextView) itemView.findViewById(R.id.all_name);
}

@Override
public int getLayoutId() {
return R.layout.all_item;
}

@Override
public void bindView(TreeNode treeNode) {
all_name.setText(treeNode.getValue() + "");//设置显示数据
}
/** 根据是否展开来变换图标 */
@Override
public void onNodeToggled(TreeNode treeNode, boolean expand) {
if(expand){
image_arrow.setImageResource(R.mipmap.img_catergory_spinner_icon);
}else {
image_arrow.setImageResource(R.mipmap.img_catergory_icon);
}
}
}

FirstAllList布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="50dp">
<View android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#555555"/>

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="46dp">
<ImageView
android:id="@+id/image_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:src="@mipmap/img_catergory_icon"/>
<TextView
android:id="@+id/text_all_Select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/image_arrow"
android:textSize="14sp"
android:clickable="false"
android:layout_centerVertical="true"
android:layout_marginLeft="5dp"/>
<CheckBox
android:id="@+id/check_select_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:paddingRight="12dp"
android:paddingTop="8dp"/>
</RelativeLayout>

</LinearLayout>


FirstAllList代码:

public class FirstAllList extends CheckableNodeViewBinder {

private TextView text_all_Select;
private CheckBox check_select_all;
private ImageView image_arrow;
public FirstAllList(View itemView) {
super(itemView);
image_arrow = (ImageView) itemView.findViewById(R.id.image_arrow);
text_all_Select = (TextView) itemView.findViewById(R.id.text_all_Select);
check_select_all = (CheckBox) itemView.findViewById(R.id.check_select_all);
}

@Override
public int getCheckableViewId() {
return R.id.check_select_all;

}

@Override
public int getLayoutId() {
return R.layout.first_all;
}

@Override
public void bindView(TreeNode treeNode) {
/** 设置TextView数据,作为第一级类目 */
text_all_Select.setText(treeNode.getValue() + "");
}

@Override
public void onNodeToggled(TreeNode treeNode, boolean expand) {
if(expand){
image_arrow.setImageResource(R.mipmap.img_catergory_spinner_icon);
}else {
image_arrow.setImageResource(R.mipmap.img_catergory_icon);
}
}
}

FirstItemList布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="46dp">
<View android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#f5f5f5"/>
<RelativeLayout
android:id="@+id/relative_shop"
android:layout_width="match_parent"
android:layout_height="46dp"
android:background="#ffffff">

<TextView
android:id="@+id/item_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textColor="#666666"
android:layout_centerVertical="true"
android:layout_marginLeft="31dp"
android:text="kkkk"/>
<CheckBox
android:id="@+id/item_choice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:paddingRight="12dp"
android:paddingTop="8dp" />
</RelativeLayout>

</LinearLayout>

FirstItemList代码:

public class FirstItemList extends CheckableNodeViewBinder{
private TextView item_name;
private CheckBox item_choice;

public FirstItemList(View itemView) {
super(itemView);
item_name = (TextView) itemView.findViewById(R.id.item_name);
item_choice = (CheckBox) itemView.findViewById(R.id.item_choice);
}

@Override
public int getCheckableViewId() {
return R.id.item_choice;
}

@Override
public int getLayoutId() {
return R.layout.item_list;
}

@Override
public void bindView(TreeNode treeNode) {
item_name.setText(treeNode.getValue() + "");
}
}

三级全部展示,你会发现第一级和第二级和第三级继承的分别是TreeView中的BaseNodeViewBinder和CheckableNodeViewBinder

这两者的区别在于:CheckableNodeViewBinder是BaseNodeViewBinder的一个子类,带有选择功能

至此,想要的效果就实现完了。

密码是:cbl2

源码下载地址:
http://pan.baidu.com/s/1o7ZlyLs 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息