Skip to content

Commit e5f51c3

Browse files
Bogdan MelnychukBogdan Melnychuk
Bogdan Melnychuk
authored and
Bogdan Melnychuk
committed
Editable tree implementation
1 parent 1163845 commit e5f51c3

File tree

12 files changed

+311
-61
lines changed

12 files changed

+311
-61
lines changed

app/src/main/java/com/unnamed/b/atv/sample/fragment/FolderStructureFragment.java

+7-10
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,17 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa
4444

4545
TreeNode myDocuments = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_folder, "My Documents"));
4646
TreeNode downloads = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_folder, "Downloads"));
47-
TreeNode file1 = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_drive_file, "File 1"));
48-
TreeNode file2 = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_drive_file, "File 2"));
49-
TreeNode file3 = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_drive_file, "File 3"));
50-
TreeNode file4 = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_drive_file, "File 4"));
47+
TreeNode file1 = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_drive_file, "Folder 1"));
48+
TreeNode file2 = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_drive_file, "Folder 2"));
49+
TreeNode file3 = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_drive_file, "Folder 3"));
50+
TreeNode file4 = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_drive_file, "Folder 4"));
5151
fillDownloadsFolder(downloads);
5252
downloads.addChildren(file1, file2, file3, file4);
5353

5454
TreeNode myMedia = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_photo_library, "Photos"));
55-
TreeNode photo1 = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_photo, "Photo 1"));
56-
TreeNode photo2 = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_photo, "Photo 2"));
57-
TreeNode photo3 = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_photo, "Photo 3"));
55+
TreeNode photo1 = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_photo, "Folder 1"));
56+
TreeNode photo2 = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_photo, "Folder 2"));
57+
TreeNode photo3 = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_photo, "Folder 3"));
5858
myMedia.addChildren(photo1, photo2, photo3);
5959

6060
myDocuments.addChild(downloads);
@@ -115,9 +115,6 @@ private void fillDownloadsFolder(TreeNode node) {
115115
public void onClick(TreeNode node, Object value) {
116116
IconTreeItemHolder.IconTreeItem item = (IconTreeItemHolder.IconTreeItem) value;
117117
statusBar.setText("Last clicked: " + item.text);
118-
if (node.isLeaf()) {
119-
Toast.makeText(getActivity(), item.text, Toast.LENGTH_SHORT).show();
120-
}
121118
}
122119
};
123120

app/src/main/java/com/unnamed/b/atv/sample/fragment/SelectableTreeFragment.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import com.unnamed.b.atv.model.TreeNode;
1212
import com.unnamed.b.atv.sample.R;
1313
import com.unnamed.b.atv.sample.holder.IconTreeItemHolder;
14+
import com.unnamed.b.atv.sample.holder.ProfileHolder;
1415
import com.unnamed.b.atv.sample.holder.SelectableHeaderHolder;
1516
import com.unnamed.b.atv.sample.holder.SelectableItemHolder;
1617
import com.unnamed.b.atv.view.AndroidTreeView;
@@ -73,6 +74,11 @@ public void onClick(View v) {
7374

7475
TreeNode root = TreeNode.root();
7576

77+
TreeNode s1 = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_sd_storage, "Storage1")).setViewHolder(new ProfileHolder(getActivity()));
78+
TreeNode s2 = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_sd_storage, "Storage2")).setViewHolder(new ProfileHolder(getActivity()));
79+
s1.setSelectable(false);
80+
s2.setSelectable(false);
81+
7682
TreeNode folder1 = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_folder, "Folder 1")).setViewHolder(new SelectableHeaderHolder(getActivity()));
7783
TreeNode folder2 = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_folder, "Folder 2")).setViewHolder(new SelectableHeaderHolder(getActivity()));
7884
TreeNode folder3 = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_folder, "Folder 3")).setViewHolder(new SelectableHeaderHolder(getActivity()));
@@ -81,8 +87,10 @@ public void onClick(View v) {
8187
fillFolder(folder2);
8288
fillFolder(folder3);
8389

90+
s1.addChildren(folder1, folder2);
91+
s2.addChildren(folder3);
8492

85-
root.addChildren(folder1, folder2, folder3);
93+
root.addChildren(s1, s2);
8694

8795
tView = new AndroidTreeView(getActivity(), root);
8896
containerView.addView(tView.getView());

app/src/main/java/com/unnamed/b/atv/sample/holder/IconTreeItemHolder.java

+21-5
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public IconTreeItemHolder(Context context) {
2121
}
2222

2323
@Override
24-
public View createNodeView(TreeNode node, IconTreeItem value) {
24+
public View createNodeView(final TreeNode node, IconTreeItem value) {
2525
final LayoutInflater inflater = LayoutInflater.from(context);
2626
final View view = inflater.inflate(R.layout.layout_icon_node, null, false);
2727
tvValue = (TextView) view.findViewById(R.id.node_value);
@@ -31,9 +31,27 @@ public View createNodeView(TreeNode node, IconTreeItem value) {
3131
iconView.setIconText(context.getResources().getString(value.icon));
3232

3333
arrowView = (PrintView) view.findViewById(R.id.arrow_icon);
34-
if (node.isLeaf()) {
35-
arrowView.setVisibility(View.INVISIBLE);
34+
35+
view.findViewById(R.id.btn_addFolder).setOnClickListener(new View.OnClickListener() {
36+
@Override
37+
public void onClick(View v) {
38+
TreeNode newFolder = new TreeNode(new IconTreeItemHolder.IconTreeItem(R.string.ic_folder, "New Folder"));
39+
getTreeView().addNode(node, newFolder);
40+
}
41+
});
42+
43+
view.findViewById(R.id.btn_delete).setOnClickListener(new View.OnClickListener() {
44+
@Override
45+
public void onClick(View v) {
46+
getTreeView().removeNode(node);
47+
}
48+
});
49+
50+
//if My computer
51+
if (node.getLevel() == 1) {
52+
view.findViewById(R.id.btn_delete).setVisibility(View.GONE);
3653
}
54+
3755
return view;
3856
}
3957

@@ -50,7 +68,5 @@ public IconTreeItem(int icon, String text) {
5068
this.icon = icon;
5169
this.text = text;
5270
}
53-
5471
}
55-
5672
}

app/src/main/java/com/unnamed/b/atv/sample/holder/SelectableHeaderHolder.java

+3
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ public View createNodeView(final TreeNode node, IconTreeItemHolder.IconTreeItem
4444
@Override
4545
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
4646
node.setSelected(isChecked);
47+
for (TreeNode n : node.getChildren()) {
48+
getTreeView().selectNode(n, isChecked);
49+
}
4750
}
4851
});
4952
nodeSelector.setChecked(node.isSelected());

app/src/main/res/layout/layout_icon_node.xml

+29-7
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,40 @@
3636
android:textSize="16sp"
3737
android:layout_marginLeft="10dp"
3838
android:layout_toRightOf="@+id/icon"
39-
android:layout_toLeftOf="@+id/total"
39+
android:layout_toLeftOf="@+id/buttonsContainer"
4040
android:id="@+id/node_value"
4141
android:layout_width="wrap_content"
4242
android:layout_height="wrap_content" />
4343

44-
<TextView
45-
android:layout_alignParentRight="true"
46-
android:textSize="16sp"
44+
45+
<LinearLayout
46+
android:id="@+id/buttonsContainer"
47+
android:layout_centerVertical="true"
4748
android:layout_marginLeft="10dp"
4849
android:layout_marginRight="10dp"
49-
android:layout_centerVertical="true"
50-
android:id="@+id/total"
50+
android:layout_alignParentRight="true"
5151
android:layout_width="wrap_content"
52-
android:layout_height="wrap_content" />
52+
android:layout_height="wrap_content">
53+
54+
<com.github.johnkil.print.PrintView
55+
android:id="@+id/btn_addFolder"
56+
android:layout_width="wrap_content"
57+
android:layout_height="wrap_content"
58+
android:padding="5dp"
59+
app:iconSize="20dp"
60+
app:iconColor="#99cc00"
61+
app:iconFont="fonts/material-icon-font.ttf"
62+
app:iconText="@string/ic_add" />
63+
64+
65+
<com.github.johnkil.print.PrintView
66+
android:padding="5dp"
67+
android:id="@+id/btn_delete"
68+
android:layout_width="wrap_content"
69+
android:layout_height="wrap_content"
70+
app:iconSize="20dp"
71+
app:iconColor="#ff4444"
72+
app:iconFont="fonts/material-icon-font.ttf"
73+
app:iconText="@string/ic_close" />
74+
</LinearLayout>
5375
</RelativeLayout>

build.gradle

+9
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,17 @@ buildscript {
1212
}
1313
}
1414

15+
def isReleaseBuild() {
16+
return version.contains("SNAPSHOT") == false
17+
}
18+
1519
allprojects {
20+
version = VERSION_NAME
21+
group = GROUP
22+
1623
repositories {
1724
jcenter()
1825
}
1926
}
27+
28+
apply plugin: 'android-reporting'

gradle.properties

+14-2
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,21 @@
1919

2020
VERSION_NAME=1.1.0
2121
VERSION_CODE=2
22-
GROUP=com.unnamed.b
22+
2323

2424
ANDROID_BUILD_MIN_SDK_VERSION=11
2525
ANDROID_BUILD_TARGET_SDK_VERSION=21
2626
ANDROID_BUILD_SDK_VERSION=21
27-
ANDROID_BUILD_TOOLS_VERSION=21.1.2
27+
ANDROID_BUILD_TOOLS_VERSION=21.1.2
28+
29+
GROUP=com.github.bmelnychuk
30+
POM_DESCRIPTION=Tree View implementation for android
31+
POM_URL=https://github.com/bmelnychuk/AndroidTreeView
32+
POM_SCM_URL=https://github.com/bmelnychuk/AndroidTreeView
33+
POM_SCM_CONNECTION=scm:[email protected]:bmelnychuk/AndroidTreeView.git
34+
POM_SCM_DEV_CONNECTION=scm:[email protected]:bmelnychuk/AndroidTreeView.git
35+
POM_LICENCE_NAME=The Apache Software License, Version 2.0
36+
POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
37+
POM_LICENCE_DIST=repo
38+
POM_DEVELOPER_ID=unnamed_b
39+
POM_DEVELOPER_NAME=Bogdan Melnychuk

library/build.gradle

+2
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,5 @@ dependencies {
2121
compile fileTree(dir: 'libs', include: ['*.jar'])
2222
compile 'com.android.support:appcompat-v7:21.0.3'
2323
}
24+
25+
apply from: '../maven_push.gradle'

library/gradle.properties

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Project-wide Gradle settings.
2+
3+
# IDE (e.g. Android Studio) users:
4+
# Gradle settings configured through the IDE *will override*
5+
# any settings specified in this file.
6+
7+
# For more details on how to configure your build environment visit
8+
# http://www.gradle.org/docs/current/userguide/build_environment.html
9+
10+
# Specifies the JVM arguments used for the daemon process.
11+
# The setting is particularly useful for tweaking memory settings.
12+
# Default value: -Xmx10248m -XX:MaxPermSize=256m
13+
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14+
15+
# When configured, Gradle will run in incubating parallel mode.
16+
# This option should only be used with decoupled projects. More details, visit
17+
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18+
# org.gradle.parallel=true
19+
20+
POM_NAME=AndroidTreeView
21+
POM_ARTIFACT_ID=atv
22+
POM_PACKAGING=aar

library/src/main/java/com/unnamed/b/atv/model/TreeNode.java

+40-6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import android.view.ViewGroup;
66

77
import com.unnamed.b.atv.R;
8+
import com.unnamed.b.atv.view.AndroidTreeView;
89
import com.unnamed.b.atv.view.TreeNodeWrapperView;
910

1011
import java.util.ArrayList;
@@ -21,14 +22,17 @@ public class TreeNode {
2122
private int mId;
2223
private TreeNode mParent;
2324
private boolean mSelected;
25+
private boolean mSelectable = true;
2426
private final List<TreeNode> children;
2527
private BaseNodeViewHolder mViewHolder;
2628
private TreeNodeClickListener mListener;
2729
private Object mValue;
2830
private boolean mExpanded;
2931

3032
public static TreeNode root() {
31-
return new TreeNode(null);
33+
TreeNode root = new TreeNode(null);
34+
root.setSelectable(false);
35+
return root;
3236
}
3337

3438
public TreeNode(Object value) {
@@ -38,6 +42,7 @@ public TreeNode(Object value) {
3842

3943
public TreeNode addChild(TreeNode childNode) {
4044
childNode.mParent = this;
45+
//TODO think about id generation
4146
childNode.mId = size();
4247
children.add(childNode);
4348
return this;
@@ -57,6 +62,16 @@ public TreeNode addChildren(Collection<TreeNode> nodes) {
5762
return this;
5863
}
5964

65+
public int deleteChild(TreeNode child) {
66+
for (int i = 0; i < children.size(); i++) {
67+
if (child.mId == children.get(i).mId) {
68+
children.remove(i);
69+
return i;
70+
}
71+
}
72+
return -1;
73+
}
74+
6075
public List<TreeNode> getChildren() {
6176
return Collections.unmodifiableList(children);
6277
}
@@ -95,7 +110,19 @@ public void setSelected(boolean selected) {
95110
}
96111

97112
public boolean isSelected() {
98-
return mSelected;
113+
if (mSelectable) {
114+
return mSelected;
115+
} else {
116+
return false;
117+
}
118+
}
119+
120+
public void setSelectable(boolean selectable) {
121+
mSelectable = selectable;
122+
}
123+
124+
public boolean isSelectable() {
125+
return mSelectable;
99126
}
100127

101128
public String getPath() {
@@ -180,6 +207,7 @@ public interface TreeNodeClickListener {
180207
}
181208

182209
public static abstract class BaseNodeViewHolder<E> {
210+
protected AndroidTreeView tView;
183211
protected TreeNode mNode;
184212
private View mView;
185213
protected int containerStyle;
@@ -201,6 +229,14 @@ public View getView() {
201229
return mView;
202230
}
203231

232+
public void setTreeViev(AndroidTreeView treeViev) {
233+
this.tView = treeViev;
234+
}
235+
236+
public AndroidTreeView getTreeView() {
237+
return tView;
238+
}
239+
204240
public void setContainerStyle(int style) {
205241
containerStyle = style;
206242
}
@@ -213,8 +249,8 @@ public ViewGroup getNodeItemsView() {
213249
return (ViewGroup) getView().findViewById(R.id.node_items);
214250
}
215251

216-
public boolean childrenInitialized() {
217-
return getNodeItemsView().getChildCount() == mNode.size();
252+
public boolean isInitialized() {
253+
return mView != null;
218254
}
219255

220256
public int getContainerStyle() {
@@ -228,8 +264,6 @@ public void toggle(boolean active) {
228264
// empty
229265
}
230266

231-
;
232-
233267
public void toggleSelectionMode(boolean editModeEnabled) {
234268
// empty
235269
}

0 commit comments

Comments
 (0)