android中怎么自定义树形,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
TreeView.java代码:
package com.tbx.android.widget;
import java.util.ArrayList;
public class TreeView extends ListView implements OnItemClickListener {
private static String TAG = "TreeView";
List<TreeElement> treeElements = null;// 所有节点集合
List<TreeElement> currentElements = null;// 当前显示的节点集合
List<TreeElement> tempElements = null;// 用于临时存储
HashMap<String, List<TreeElement>> deleteMap = new HashMap<String, List<TreeElement>>();
//用于存储要删除的子节点,以及间接子节点。
TreeViewAdapter adapter = null;// 用于数据填充
LastLevelItemClickListener itemClickCallBack;// 用户点击事件回调
public TreeView(final Context context, AttributeSet attrs) {
super(context, attrs);
Log.d(TAG, "create with TreeView(Context context, AttributeSet attrs)");
treeElements = new ArrayList<TreeElement>();
currentElements = new ArrayList<TreeElement>();
adapter = new TreeViewAdapter(context, currentElements);
this.setAdapter(adapter);
itemClickCallBack = new LastLevelItemClickListener() {
@Override
public void onLastLevelItemClick(int position,TreeViewAdapter adapter) {
Log.d(TAG, "last level element "
+ currentElements.get(position).getTitle()
+ " is clicked");
}
};
this.setOnItemClickListener(this);
}
public void initData(Context context, List<TreeElement> treeElements) {
this.treeElements = treeElements;
getFirstLevelElements(context);
adapter.notifyDataSetChanged();
}
/**
* 设置点击事件回调接口
*
* @param itemClickCallBack
*/
public void setLastLevelItemClickCallBack(LastLevelItemClickListener itemClickCallBack) {
this.itemClickCallBack = itemClickCallBack;
}
/**
* 初始化树形结构列表数据,把第一层级的数据添加到currentElements中
*/
public void getFirstLevelElements(Context context) {
Log.d(TAG, "initCurrentElements");
int size = treeElements.size();
Log.d(TAG, "tree elements num is: " + size);
if (currentElements == null) {
currentElements = new ArrayList<TreeElement>();
}
currentElements.clear();
for (int i = 0; i < size; i++) {
if (treeElements.get(i).getLevel() == 1) {
currentElements.add(treeElements.get(i));
Log.d(TAG, "find a first level element: " + treeElements.get(i));
}
}
}
/**
* 从所有节点集合中获取某父节点的子节点集合
*
* @param parentId
* @return
*/
private List<TreeElement> getChildElementsFromAllById(String parentId) {
tempElements = new ArrayList<TreeElement>();
int size = treeElements.size();
for (int i = 0; i < size; i++) {
String temptParentId = treeElements.get(i).getParentId() ;
if(temptParentId != null){
if (temptParentId.equalsIgnoreCase(parentId)) {
tempElements.add(treeElements.get(i));
Log.d(TAG, "find a child element: " + treeElements.get(i));
}
}
}
return tempElements;
}
/**
* 从当前显示的节点集合中 , 获取某父节点的子节点集合
* @param parentId
* @return
*/
private List<TreeElement> getChildElementsFromCurrentById(String parentId) {
Log.d(TAG, "getChildElementsFromCurrentById parentId: " + parentId);
if (tempElements == null) {
tempElements = new ArrayList<TreeElement>();
} else {
tempElements.clear();
}
int size = currentElements.size();
if(size > 0){
for(TreeElement treeElement : currentElements){
String temp = treeElement.getParentId();
if(temp != null){
if (temp.equalsIgnoreCase(parentId)) {
tempElements.add(treeElement);
Log.d(TAG, "find a child element to delete: " +treeElement);
}
}
}
}
return tempElements;
}
/**
* 删除某父节点的所有子节点集合(包括直接节点和间接节点)
* @param parentId
* @return
*/
private synchronized boolean delAllChildElementsByParentId(String parentId) {
Log.e(TAG, "delAllChildElementsByParentId: " + parentId);
List<TreeElement> childElments = getChildElementsFromCurrentById(parentId);
List<TreeElement> treeElementsToDel = deleteMap.get(parentId);
if (treeElementsToDel == null) {
treeElementsToDel = new ArrayList<TreeElement>();
deleteMap.put(parentId, treeElementsToDel);
} else {
treeElementsToDel.clear();
}
int size = childElments.size();
Log.e(TAG, "childElments size : " + size);
TreeElement childElement = null;
for (int i = 0; i < size; i++) {
childElement = childElments.get(i);
//寻找间接节点
if (childElement.hasChild && childElement.fold) {
treeElementsToDel.add(childElement);
}
}
size = treeElementsToDel.size();
Log.e(TAG, "treeElementsToDel size : " + size);
if(size > 0){
//删除间接节点
List<TreeElement> deleteTreeElement = treeElementsToDel;
for(TreeElement element : deleteTreeElement){
delAllChildElementsByParentId(element.getId());
}
}
//删除直接节点
delDirectChildElementsByParentId(parentId);
return true;
}
/**
* 删除某父节点的直接子节点集合
*
* @param parentId
* @return
*/
private synchronized boolean delDirectChildElementsByParentId(
String parentId) {
Log.d(TAG, "delDirectChildElementsByParentId(): " + parentId);
boolean success = false;
if (currentElements == null || currentElements.size() == 0) {
Log.d(TAG, "delChildElementsById() failed,currentElements is null or it's size is 0");
return success;
}
synchronized (currentElements) {
int size = currentElements.size();
Log.d(TAG, "begin delete");
for (int i = size - 1; i >= 0; i--) {
String temp = currentElements.get(i).getParentId();
if(temp != null && temp.equalsIgnoreCase(parentId)){
currentElements.get(i).fold = false;// 记得隐藏子节点时把展开状态设为false
currentElements.remove(i);
}
}
}
success = true;
return success;
}
/**
* 根据id查下标
*
* @param id
* @return
*/
@SuppressWarnings("unused")
private int getElementIndexById(String id) {
int num = currentElements.size();
for (int i = 0; i < num; i++) {
if (currentElements.get(i).getId().equalsIgnoreCase(id)) {
return i;
}
}
return -1;
}
@SuppressWarnings("unused")
private TreeElement getElementById(String id){
int num = currentElements.size();
if( num > 0){
for (int i = 0; i < num; i++) {
if (currentElements.get(i).getId().equalsIgnoreCase(id)) {
return currentElements.get(i);
}
}
}
return null;
}
@Override
public void onItemClick(AdapterView<?> arg0, View convertView,
int position, long id) {
TreeElement element = currentElements.get(position);
if (element.isHasChild()) {// 当前节点有子节点时只进行数据显示或隐藏等操作
if (!element.isFold()) {// 当前父节点为未展开状态
currentElements.addAll(position + 1,this.getChildElementsFromAllById(element.getId()));
} else if (element.fold) {// 当前父节点为展开状态
boolean success = this.delAllChildElementsByParentId(element.getId());
Log.d(TAG, "delete child state: " + success);
if (!success) {
return;
}
}
element.setFold(!element.isFold());// 设置反状态
adapter.notifyDataSetChanged();// 刷新数据显示
} else {// 当前节点有子节点时只进行用户自定义操作
itemClickCallBack.onLastLevelItemClick(position,adapter);
}
}
/**
* 自定义内部接口,用于用户点击最终节点时的事件回调
*/
public interface LastLevelItemClickListener {
public void onLastLevelItemClick(int position,TreeViewAdapter adapter);
}
}
TreeElement.java代码:
/**
* 类名:TreeElement.java
* 类描述:树形结构节点类
* 创建时间:2012-11-23 16:32
*/
public class TreeElement {
String id = null;// 当前节点id
String title = null;// 当前节点文字
boolean hasParent = false;// 当前节点是否有父节点
boolean hasChild = false;// 当前节点是否有子节点
boolean childShow = false;// 如果子节点,字节当当前是否已显示
String parentId = null;// 父节点id
int level = -1;// 当前界面层级
boolean fold = false;// 是否处于展开状态
...
}
TreeViewAdapter.java
package com.tbx.android.adapter;
import java.util.List;
/**
* 类名:TreeViewAdapter.java
* 类描述:用于填充数据的类
* 创建时间:2012-11-23 16:32
*/
public class TreeViewAdapter extends BaseAdapter {
class ViewHolder {
ImageView icon;
TextView title;
}
Context context;
ViewHolder holder;
LayoutInflater inflater;
List<TreeElement> elements;
public TreeViewAdapter(Context context, List<TreeElement> elements) {
this.context = context;
this.elements = elements;
}
@Override
public int getCount() {
return elements.size();
}
@Override
public Object getItem(int position) {
return elements.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
/**
* ---------------------- get holder------------------------
*/
if (convertView == null) {
if (inflater == null) {
inflater = LayoutInflater.from(context);
}
holder = new ViewHolder();
convertView = inflater
.inflate(R.layout.tree_view_item, null);
holder.icon = (ImageView) convertView
.findViewById(R.id.tree_view_item_icon);
holder.title = (TextView) convertView
.findViewById(R.id.tree_view_item_title);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
/**
* ---------------------- set holder--------------------------
*/
if (elements.get(position).isHasChild()) {// 有子节点,要显示图标
if (elements.get(position).isFold()) {
holder.icon.setImageResource(R.drawable.tree_view_icon_open);
} else if (!elements.get(position).isFold()) {
holder.icon.setImageResource(R.drawable.tree_view_icon_close);
}
holder.icon.setVisibility(View.VISIBLE);
} else {// 没有子节点,要隐藏图标
holder.icon.setImageResource(R.drawable.tree_view_icon_close);
holder.icon.setVisibility(View.INVISIBLE);
}
holder.icon.setPadding(25 * (elements.get(position).getLevel()), 0, 0, 0);// 根据层级设置缩进
holder.title.setText(elements.get(position).getTitle());
holder.title.setTextSize(35 - elements.get(position).getLevel() * 5); // 根据层级设置字体大小
return convertView;
}
}
MainActivity.java
public class MainActivity extends Activity {
private TreeView lvAddress; //通讯录列表
private List<TreeElement> lvAddressData = new ArrayList<TreeElement>();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvAddress = (TreeView) findViewById(R.id.frame_listview_address);
LastLevelItemClickListener itemClickCallBack = new LastLevelItemClickListener() {
// 创建节点点击事件监听
@Override
public void onLastLevelItemClick(int position,
TreeViewAdapter adapter) {
TreeElement element = (TreeElement) adapter.getItem(position);
//然后自己处理
}
};
//初始化数据
initData();
lvAddress.initData(this, lvAddressData);// 初始化数据
lvAddress.setLastLevelItemClickCallBack(itemClickCallBack);// 设置节点点击事件监听
}
private void initData() {//测试数据
TreeElement root = new TreeElement();
root.setId("01");
root.setLevel(1);
root.setTitle("好友");
root.setFold(false);
root.setHasChild(true);
root.setHasParent(false);
root.setParentId(null);
lvAddressData.add(root);
TreeElement twoLevel = new TreeElement();
twoLevel.setId("0101");
twoLevel.setLevel(2);
twoLevel.setTitle("初中同学");
twoLevel.setFold(false);
twoLevel.setHasChild(true);
twoLevel.setHasParent(true);
twoLevel.setParentId("01");
lvAddressData.add(twoLevel);
TreeElement threeLevel = new TreeElement();
threeLevel.setId("010101");
threeLevel.setLevel(3);
threeLevel.setTitle("发财");
threeLevel.setFold(false);
threeLevel.setHasChild(false);
threeLevel.setHasParent(true);
threeLevel.setParentId("0101");
lvAddressData.add(threeLevel);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
tree_view_item.xml布局内容
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:orientation="horizontal" >
<ImageView
android:id="@+id/tree_view_item_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tree_view_item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="15dip"
/>
</LinearLayout>
关于android中怎么自定义树形问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/winHerson/blog/91491