編輯:關於Android編程
直接貼代碼,代碼中有相應注釋:
主界面Activity,布局就只一個ListView:
public class MainActivity extends Activity { private ListView mListView; private TreeListViewAdapter<TestBean> mAdapter; private List<TestBean> mDatas = new ArrayList<TestBean>(); @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.mListView = (ListView) findViewById(R.id.listview); initTestDatas(); try { mAdapter = new TreeListViewAdapter<TestBean>(mListView, this, mDatas, 0); } catch (Exception e) { e.printStackTrace(); } this.mListView.setAdapter(mAdapter); mAdapter.setmTreeListener(new TreeViewOnItemClick() { @Override public void onTreeItemClick(int position, Node node) { Toast.makeText(MainActivity.this, "你點擊的是:" + node.getName(), Toast.LENGTH_SHORT).show(); } }); this.mListView.setOnItemLongClickListener(new OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> arg0, View arg1, final int arg2, long arg3) { final EditText edt = new EditText(MainActivity.this); new AlertDialog.Builder(MainActivity.this).setTitle("Insert").setView(edt).setPositiveButton("submit", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (TextUtils.isEmpty(edt.getText().toString())) { Toast.makeText(MainActivity.this, "請填寫添加內容", Toast.LENGTH_SHORT).show(); } else { mAdapter.insertNodeData(arg2, edt.getText().toString()); } } }).setNegativeButton("Cancel", null).create().show(); return true; } }); } private void initTestDatas() { TestBean bean = null; bean = new TestBean(1, 0, "文件目錄1"); mDatas.add(bean); bean = new TestBean(2, 0, "文件目錄2"); mDatas.add(bean); bean = new TestBean(3, 0, "文件目錄3"); mDatas.add(bean); bean = new TestBean(4, 1, "文件目錄4"); mDatas.add(bean); bean = new TestBean(5, 1, "文件目錄5"); mDatas.add(bean); bean = new TestBean(6, 2, "文件目錄6"); mDatas.add(bean); bean = new TestBean(7, 2, "文件目錄7"); mDatas.add(bean); bean = new TestBean(8, 3, "文件目錄8"); mDatas.add(bean); bean = new TestBean(9, 3, "文件目錄9"); mDatas.add(bean); bean = new TestBean(10, 0, "文件目錄10"); mDatas.add(bean); } }
數據適配器基類:
** * 樹形ListView的數據適配器類 * @description: * @author ldm * @date 2015-10-9 上午9:47:01 */ public abstract class TreeViewBaseAdapter<T> extends BaseAdapter { protected Context context; protected List<T> datas; protected List<Node> mAllNodes; protected List<Node> mVisibleNodes; protected LayoutInflater mInflater; protected ListView treeLv; protected TreeViewOnItemClick mTreeListener; public TreeViewBaseAdapter(ListView treeLv, Context context, List<T> datas, int defaultExpandLevel) throws IllegalAccessException, IllegalArgumentException { this.context = context; this.treeLv = treeLv; mInflater = LayoutInflater.from(context); mAllNodes = TreeHelperTools.getSortedNodes(datas, defaultExpandLevel); mVisibleNodes = TreeHelperTools.filterVisibleNodes(mAllNodes); this.treeLv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) { expandOrCollapse(position); if(mTreeListener!=null){ mTreeListener.onTreeItemClick(position, mVisibleNodes.get(position)); } } }); } public void setmTreeListener(TreeViewOnItemClick mTreeListener) { this.mTreeListener = mTreeListener; } /** * 設置ListView點擊item節點時,是否應該展開 * @description: * @author ldm * @date 2015-10-10 上午9:05:08 */ protected void expandOrCollapse(int position) { Node n=mVisibleNodes.get(position); if(n!=null){ if(n.isLeaf()){ return; } n.setExpand(!n.isExpand()); mVisibleNodes=TreeHelperTools.filterVisibleNodes(mAllNodes); notifyDataSetChanged(); } } @Override public int getCount() { // TODO Auto-generated method stub return mVisibleNodes.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return mVisibleNodes.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { Node node=mVisibleNodes.get(position); convertView = getContentView(node,position, convertView, parent); return convertView; } public abstract View getContentView(Node node,int position, View convertView, ViewGroup parent); public interface TreeViewOnItemClick{ void onTreeItemClick(int position,Node node); } }
我們使用的Adapter
public class TreeListViewAdapter<T> extends TreeViewBaseAdapter<T> { public TreeListViewAdapter(ListView treeLv, Context context, List<T> datas, int defaultExpandLevel) throws IllegalAccessException, IllegalArgumentException { super(treeLv, context, datas, defaultExpandLevel); } @Override public View getContentView(Node node, int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { holder = new ViewHolder(); convertView = mInflater.inflate(R.layout.tree_listview_item, parent, false); holder.mItemIv = (ImageView) convertView.findViewById(R.id.mItemIv); holder.mItemTv = (TextView) convertView.findViewById(R.id.mItemTv); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.mItemIv.setPadding(node.getLevel()*30, 3, 3, 3); if (node.getIcon() == -1) { holder.mItemIv.setVisibility(View.INVISIBLE); } else { holder.mItemIv.setVisibility(View.VISIBLE); holder.mItemIv.setImageResource(node.getIcon()); } holder.mItemTv.setText(node.getName()); return convertView; } private static class ViewHolder { ImageView mItemIv; TextView mItemTv; } /** * 動態插入數據 * @description: * @author ldm * @date 2015-10-10 上午10:08:03 */ public void insertNodeData(int position,String label) { Node node=mVisibleNodes.get(position); int indexOf=mAllNodes.indexOf(node); Node insertNode=new Node(-1, node.getId(), label); insertNode.setParent(node); node.getChildren().add(insertNode); mAllNodes.add(indexOf+1,insertNode); mVisibleNodes=TreeHelperTools.filterVisibleNodes(mVisibleNodes); notifyDataSetChanged(); } }
數據處理的工具類:
public class TreeDatasHelperTools { /** * 將用戶提供的數據轉化成樹層級上可用數據 * @description: * @date 2015-10-9 下午4:07:24 */ public static <T> List<Node> datas2Nodes(List<T> datas) throws IllegalAccessException, IllegalArgumentException { List<Node> nodes = new ArrayList<Node>(); Node node = null; for (T t : datas) { int id = -1; int pid = -1; String label = ""; // node = new Node(); Class clazz = t.getClass(); Field[] fields = clazz.getDeclaredFields();// 反射獲取類中的字段 for (Field field : fields) { if (field.getAnnotation(TreeNodeId.class) != null) {// 根據字段上的注解來獲取對應的值 field.setAccessible(true);// 在java的反射使用中,如果字段是私有的,那麼必須要對這個字段設置才能正常使用,否則報錯 id = field.getInt(t); } if (field.getAnnotation(TreeNodePid.class) != null) { field.setAccessible(true); pid = field.getInt(t); } if (field.getAnnotation(TreeNodeLabel.class) != null) { field.setAccessible(true); label = (String) field.get(t); } } node = new Node(id, pid, label); nodes.add(node); } // 設置nodes中的父子節點關系 for (int i = 0; i < nodes.size(); i++) { Node n = nodes.get(i); for (int j = i + 1; j < nodes.size(); j++) { Node m = nodes.get(j); if (m.getPid() == n.getId()) {// 如果m的父節點pid==n的id,則m是父節點,n是子節點 n.getChildren().add(m); m.setParent(n); } else if (m.getId() == n.getPid()) { m.getChildren().add(n); n.setParent(m); } } } // 設置節點圖片 for (Node n : nodes) { setNodeIcon(n); } return nodes; } /** * 為我們的node數據設置對應的圖標 * @description: * @date 2015-10-9 下午4:46:29 */ private static void setNodeIcon(Node n) { if (n.getChildren().size() > 0 && n.isExpand()) {// 如果有子節點且展開狀態 n.setIcon(R.drawable.icon_unable); } else if (n.getChildren().size() > 0 && !n.isExpand()) { n.setIcon(R.drawable.icon_enable); } else { n.setIcon(-1); } } public static <T> List<Node> getSortedNodes(List<T> datas, int defaultExpandLevel) throws IllegalAccessException, IllegalArgumentException { List<Node> result = new ArrayList<Node>(); List<Node> nodes = datas2Nodes(datas); // 首先獲取根節點數據 List<Node> rootNodes = getRootNodes(nodes); for (Node node : rootNodes) { addNode(result, node, defaultExpandLevel, 1); } return result; }
/** * 獲取數據中的所有根節點數據 * @description: * @date 2015-10-9 下午5:00:32 */ private static List<Node> getRootNodes(List<Node> nodes) { List<Node> root = new ArrayList<Node>(); for (Node node : nodes) { if (node.isRoot()) { root.add(node); } } return root; } /** * 獲取到可見的節點數據 * @description: * @date 2015-10-9 下午5:12:58 */ public static List<Node> filterVisibleNodes(List<Node> mAllNodes) { List<Node> nodes = new ArrayList<Node>(); for (Node node : mAllNodes) { if (node.isRoot() || node.isParentExpand()) { setNodeIcon(node); nodes.add(node); } } return nodes; } /** * 把一個節點的所有子節點都放入result中 * @description: * @date 2015-10-9 下午5:05:57 */ private static void addNode(List<Node> result, Node node, int defaultExpandLevel, int currentLevel) { result.add(node); if (defaultExpandLevel >= currentLevel) { node.setExpand(true); } if (node.isLeaf()) { return; } for (int i = 0; i < node.getChildren().size(); i++) { addNode(result, node.getChildren().get(i), defaultExpandLevel, currentLevel + 1); } } }
數據實體Bean:
public class TestBean { @TreeNodeId private int id;//添加對應的注解 @TreeNodePid private int pid; @TreeNodeLabel private String label; private String desc; public TestBean(int id, int pid, String label) { super(); this.id = id; this.pid = pid; this.label = label; } public TestBean() { // TODO Auto-generated constructor stub } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getPid() { return pid; } public void setPid(int pid) { this.pid = pid; } public String getLabel() { return label; } public void setLabel(String label) { this.label = label; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } }
數據展示中的Node類,我們可以通過反射+注解把任意實體bean如TestBean映射成我們想要的Node
public class Node { private int id;// 所在節點id private int pid = 0;// 父節點的id private String name;// 對應的內容 private int level;// 所在ListView中樹層級 private boolean isExpand = false;// 所在節點是否展開 private int icon;// 圖標icon private Node parent;// 父節點Node private List<Node> children = new ArrayList<Node>();// 對應的子節點數據集 public Node() { } public Node(int id, int pid, String name) { this.id = id; this.pid = pid; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getPid() { return pid; } public void setPid(int pid) { this.pid = pid; } public String getName() { return name; } public void setName(String name) { this.name = name; }
/** * 當前節點所在的層級 * @description: * @date 2015-10-9 下午4:02:29 */ public int getLevel() { return parent == null ? 0 : parent.getLevel() + 1; } public void setLevel(int level) { this.level = level; } public boolean isExpand() { return isExpand; } public void setExpand(boolean isExpand) { this.isExpand = isExpand; if (!isExpand && children.size() > 0) {// 如果當前節點沒有展開,則其子節點展開狀態也是:沒展開 for (Node node : children) { node.setExpand(false); } } } public int getIcon() { return icon; } public void setIcon(int icon) { this.icon = icon; } public Node getParent() { return parent; } public void setParent(Node parent) { this.parent = parent; } public List<Node> getChildren() { return children; } public void setChildren(List<Node> children) { this.children = children; } /** * 判斷當前節點有沒有子節點 * @description: * @author ldm * @date 2015-10-9 下午3:59:42 */ public boolean isLeaf() { return children.size() == 0; } /** * 是不是根節點 * @description: * @author ldm * @date 2015-10-9 下午3:58:15 */ public boolean isRoot() { return parent == null; } /** * 當前節點所在父節點是否展開 * @description: * @author ldm * @date 2015-10-9 下午3:58:34 */ public boolean isParentExpand() { if (parent == null) { return false; } else { return parent.isExpand; } } }
用到的注解類:
@Target(ElementType.FIELD)//定義注解的作用目標:字段、枚舉的常量 @Retention(RetentionPolicy.RUNTIME)//注解策略: 注解會在class字節碼文件中存在,在運行時可以通過反射獲取到 public @interface TreeNodeId { }
@Target(ElementType.FIELD)//定義注解的作用目標:字段、枚舉的常量 @Retention(RetentionPolicy.RUNTIME)//注解策略: 注解會在class字節碼文件中存在,在運行時可以通過反射獲取到 public @interface TreeNodeLabel { } ``
@Target(ElementType.FIELD)//定義注解的作用目標:字段、枚舉的常量 @Retention(RetentionPolicy.RUNTIME)//注解策略: 注解會在class字節碼文件中存在,在運行時可以通過反射獲取到 public @interface TreeNodePid { }
以上就是Android實現樹形層級ListView的相關代碼,希望對大家的學習有所幫助。
微信小程序 bnner滾動首先是輪播圖,autoplay 自動播放,interval 輪播的時間,duration 切換速度,可以根據自己需求去添加。Delete:是刪除
問題:橫豎屏切換時Activity的生命周期?測試環境:華為mate7 package com.virglass.beyond.activity;import
相機調焦:原理,使用豎直seekbar,根據用戶拖拉來獲得距離,然後以Parameter的形式設置到Camera。 實現O
概述Healthd是android4.4之後提出來的一種中介模型,該模型向下監聽來自底層的電池事件,向上傳遞電池數據信息給Framework層的BatteryServic