Skip to content

Commit 38e965f

Browse files
committed
Refactor listview to use RecyclerView and add an example
1 parent a58fc8e commit 38e965f

File tree

13 files changed

+470
-140
lines changed

13 files changed

+470
-140
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# enaml-native 4.5.0
2+
3+
- Refactor ListView to use RecyclerAdapter and support container
4+
operations (append, insert, remove, pop)
5+
- Fix issue with builtin event loop with Python 3
6+
17
# enaml-native 4.4.2
28

39
- Support screen orientation changes
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package com.codelv.enamlnative.adapters;
2+
3+
import android.support.v7.widget.RecyclerView;
4+
import android.view.View;
5+
import android.view.ViewGroup;
6+
import android.widget.FrameLayout;
7+
8+
import java.util.ArrayList;
9+
10+
/**
11+
* Created by jrm on 5/3/18.
12+
*/
13+
public class BridgedRecyclerAdapter extends RecyclerView.Adapter<BridgedRecyclerAdapter.ViewHolder> {
14+
public static final String TAG = "BridgedRecyclerAdapter";
15+
int mCount;
16+
int mRecycleIndex = -1; // Incremented before first use
17+
RecyclerView mListView;
18+
BridgedListAdapterListener mListener;
19+
final ArrayList<View> mRecycleViews = new ArrayList<>();
20+
21+
// Provide a reference to the views for each data item
22+
// Complex data items may need more than one view per item, and
23+
// you provide access to all the views for a data item in a view holder
24+
public static class ViewHolder extends RecyclerView.ViewHolder {
25+
// each data item is just a string in this case
26+
public View mView;
27+
public int mIndex;
28+
public ViewHolder(View v, int i) {
29+
super(v);
30+
mView = v;
31+
mIndex = i;
32+
}
33+
}
34+
35+
public BridgedRecyclerAdapter(RecyclerView listView) {
36+
super();
37+
mListView = listView;
38+
}
39+
40+
// Create new views (invoked by the layout manager)
41+
@Override
42+
public BridgedRecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
43+
int viewType) {
44+
// create a new view
45+
mRecycleIndex += 1;
46+
if (mRecycleIndex==mRecycleViews.size()) {
47+
mRecycleIndex = 0;
48+
}
49+
View v = mRecycleViews.get(mRecycleIndex);
50+
ViewGroup vp = (ViewGroup) v.getParent();
51+
if (vp!=null) {
52+
vp.removeView(v);
53+
}
54+
FrameLayout frame = new FrameLayout(parent.getContext());
55+
frame.addView(v);
56+
return new ViewHolder(frame, mRecycleIndex);
57+
}
58+
59+
60+
// Replace the contents of a view (invoked by the layout manager)
61+
@Override
62+
public void onBindViewHolder(ViewHolder holder, int position) {
63+
mListener.onRecycleView(holder.mIndex, position);
64+
}
65+
66+
public void setRecyleListener(BridgedListAdapterListener listener) {
67+
mListener = listener;
68+
// mListView.addOnScrollListener(new AbsListView.OnScrollListener() {
69+
// @Override
70+
// public void onScrollStateChanged(AbsListView view, int scrollState) {
71+
// if (mListener!=null) {
72+
// mListener.onScrollStateChanged(view, scrollState);
73+
// }
74+
// }
75+
//
76+
// @Override
77+
// public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
78+
// if (mListener!=null) {
79+
// // Notify if # of visible items changed
80+
// if (mVisibileCount!=visibleItemCount) {
81+
// mListener.onVisibleCountChanged(visibleItemCount, totalItemCount);
82+
// }
83+
// mVisibileCount = visibleItemCount;
84+
// }
85+
// }
86+
// });
87+
}
88+
89+
/**
90+
* Set the number of items this adapter has.
91+
*/
92+
public void setItemCount(int count) {
93+
mCount = count;
94+
}
95+
96+
@Override
97+
public int getItemCount() {
98+
return mCount;
99+
}
100+
101+
/**
102+
* Set the views that this adapter will cycle through.
103+
* @param views
104+
*/
105+
public void setRecycleViews(View... views) {
106+
for (View view: views) {
107+
mRecycleViews.add(view);
108+
}
109+
}
110+
111+
public void addRecyleView(View view) {
112+
mRecycleViews.add(view);
113+
}
114+
115+
public void removeRecycleView(View view) {
116+
mRecycleViews.remove(view);
117+
}
118+
119+
public void clearRecycleViews() {
120+
mRecycleViews.clear();
121+
}
122+
123+
124+
interface BridgedListAdapterListener {
125+
void onRecycleView(int index, int position);
126+
}
127+
}

docs/apis/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ APIs
66
:maxdepth: 2
77

88
InputMethodManager <android_inputmethodmanager>
9-
Location <android_location>
109
LocationManager <android_locationmanager>
10+
NotificationManager <android_notificationmanager>
1111
Sensor <android_sensor>
1212
SensorManager <android_sensormanager>
1313
UsbDevice <android_usbdevice>

docs/widgets/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Widgets
3333
LinearLayout <linearlayout>
3434
ListItem <listitem>
3535
ListView <listview>
36+
Notification <notification>
3637
PagerFragment <pagerfragment>
3738
PagerTabStrip <pagertabstrip>
3839
PagerTitleStrip <pagertitlestrip>

docs/widgets/listitem.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
ListItem
33
========================================
44

5-
No example available.
5+
.. literalinclude:: ../../examples/list_view.enaml
6+
:language: python
67

78
Declaration
89
----------------------------

docs/widgets/listview.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
ListView
33
========================================
44

5-
No example available.
5+
.. literalinclude:: ../../examples/list_view.enaml
6+
:language: python
67

78
Declaration
89
----------------------------

docs/widgets/swiperefreshlayout.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
SwipeRefreshLayout
33
========================================
44

5-
No example available.
5+
.. literalinclude:: ../../examples/swipe_refresh_layout.enaml
6+
:language: python
67

78
Declaration
89
----------------------------

docs/widgets/timepicker.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
TimePicker
33
========================================
44

5-
No example available.
5+
.. literalinclude:: ../../examples/time_picker.enaml
6+
:language: python
67

78
Declaration
89
----------------------------

examples/list_view.enaml

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
"""
2+
3+
Demonstrates using a ListView
4+
5+
"""
6+
from atom.api import Atom, Unicode, List, Bool
7+
from enamlnative.core.api import *
8+
from enamlnative.widgets.api import *
9+
10+
from iconify import material
11+
12+
class AppState(Atom):
13+
_instance = None
14+
15+
search = Unicode()
16+
data = List()
17+
show_search = Bool()
18+
19+
def _default_data(self):
20+
return list(material.ICONS.keys())
21+
22+
@classmethod
23+
def instance(cls):
24+
""" Use this to access the state """
25+
if cls._instance is None:
26+
cls._instance = cls()
27+
return cls._instance
28+
29+
def __init__(self):
30+
""" Make it a singleton """
31+
if AppState._instance is not None:
32+
raise RuntimeError("Only one AppState should exist!")
33+
super(AppState, self).__init__()
34+
35+
36+
enamldef ContentView(LinearLayout): drawer:
37+
attr state = AppState.instance()
38+
orientation = 'vertical'
39+
AppBarLayout:
40+
height = "wrap_content"
41+
width = 'match_parent'
42+
Toolbar:
43+
Flexbox:
44+
justify_content = "space_between"
45+
align_items = "center"
46+
TextView:
47+
text = "Icons"
48+
visible << not state.show_search
49+
text_color = "#fff"
50+
text_size = 18
51+
clickable = True
52+
EditText:
53+
width = 'match_parent'
54+
visible << state.show_search
55+
placeholder = "Filter"
56+
text_color = "#fff"
57+
editor_actions = True
58+
text := state.search
59+
editor_action :: state.show_search = False
60+
Icon:
61+
text = "{md-search}"
62+
visible << not state.show_search
63+
padding = (10, 10, 10, 10)
64+
text_size = 32
65+
text_color = "#fff"
66+
clickable = True
67+
clicked :: state.show_search = True
68+
69+
ListView: list_view:
70+
items << [s for s in state.data
71+
if not state.search or state.search in s]
72+
Looper:
73+
iterable = range(30)
74+
ListItem:
75+
attr icon << item or ''
76+
LinearLayout:
77+
orientation = 'vertical'
78+
Flexbox:
79+
align_items = 'center'
80+
padding = (10, 10, 10, 10)
81+
Icon:
82+
text << "{%s}"%icon
83+
text_size = 32
84+
width = 50
85+
TextView:
86+
text << "{}".format(icon)
87+
padding = (10, 0, 10, 10)
88+
View:
89+
background_color = '#ccc'
90+
height = 1

meta.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package:
22
name: enaml-native
3-
version: 4.4.2
3+
version: 4.5.0
44

55
requirements:
66
build:
@@ -13,7 +13,7 @@ requirements:
1313
- ios-msgpack # [osx]
1414

1515
build:
16-
number: 4
16+
number: 5
1717
noarch: generic
1818
include_recipe: False
1919

0 commit comments

Comments
 (0)