編輯:關於Android編程
1.開發原因
在項目中經常需要一個需要一個樹狀框架,這是非常常見的控件。不過可能是谷歌考慮到android是手機系統,界面寬度有限,所以只提供了只有二級的ExpandableListView。雖然這個控件可以滿足很多需求,但是無數級的樹在某些情況下還是需要的,所以我花了一天時間(大部分時間都在調試動畫去了,不過現在動畫還有點問題,具體原因不明。。如果某位大神能找到原因灰常感謝)。
2.原理
網上很多都是擴展listview實現的,不過listview貌似不支持復雜控件的事件?而且做動畫也不方便,所有我決定擴展linearlayout,在裡面增加子節點的方式實現。
3.代碼
TreeView.java:
復制代碼 代碼如下:
package net.memornote.android.ui.view;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.LinearLayout;
public class TreeView extends LinearLayout{
// private List<TreeItem> items;
private List<TreeItem> sortedItems;
private int animTime;
public TreeView(Context context, AttributeSet attrs) {
super(context, attrs);
setOrientation(LinearLayout.VERTICAL);
}
/**
* initialize data,you must make sure that each item has parent except the top ones.
* @param items the data to show
* @param index the index of the tree to insert to
* @param viewHeight each view's height
* @param animTime if you want expand animation,
* you can set the time(ms) of animation,otherwise you can set 0.
*
*/
public void initData(List<TreeItem> items,int index){
if(items==null||items.size()==0){
return ;
}
sortItemList(items);
int size=sortedItems.size();
initAddIndex=index<0?-Integer.MAX_VALUE:index;
for (int i=0;i<size;i++) {
TreeItem item=sortedItems.get(i);
recuseShow(item);
}
}
private boolean isAnim=false;
/**
* 這個方法還有很 嚴重的bug,無法使用。。
* 設置為0則關閉動畫
* @param animTime
*/
public void enabledAnim(int animTime) {
if(animTime<0){
isAnim=false;
return ;
}
this.animTime=animTime;
isAnim=true;
}
private int initAddIndex;
private void recuseShow(TreeItem item){
View view=item.getView();
addView(view,initAddIndex);
if(item.getParent()!=null){
view.setVisibility(View.GONE);
item.isShow=false;
}else {
view.setVisibility(View.VISIBLE);
item.isShow=true;
}
initAddIndex++;
List<TreeItem> childrens=item.getChildrens();
if(childrens.size()>0){
for (TreeItem it : childrens) {
recuseShow(it);
}
}
}
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
if(hasWindowFocus){
}
}
private void sortItemList(List<TreeItem> items) {
//把items按照層級關系存放,sortedItems只存放頂層的item
sortedItems=new ArrayList<TreeItem>(5);
for (TreeItem item : items) {
if(item.getParent()==null){
sortedItems.add(item);
}else {
item.getParent().getChildrens().add(item);
}
}
}
private int viewIndex=0;
private int animHeight=0;
private void addChild(TreeItem item,boolean isRecurse){
if(item.getChildrens().size()>0){
List<TreeItem> list=item.getChildrens();
for (TreeItem it : list) {
View view=it.getView();
if(it.isShow){
continue;
}
viewIndex++;
view.setVisibility(View.VISIBLE);
it.isShow=true;
if(isAnim){
animHeight-=it.getViewHeight();
}
it.nextIsExpand=true;
if(isRecurse){
addChild(it,true);
}
}
}
}
private int removeCount=0;
private synchronized void removeChild(TreeItem item,boolean isRecurse){
if(item.getChildrens().size()>0){
List<TreeItem> list=item.getChildrens();
for (TreeItem it : list) {
View view=it.getView();
if(!it.isShow){
continue;
}
// removeViewAt(viewIndex);
TranslateAnimation ta=new TranslateAnimation(0, 0, 0, 0);
ta.setFillAfter(true);
ta.setDuration(1000);
view.startAnimation(ta);
// viewIndex++;
removeCount++;
it.isShow=false;
view.setVisibility(View.GONE);
if(isAnim){
animHeight+=it.getViewHeight();
}
if(isRecurse){
removeChild(it,true);
}
}
}
}
private void animAdd(){
TranslateAnimation ta=new TranslateAnimation(
Animation.ABSOLUTE, 0,
Animation.ABSOLUTE, 0,
Animation.ABSOLUTE, animHeight,
Animation.ABSOLUTE, 0);
ta.setFillBefore(true);
// ta.setFillAfter(false);
ta.setDuration(animTime);
for (int i = viewIndex+1; i < getChildCount(); i++) {
View view=getChildAt(i);
view.startAnimation(ta);
}
animHeight=0;
}
private void animRemove(){
TranslateAnimation ta=new TranslateAnimation(
Animation.ABSOLUTE, 0,
Animation.ABSOLUTE, 0,
Animation.ABSOLUTE, animHeight,
Animation.ABSOLUTE, 0);
ta.setFillAfter(false);
ta.setFillBefore(true);
ta.setDuration(animTime);
int startAnimIndex;
startAnimIndex=viewIndex+1;
for (int i = startAnimIndex; i < getChildCount(); i++) {
View view=getChildAt(i);
view.startAnimation(ta);
}
animHeight=0;
}
public void expand(TreeItem item){
viewIndex=indexOfChild(item.getView());
addChild(item,false);
if(isAnim){
animAdd();
}
}
public void expandAllChildren(TreeItem item) {
viewIndex=indexOfChild(item.getView());
addChild(item,true);
if(isAnim){
animAdd();
}
}
public void expandAll(){
if(sortedItems==null){
return ;
}
for (TreeItem item : sortedItems) {
expandAllChildren(item);
}
}
public void contractAllChildren(TreeItem item) {
viewIndex=indexOfChild(item.getView())+1;
removeChild(item,true);
if(isAnim){
animRemove();
}
}
public void contractAll(){
if(sortedItems==null){
return ;
}
for (TreeItem item : sortedItems) {
contractAllChildren(item);
}
}
public void bind(TreeItem item) {
if(item.nextIsExpand){
expand(item);
}else {
contractAllChildren(item);
}
item.nextIsExpand=!item.nextIsExpand;
}
}
TreeItem.java
復制代碼 代碼如下:
package net.memornote.android.ui.view;
import java.util.ArrayList;
import java.util.List;
import android.view.View;
public class TreeItem {
private View view;
private TreeItem parent;
private List<TreeItem> childrens=new ArrayList<TreeItem>(0);
public boolean nextIsExpand=true;
public boolean isShow=false;
private int viewHeight;
public TreeItem(){}
public TreeItem(int id,View view, TreeItem parent) {
super();
this.view = view;
this.parent = parent;
}
public View getView() {
if(view!=null){
view.setPadding(getLevel()*20,0,0,0);
}
return view;
}
public void setView(View view) {
this.view = view;
}
public TreeItem getParent() {
return parent;
}
public void setParent(TreeItem parent) {
this.parent = parent;
}
/**
* 動態獲取該節點的級數
* @return
*/
public int getLevel() {
int level=0;
TreeItem localParent=parent;
while (localParent!=null) {
level++;
localParent=localParent.getParent();
}
return level;
}
public List<TreeItem> getChildrens() {
return childrens;
}
public int getViewHeight() {
if(view==null||view.getHeight()==0){
return viewHeight;
}
return view.getHeight();
}
public void setViewHeight(int viewHeight) {
this.viewHeight = viewHeight;
}
}
測試代碼:
復制代碼 代碼如下:
package net.memornote.android.ui;
import net.memornote.android.R;
import net.memornote.android.ui.fragment.MainFragment;
import net.memornote.android.ui.fragment.MenuFragment;
import com.actionbarsherlock.view.Menu;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;
import com.jeremyfeinstein.slidingmenu.lib.app.SlidingFragmentActivity;
import android.os.Bundle;
import android.view.KeyEvent;
public class MainActivity extends SlidingFragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.slid_content_frame);
tv_notebook=(TreeView) findViewById(R.id.tv_notebook);
List<TreeItem> items=new ArrayList<TreeItem>();
initData(items);
tv_notebook.initData(items, 0);
tv_notebook.enabledAnim(500);
}
//初始化一些測試數據
public void initData(List<TreeItem> items) {
for (int i=0;i<10;i++) {
// TextView tv=new TextView(getActivity());
Button button=new Button(getActivity());
button.setText("item"+i);
final TreeItem item=new TreeItem(0, button, null);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
tv_notebook.bind(item);
}
});
items.add(item);
if(i%2==0){
Button bt1=new Button(getActivity());
bt1.setText("item"+i);
bt1.setClickable(true);
final TreeItem item_1=new TreeItem(0, bt1, null);
bt1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
tv_notebook.bind(item_1);
}
});
item_1.setParent(item);
items.add(item_1);
if(i%4==0){
Button bt_2=new Button(getActivity());
bt_2.setText("item"+i);
bt_2.setClickable(true);
final TreeItem item_2=new TreeItem(0, bt_2, null);
bt_2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
tv_notebook.bind(item_2);
}
});
item_2.setParent(item_1);
items.add(item_2);
}
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
return true;
}
}
首篇作為開始,先講講簡單的反編譯。反編譯通常有幾種目的:互相學習、借來用用、嘿嘿(干你,又分為小干干類似微信紅包,和大干干改別人的apk幫他上架)。因為沒帶kvm回來,m
公司項目需要做推送,我們選擇用小米推送,經過一段時間的摸索,終於可以簡單的使用小米推送了。1.創建賬號登入後 登入後選擇消息推送:2.進入後創建項目,按照步驟創建完後如下
①下載Git工具,配置到Android studio中http://git-scm.com/downloads------------------------------
1.效果圖: 2.項目地址:https://github.com/lynnchurch/HorizontalScrollMenu.git 3.使用示例