printer setting page

chengzhenyu 8 年 前
コミット
b8eb7dfee1

+ 40 - 0
app/src/main/java/ai/pai/lensman/printer/BluetoothDeviceListAdapter.java

@@ -0,0 +1,40 @@
1
+package ai.pai.lensman.printer;
2
+
3
+import android.content.Context;
4
+import android.view.LayoutInflater;
5
+import android.view.View;
6
+import android.view.ViewGroup;
7
+import android.widget.BaseAdapter;
8
+
9
+/**
10
+ * Created by chengzhenyu on 2016/9/1.
11
+ */
12
+
13
+public class BluetoothDeviceListAdapter extends BaseAdapter {
14
+
15
+    private LayoutInflater inflater;
16
+
17
+    public BluetoothDeviceListAdapter(Context context){
18
+        inflater = LayoutInflater.from(context);
19
+    }
20
+
21
+    @Override
22
+    public int getCount() {
23
+        return 0;
24
+    }
25
+
26
+    @Override
27
+    public Object getItem(int i) {
28
+        return null;
29
+    }
30
+
31
+    @Override
32
+    public long getItemId(int i) {
33
+        return 0;
34
+    }
35
+
36
+    @Override
37
+    public View getView(int i, View view, ViewGroup viewGroup) {
38
+        return null;
39
+    }
40
+}

+ 77 - 1
app/src/main/java/ai/pai/lensman/printer/PrinterSettingActivity.java

@@ -2,23 +2,99 @@ package ai.pai.lensman.printer;
2 2
 
3 3
 import android.os.Bundle;
4 4
 import android.support.annotation.Nullable;
5
+import android.widget.ListView;
6
+import android.widget.TextView;
7
+import android.widget.ToggleButton;
8
+
9
+import com.android.views.mergeAdapter.MergeAdapter;
5 10
 
6 11
 import ai.pai.lensman.R;
7 12
 import ai.pai.lensman.base.BaseActivity;
13
+import butterknife.BindView;
8 14
 import butterknife.ButterKnife;
9 15
 
10 16
 /**
11 17
  * Created by chengzhenyu on 2016/8/31.
12 18
  */
13 19
 
14
-public class PrinterSettingActivity extends BaseActivity {
20
+public class PrinterSettingActivity extends BaseActivity implements PrinterSettingContract.View {
21
+
22
+    @BindView(R.id.tv_printer_status)  TextView printerStatusText;
23
+    @BindView(R.id.tv_print_test) TextView printTestText;
24
+    @BindView(R.id.tv_bluetooth_status) TextView bluetoothStatusText;
25
+    @BindView(R.id.tb_bluetooth_switch)   ToggleButton btSwitchToggle;
26
+    @BindView(R.id.list_bt_devices)    ListView btDevicesList;
27
+
28
+    private MergeAdapter mergeAdapter;
29
+    private BluetoothDeviceListAdapter newDeviceAdapter;
30
+    private BluetoothDeviceListAdapter pairedDeviceAdapter;
31
+    private PrinterSettingContract.Presenter presenter;
15 32
 
16 33
     @Override
17 34
     protected void onCreate(@Nullable Bundle savedInstanceState) {
18 35
         super.onCreate(savedInstanceState);
19 36
         setContentView(R.layout.activity_printer_setting);
20 37
         unbinder = ButterKnife.bind(this);
38
+
39
+        mergeAdapter = new MergeAdapter();
40
+        newDeviceAdapter = new BluetoothDeviceListAdapter(this);
41
+        pairedDeviceAdapter = new BluetoothDeviceListAdapter(this);
42
+
43
+        btDevicesList.setAdapter(mergeAdapter);
44
+        mergeAdapter.addAdapter(pairedDeviceAdapter);
45
+        mergeAdapter.addAdapter(newDeviceAdapter);
46
+        presenter = new PrinterSettingPresenter(this,this);
47
+        presenter.start();
48
+    }
49
+
50
+    @Override
51
+    protected void onDestroy() {
52
+        presenter.stop();
53
+        super.onDestroy();
54
+    }
55
+
56
+    @Override
57
+    public void onBluetoothEnabled() {
58
+
59
+    }
60
+
61
+    @Override
62
+    public void onBluetoothDisabled() {
63
+
64
+    }
65
+
66
+    @Override
67
+    public void onPrinterOk() {
68
+
69
+    }
70
+
71
+    @Override
72
+    public void onPrinterError(String error) {
73
+
21 74
     }
22 75
 
76
+    @Override
77
+    public void onPrinterConnected() {
78
+
79
+    }
23 80
 
81
+    @Override
82
+    public void onPrinterDisconnected() {
83
+
84
+    }
85
+
86
+    @Override
87
+    public void onNewDeviceDiscovered() {
88
+
89
+    }
90
+
91
+    @Override
92
+    public void onPrinterTestPageFail() {
93
+
94
+    }
95
+
96
+    @Override
97
+    public void onPairedDeviceDiscovered() {
98
+
99
+    }
24 100
 }

+ 33 - 0
app/src/main/java/ai/pai/lensman/printer/PrinterSettingContract.java

@@ -0,0 +1,33 @@
1
+package ai.pai.lensman.printer;
2
+
3
+/**
4
+ * Created by chengzhenyu on 2016/9/1.
5
+ */
6
+
7
+public class PrinterSettingContract {
8
+
9
+    public interface Presenter{
10
+        void start();
11
+        void stop();
12
+        void queryPrinterStatus();
13
+        void printTestPage();
14
+        void queryBluetoothStatus();
15
+        void enableBluetooth();
16
+        void disableBluetooth();
17
+        void queryPairedDevices();
18
+        void discoverNewDevices();
19
+        void connectPrinter();
20
+    }
21
+
22
+    public interface View{
23
+        void onBluetoothEnabled();
24
+        void onBluetoothDisabled();
25
+        void onPrinterOk();
26
+        void onPrinterError(String error);
27
+        void onPrinterConnected();
28
+        void onPrinterDisconnected();
29
+        void onNewDeviceDiscovered();
30
+        void onPrinterTestPageFail();
31
+        void onPairedDeviceDiscovered();
32
+    }
33
+}

+ 68 - 0
app/src/main/java/ai/pai/lensman/printer/PrinterSettingPresenter.java

@@ -0,0 +1,68 @@
1
+package ai.pai.lensman.printer;
2
+
3
+import android.content.Context;
4
+
5
+/**
6
+ * Created by chengzhenyu on 2016/9/1.
7
+ */
8
+
9
+public class PrinterSettingPresenter implements PrinterSettingContract.Presenter {
10
+
11
+    private Context context;
12
+    private PrinterSettingContract.View view;
13
+
14
+    public PrinterSettingPresenter(Context context, PrinterSettingContract.View view){
15
+        this.view = view;
16
+        this.context = context;
17
+    }
18
+
19
+    @Override
20
+    public void start() {
21
+
22
+    }
23
+
24
+    @Override
25
+    public void stop() {
26
+
27
+    }
28
+
29
+    @Override
30
+    public void queryPrinterStatus() {
31
+
32
+    }
33
+
34
+    @Override
35
+    public void printTestPage() {
36
+
37
+    }
38
+
39
+    @Override
40
+    public void queryBluetoothStatus() {
41
+
42
+    }
43
+
44
+    @Override
45
+    public void enableBluetooth() {
46
+
47
+    }
48
+
49
+    @Override
50
+    public void disableBluetooth() {
51
+
52
+    }
53
+
54
+    @Override
55
+    public void queryPairedDevices() {
56
+
57
+    }
58
+
59
+    @Override
60
+    public void discoverNewDevices() {
61
+
62
+    }
63
+
64
+    @Override
65
+    public void connectPrinter() {
66
+
67
+    }
68
+}

+ 109 - 120
app/src/main/res/layout/activity_printer_setting.xml

@@ -59,133 +59,122 @@
59 59
 
60 60
     </LinearLayout>
61 61
 
62
-    <ScrollView
62
+    <LinearLayout
63 63
         android:layout_width="match_parent"
64 64
         android:layout_height="match_parent"
65
-        android:layout_below="@id/title_bar_with_back_btn">
65
+        android:layout_below="@id/title_bar_with_back_btn"
66
+        android:orientation="vertical">
67
+
68
+        <LinearLayout
69
+            android:layout_width="match_parent"
70
+            android:layout_height="38dp"
71
+            android:gravity="center_vertical"
72
+            android:orientation="horizontal"
73
+            android:paddingLeft="12dp">
74
+
75
+            <TextView
76
+                android:layout_width="wrap_content"
77
+                android:layout_height="wrap_content"
78
+                android:text="@string/printer_status"
79
+                android:textColor="@color/grey"
80
+                android:textSize="14sp" />
81
+        </LinearLayout>
82
+
83
+
84
+        <LinearLayout
85
+            android:layout_width="match_parent"
86
+            android:layout_height="42dp"
87
+            android:background="@color/white"
88
+            android:gravity="center_vertical"
89
+            android:orientation="horizontal"
90
+            android:paddingLeft="12dp">
91
+
92
+            <TextView
93
+                android:id="@+id/tv_printer_status"
94
+                android:layout_width="wrap_content"
95
+                android:layout_height="wrap_content"
96
+                android:text="@string/query_processing"
97
+                android:textColor="@color/dark_grey"
98
+                android:textSize="16sp" />
99
+        </LinearLayout>
100
+
101
+        <LinearLayout
102
+            android:layout_width="match_parent"
103
+            android:layout_height="42dp"
104
+            android:layout_marginTop="1dp"
105
+            android:background="@color/white"
106
+            android:gravity="center_vertical"
107
+            android:orientation="horizontal"
108
+            android:paddingLeft="12dp">
109
+
110
+            <TextView
111
+                android:id="@+id/tv_print_test"
112
+                android:layout_width="wrap_content"
113
+                android:layout_height="wrap_content"
114
+                android:text="@string/print_test"
115
+                android:textColor="@color/dark_grey"
116
+                android:textSize="16sp" />
117
+        </LinearLayout>
118
+
119
+        <LinearLayout
120
+            android:layout_width="match_parent"
121
+            android:layout_height="38dp"
122
+            android:gravity="center_vertical"
123
+            android:orientation="horizontal"
124
+            android:paddingLeft="12dp">
125
+
126
+            <TextView
127
+                android:layout_width="wrap_content"
128
+                android:layout_height="wrap_content"
129
+                android:text="@string/bluetooth_status"
130
+                android:textColor="@color/grey"
131
+                android:textSize="14sp" />
132
+        </LinearLayout>
133
+
66 134
 
67 135
         <LinearLayout
68 136
             android:layout_width="match_parent"
69
-            android:layout_height="wrap_content"
70
-            android:orientation="vertical">
71
-
72
-            <LinearLayout
73
-                android:layout_width="match_parent"
74
-                android:layout_height="38dp"
75
-                android:gravity="center_vertical"
76
-                android:orientation="horizontal"
77
-                android:paddingLeft="12dp">
78
-
79
-                <TextView
80
-                    android:layout_width="wrap_content"
81
-                    android:layout_height="wrap_content"
82
-                    android:text="@string/printer_status"
83
-                    android:textColor="@color/grey"
84
-                    android:textSize="14sp" />
85
-            </LinearLayout>
86
-
87
-
88
-            <LinearLayout
89
-                android:layout_width="match_parent"
90
-                android:layout_height="42dp"
91
-                android:background="@color/white"
92
-                android:gravity="center_vertical"
93
-                android:orientation="horizontal"
94
-                android:paddingLeft="12dp">
95
-
96
-                <TextView
97
-                    android:id="@+id/tv_printer_status"
98
-                    android:layout_width="wrap_content"
99
-                    android:layout_height="wrap_content"
100
-                    android:text="@string/query_processing"
101
-                    android:textColor="@color/dark_grey"
102
-                    android:textSize="16sp" />
103
-            </LinearLayout>
104
-
105
-            <LinearLayout
106
-                android:layout_width="match_parent"
107
-                android:layout_height="42dp"
108
-                android:layout_marginTop="1dp"
109
-                android:background="@color/white"
110
-                android:gravity="center_vertical"
111
-                android:orientation="horizontal"
112
-                android:paddingLeft="12dp">
113
-
114
-                <TextView
115
-                    android:id="@+id/tv_print_test"
116
-                    android:layout_width="wrap_content"
117
-                    android:layout_height="wrap_content"
118
-                    android:text="@string/print_test"
119
-                    android:textColor="@color/dark_grey"
120
-                    android:textSize="16sp" />
121
-            </LinearLayout>
122
-
123
-            <LinearLayout
124
-                android:layout_width="match_parent"
125
-                android:layout_height="38dp"
126
-                android:gravity="center_vertical"
127
-                android:orientation="horizontal"
128
-                android:paddingLeft="12dp">
129
-
130
-                <TextView
131
-                    android:layout_width="wrap_content"
132
-                    android:layout_height="wrap_content"
133
-                    android:text="@string/bluetooth_status"
134
-                    android:textColor="@color/grey"
135
-                    android:textSize="14sp" />
136
-            </LinearLayout>
137
-
138
-
139
-            <LinearLayout
140
-                android:layout_width="match_parent"
141
-                android:layout_height="42dp"
142
-                android:background="@color/white"
143
-                android:gravity="center_vertical"
144
-                android:orientation="horizontal"
145
-                android:paddingLeft="12dp">
146
-
147
-                <TextView
148
-                    android:id="@+id/tv_bluetooth_status"
149
-                    android:layout_width="0dp"
150
-                    android:layout_height="wrap_content"
151
-                    android:layout_weight="1"
152
-                    android:text="@string/bt_is_enabled"
153
-                    android:textColor="@color/dark_grey"
154
-                    android:textSize="16sp" />
155
-
156
-
157
-                <ToggleButton
158
-                    android:id="@+id/tb_bluetooth_switch"
159
-                    android:layout_width="56dp"
160
-                    android:layout_height="19dp"
161
-                    android:layout_marginRight="12dp"
162
-                    android:background="@drawable/toggle_button_selector"
163
-                    android:checked="true"
164
-                    android:gravity="center"
165
-                    android:textColor="@color/white"
166
-                    android:textOff="@null"
167
-                    android:textOn="@null" />
168
-
169
-            </LinearLayout>
170
-
171
-
172
-            <LinearLayout
173
-                android:layout_width="match_parent"
174
-                android:layout_height="38dp"
175
-                android:gravity="center_vertical"
176
-                android:orientation="horizontal"
177
-                android:paddingLeft="12dp">
178
-
179
-                <TextView
180
-                    android:layout_width="wrap_content"
181
-                    android:layout_height="wrap_content"
182
-                    android:text="@string/paired_devices"
183
-                    android:textColor="@color/grey"
184
-                    android:textSize="14sp" />
185
-            </LinearLayout>
137
+            android:layout_height="42dp"
138
+            android:background="@color/white"
139
+            android:gravity="center_vertical"
140
+            android:orientation="horizontal"
141
+            android:paddingLeft="12dp">
142
+
143
+            <TextView
144
+                android:id="@+id/tv_bluetooth_status"
145
+                android:layout_width="0dp"
146
+                android:layout_height="wrap_content"
147
+                android:layout_weight="1"
148
+                android:text="@string/bt_is_enabled"
149
+                android:textColor="@color/dark_grey"
150
+                android:textSize="16sp" />
151
+
152
+
153
+            <ToggleButton
154
+                android:id="@+id/tb_bluetooth_switch"
155
+                android:layout_width="56dp"
156
+                android:layout_height="19dp"
157
+                android:layout_marginRight="12dp"
158
+                android:background="@drawable/toggle_button_selector"
159
+                android:checked="true"
160
+                android:gravity="center"
161
+                android:textColor="@color/white"
162
+                android:textOff="@null"
163
+                android:textOn="@null" />
186 164
 
187 165
         </LinearLayout>
188
-    </ScrollView>
166
+
167
+        <ListView
168
+            android:id="@+id/list_bt_devices"
169
+            android:layout_width="match_parent"
170
+            android:layout_height="match_parent"
171
+            android:background="@color/white"
172
+            android:paddingLeft="12dp"
173
+            android:paddingRight="6dp"
174
+            android:listSelector="@color/transparent"
175
+            android:cacheColorHint="@color/transparent"/>
176
+
177
+    </LinearLayout>
189 178
 
190 179
 
191 180
 </RelativeLayout>

+ 23 - 0
app/src/main/res/layout/layout_bt_device_list_item.xml

@@ -0,0 +1,23 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
+    android:orientation="vertical" android:layout_width="match_parent"
4
+    android:layout_height="wrap_content"
5
+    android:paddingTop="4dp"
6
+    android:paddingBottom="4dp">
7
+
8
+    <TextView
9
+        android:id="@+id/tv_device_name"
10
+        android:layout_width="wrap_content"
11
+        android:layout_height="wrap_content"
12
+        android:textSize="14sp"
13
+        android:textColor="@color/dark_grey"/>
14
+
15
+    <TextView
16
+        android:id="@+id/tv_device_mac"
17
+        android:layout_width="wrap_content"
18
+        android:layout_height="wrap_content"
19
+        android:paddingTop="3dp"
20
+        android:textSize="12sp"
21
+        android:textColor="@color/grey"/>
22
+
23
+</LinearLayout>

+ 480 - 0
views/src/main/java/com/android/views/mergeAdapter/MergeAdapter.java

@@ -0,0 +1,480 @@
1
+/***
2
+  Copyright (c) 2008-2009 CommonsWare, LLC
3
+  Portions (c) 2009 Google, Inc.
4
+  
5
+  Licensed under the Apache License, Version 2.0 (the "License"); you may
6
+  not use this file except in compliance with the License. You may obtain
7
+  a copy of the License at
8
+    http://www.apache.org/licenses/LICENSE-2.0
9
+  Unless required by applicable law or agreed to in writing, software
10
+  distributed under the License is distributed on an "AS IS" BASIS,
11
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+  See the License for the specific language governing permissions and
13
+  limitations under the License.
14
+ */
15
+
16
+package com.android.views.mergeAdapter;
17
+
18
+import android.database.DataSetObserver;
19
+import android.view.View;
20
+import android.view.ViewGroup;
21
+import android.widget.BaseAdapter;
22
+import android.widget.ListAdapter;
23
+import android.widget.SectionIndexer;
24
+
25
+import java.util.ArrayList;
26
+import java.util.Collections;
27
+import java.util.List;
28
+
29
+/**
30
+ * Adapter that merges multiple child adapters and views
31
+ * into a single contiguous whole.
32
+ * 
33
+ * Adapters used as pieces within MergeAdapter must have
34
+ * view type IDs monotonically increasing from 0. Ideally,
35
+ * adapters also have distinct ranges for their row ids, as
36
+ * returned by getItemId().
37
+ * 
38
+ */
39
+public class MergeAdapter extends BaseAdapter implements SectionIndexer {
40
+  protected PieceStateRoster pieces=new PieceStateRoster();
41
+
42
+  /**
43
+   * Stock constructor, simply chaining to the superclass.
44
+   */
45
+  public MergeAdapter() {
46
+    super();
47
+  }
48
+
49
+  /**
50
+   * Adds a new adapter to the roster of things to appear in
51
+   * the aggregate list.
52
+   * 
53
+   * @param adapter
54
+   *          Source for row views for this section
55
+   */
56
+  public void addAdapter(ListAdapter adapter) {
57
+    pieces.add(adapter);
58
+    adapter.registerDataSetObserver(new CascadeDataSetObserver());
59
+  }
60
+
61
+  /**
62
+   * Adds a new View to the roster of things to appear in
63
+   * the aggregate list.
64
+   * 
65
+   * @param view
66
+   *          Single view to add
67
+   */
68
+  public void addView(View view) {
69
+    addView(view, false);
70
+  }
71
+
72
+  /**
73
+   * Adds a new View to the roster of things to appear in
74
+   * the aggregate list.
75
+   * 
76
+   * @param view
77
+   *          Single view to add
78
+   * @param enabled
79
+   *          false if views are disabled, true if enabled
80
+   */
81
+  public void addView(View view, boolean enabled) {
82
+    ArrayList<View> list=new ArrayList<View>(1);
83
+
84
+    list.add(view);
85
+
86
+    addViews(list, enabled);
87
+  }
88
+
89
+  /**
90
+   * Adds a list of views to the roster of things to appear
91
+   * in the aggregate list.
92
+   * 
93
+   * @param views
94
+   *          List of views to add
95
+   */
96
+  public void addViews(List<View> views) {
97
+    addViews(views, false);
98
+  }
99
+
100
+  /**
101
+   * Adds a list of views to the roster of things to appear
102
+   * in the aggregate list.
103
+   * 
104
+   * @param views
105
+   *          List of views to add
106
+   * @param enabled
107
+   *          false if views are disabled, true if enabled
108
+   */
109
+  public void addViews(List<View> views, boolean enabled) {
110
+    if (enabled) {
111
+      addAdapter(new EnabledSackAdapter(views));
112
+    }
113
+    else {
114
+      addAdapter(new SackOfViewsAdapter(views));
115
+    }
116
+  }
117
+
118
+  /**
119
+   * Get the data item associated with the specified
120
+   * position in the data set.
121
+   * 
122
+   * @param position
123
+   *          Position of the item whose data we want
124
+   */
125
+  @Override
126
+  public Object getItem(int position) {
127
+    for (ListAdapter piece : getPieces()) {
128
+      int size=piece.getCount();
129
+
130
+      if (position < size) {
131
+        return(piece.getItem(position));
132
+      }
133
+
134
+      position-=size;
135
+    }
136
+
137
+    return(null);
138
+  }
139
+
140
+  /**
141
+   * Get the adapter associated with the specified position
142
+   * in the data set.
143
+   * 
144
+   * @param position
145
+   *          Position of the item whose adapter we want
146
+   */
147
+  public ListAdapter getAdapter(int position) {
148
+    for (ListAdapter piece : getPieces()) {
149
+      int size=piece.getCount();
150
+
151
+      if (position < size) {
152
+        return(piece);
153
+      }
154
+
155
+      position-=size;
156
+    }
157
+
158
+    return(null);
159
+  }
160
+
161
+  /**
162
+   * How many items are in the data set represented by this
163
+   * Adapter.
164
+   */
165
+  @Override
166
+  public int getCount() {
167
+    int total=0;
168
+
169
+    for (ListAdapter piece : getPieces()) {
170
+      total+=piece.getCount();
171
+    }
172
+
173
+    return(total);
174
+  }
175
+
176
+  /**
177
+   * Returns the number of types of Views that will be
178
+   * created by getView().
179
+   */
180
+  @Override
181
+  public int getViewTypeCount() {
182
+    int total=0;
183
+
184
+    for (PieceState piece : pieces.getRawPieces()) {
185
+      total+=piece.adapter.getViewTypeCount();
186
+    }
187
+
188
+    return(Math.max(total, 1)); // needed for
189
+                                // setListAdapter() before
190
+                                // content add'
191
+  }
192
+
193
+  /**
194
+   * Get the type of View that will be created by getView()
195
+   * for the specified item.
196
+   * 
197
+   * @param position
198
+   *          Position of the item whose data we want
199
+   */
200
+  @Override
201
+  public int getItemViewType(int position) {
202
+    int typeOffset=0;
203
+    int result=-1;
204
+
205
+    for (PieceState piece : pieces.getRawPieces()) {
206
+      if (piece.isActive) {
207
+        int size=piece.adapter.getCount();
208
+  
209
+        if (position < size) {
210
+          result=typeOffset + piece.adapter.getItemViewType(position);
211
+          break;
212
+        }
213
+  
214
+        position-=size;
215
+      }
216
+      
217
+      typeOffset+=piece.adapter.getViewTypeCount();
218
+    }
219
+
220
+    return(result);
221
+  }
222
+
223
+  /**
224
+   * Are all items in this ListAdapter enabled? If yes it
225
+   * means all items are selectable and clickable.
226
+   */
227
+  @Override
228
+  public boolean areAllItemsEnabled() {
229
+    return(false);
230
+  }
231
+
232
+  /**
233
+   * Returns true if the item at the specified position is
234
+   * not a separator.
235
+   * 
236
+   * @param position
237
+   *          Position of the item whose data we want
238
+   */
239
+  @Override
240
+  public boolean isEnabled(int position) {
241
+    for (ListAdapter piece : getPieces()) {
242
+      int size=piece.getCount();
243
+
244
+      if (position < size) {
245
+        return(piece.isEnabled(position));
246
+      }
247
+
248
+      position-=size;
249
+    }
250
+
251
+    return(false);
252
+  }
253
+
254
+  /**
255
+   * Get a View that displays the data at the specified
256
+   * position in the data set.
257
+   * 
258
+   * @param position
259
+   *          Position of the item whose data we want
260
+   * @param convertView
261
+   *          View to recycle, if not null
262
+   * @param parent
263
+   *          ViewGroup containing the returned View
264
+   */
265
+  @Override
266
+  public View getView(int position, View convertView, ViewGroup parent) {
267
+    for (ListAdapter piece : getPieces()) {
268
+      int size=piece.getCount();
269
+
270
+      if (position < size) {
271
+
272
+        return(piece.getView(position, convertView, parent));
273
+      }
274
+
275
+      position-=size;
276
+    }
277
+
278
+    return(null);
279
+  }
280
+
281
+  /**
282
+   * Get the row id associated with the specified position
283
+   * in the list.
284
+   * 
285
+   * @param position
286
+   *          Position of the item whose data we want
287
+   */
288
+  @Override
289
+  public long getItemId(int position) {
290
+    for (ListAdapter piece : getPieces()) {
291
+      int size=piece.getCount();
292
+
293
+      if (position < size) {
294
+        return(piece.getItemId(position));
295
+      }
296
+
297
+      position-=size;
298
+    }
299
+
300
+    return(-1);
301
+  }
302
+
303
+  @Override
304
+  public int getPositionForSection(int section) {
305
+    int position=0;
306
+
307
+    for (ListAdapter piece : getPieces()) {
308
+      if (piece instanceof SectionIndexer) {
309
+        Object[] sections=((SectionIndexer)piece).getSections();
310
+        int numSections=0;
311
+
312
+        if (sections != null) {
313
+          numSections=sections.length;
314
+        }
315
+
316
+        if (section < numSections) {
317
+          return(position + ((SectionIndexer)piece).getPositionForSection(section));
318
+        }
319
+        else if (sections != null) {
320
+          section-=numSections;
321
+        }
322
+      }
323
+
324
+      position+=piece.getCount();
325
+    }
326
+
327
+    return(0);
328
+  }
329
+
330
+  @Override
331
+  public int getSectionForPosition(int position) {
332
+    int section=0;
333
+
334
+    for (ListAdapter piece : getPieces()) {
335
+      int size=piece.getCount();
336
+
337
+      if (position < size) {
338
+        if (piece instanceof SectionIndexer) {
339
+          return(section + ((SectionIndexer)piece).getSectionForPosition(position));
340
+        }
341
+
342
+        return(0);
343
+      }
344
+      else {
345
+        if (piece instanceof SectionIndexer) {
346
+          Object[] sections=((SectionIndexer)piece).getSections();
347
+
348
+          if (sections != null) {
349
+            section+=sections.length;
350
+          }
351
+        }
352
+      }
353
+
354
+      position-=size;
355
+    }
356
+
357
+    return(0);
358
+  }
359
+
360
+  @Override
361
+  public Object[] getSections() {
362
+    ArrayList<Object> sections=new ArrayList<Object>();
363
+
364
+    for (ListAdapter piece : getPieces()) {
365
+      if (piece instanceof SectionIndexer) {
366
+        Object[] curSections=((SectionIndexer)piece).getSections();
367
+
368
+        if (curSections != null) {
369
+          Collections.addAll(sections, curSections);
370
+        }
371
+      }
372
+    }
373
+
374
+    if (sections.size() == 0) {
375
+      return(new String[0]);
376
+    }
377
+
378
+    return(sections.toArray(new Object[0]));
379
+  }
380
+  
381
+  public void setActive(ListAdapter adapter, boolean isActive) {
382
+    pieces.setActive(adapter, isActive);
383
+    notifyDataSetChanged();
384
+  }
385
+
386
+  public void setActive(View v, boolean isActive) {
387
+    pieces.setActive(v, isActive);
388
+    notifyDataSetChanged();
389
+  }
390
+
391
+  protected List<ListAdapter> getPieces() {
392
+    return(pieces.getPieces());
393
+  }
394
+
395
+  private static class PieceState {
396
+    ListAdapter adapter;
397
+    boolean isActive=true;
398
+
399
+    PieceState(ListAdapter adapter, boolean isActive) {
400
+      this.adapter=adapter;
401
+      this.isActive=isActive;
402
+    }
403
+  }
404
+
405
+  private static class PieceStateRoster {
406
+    protected ArrayList<PieceState> pieces=new ArrayList<PieceState>();
407
+    protected ArrayList<ListAdapter> active=null;
408
+
409
+    void add(ListAdapter adapter) {
410
+      pieces.add(new PieceState(adapter, true));
411
+    }
412
+    
413
+    void setActive(ListAdapter adapter, boolean isActive) {
414
+      for (PieceState state : pieces) {
415
+        if (state.adapter==adapter) {
416
+          state.isActive=isActive;
417
+          active=null;
418
+          break;
419
+        }
420
+      }
421
+    }
422
+    
423
+    void setActive(View v, boolean isActive) {
424
+      for (PieceState state : pieces) {
425
+        if (state.adapter instanceof SackOfViewsAdapter &&
426
+            ((SackOfViewsAdapter)state.adapter).hasView(v)) {
427
+          state.isActive=isActive;
428
+          active=null;
429
+          break;
430
+        }
431
+      }
432
+    }
433
+    
434
+    List<PieceState> getRawPieces() {
435
+      return(pieces);
436
+    }
437
+
438
+    List<ListAdapter> getPieces() {
439
+      if (active == null) {
440
+        active=new ArrayList<ListAdapter>();
441
+
442
+        for (PieceState state : pieces) {
443
+          if (state.isActive) {
444
+            active.add(state.adapter);
445
+          }
446
+        }
447
+      }
448
+
449
+      return(active);
450
+    }
451
+  }
452
+
453
+  private static class EnabledSackAdapter extends SackOfViewsAdapter {
454
+    public EnabledSackAdapter(List<View> views) {
455
+      super(views);
456
+    }
457
+
458
+    @Override
459
+    public boolean areAllItemsEnabled() {
460
+      return(true);
461
+    }
462
+
463
+    @Override
464
+    public boolean isEnabled(int position) {
465
+      return(true);
466
+    }
467
+  }
468
+
469
+  private class CascadeDataSetObserver extends DataSetObserver {
470
+    @Override
471
+    public void onChanged() {
472
+      notifyDataSetChanged();
473
+    }
474
+
475
+    @Override
476
+    public void onInvalidated() {
477
+      notifyDataSetInvalidated();
478
+    }
479
+  }
480
+}

+ 178 - 0
views/src/main/java/com/android/views/mergeAdapter/SackOfViewsAdapter.java

@@ -0,0 +1,178 @@
1
+/***
2
+  Copyright (c) 2008-2009 CommonsWare, LLC
3
+  Portions (c) 2009 Google, Inc.
4
+  
5
+  Licensed under the Apache License, Version 2.0 (the "License"); you may
6
+  not use this file except in compliance with the License. You may obtain
7
+  a copy of the License at
8
+    http://www.apache.org/licenses/LICENSE-2.0
9
+  Unless required by applicable law or agreed to in writing, software
10
+  distributed under the License is distributed on an "AS IS" BASIS,
11
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+  See the License for the specific language governing permissions and
13
+  limitations under the License.
14
+*/    
15
+
16
+package com.android.views.mergeAdapter;
17
+
18
+import android.view.View;
19
+import android.view.ViewGroup;
20
+import android.widget.BaseAdapter;
21
+
22
+import java.util.ArrayList;
23
+import java.util.List;
24
+
25
+/**
26
+ * Adapter that simply returns row views from a list.
27
+ *
28
+ * If you supply a size, you must implement newView(), to
29
+ * create a required view. The adapter will then cache these
30
+ * views.
31
+ *
32
+ * If you supply a list of views in the constructor, that
33
+ * list will be used directly. If any elements in the list
34
+ * are null, then newView() will be called just for those
35
+ * slots.
36
+ *
37
+ * Subclasses may also wish to override areAllItemsEnabled()
38
+ * (default: false) and isEnabled() (default: false), if some
39
+ * of their rows should be selectable.
40
+ *
41
+ * It is assumed each view is unique, and therefore will not
42
+ * get recycled.
43
+ *
44
+ * Note that this adapter is not designed for long lists. It
45
+ * is more for screens that should behave like a list. This
46
+ * is particularly useful if you combine this with other
47
+ * adapters (e.g., SectionedAdapter) that might have an
48
+ * arbitrary number of rows, so it all appears seamless.
49
+ */
50
+public class SackOfViewsAdapter extends BaseAdapter {
51
+  private List<View> views=null;
52
+
53
+  /**
54
+    * Constructor creating an empty list of views, but with
55
+    * a specified count. Subclasses must override newView().
56
+    */
57
+  public SackOfViewsAdapter(int count) {
58
+    super();
59
+    
60
+    views=new ArrayList<View>(count);
61
+    
62
+    for (int i=0;i<count;i++) {
63
+      views.add(null);
64
+    }
65
+  }
66
+
67
+  /**
68
+    * Constructor wrapping a supplied list of views.
69
+    * Subclasses must override newView() if any of the elements
70
+    * in the list are null.
71
+    */
72
+  public SackOfViewsAdapter(List<View> views) {
73
+    super();
74
+    
75
+    this.views=views;
76
+  }
77
+
78
+  /**
79
+    * Get the data item associated with the specified
80
+    * position in the data set.
81
+    * @param position Position of the item whose data we want
82
+    */
83
+  @Override
84
+  public Object getItem(int position) {
85
+    return(views.get(position));
86
+  }
87
+
88
+  /**
89
+    * How many items are in the data set represented by this
90
+    * Adapter.
91
+    */
92
+  @Override
93
+  public int getCount() {
94
+    return(views.size());
95
+  }
96
+
97
+  /**
98
+    * Returns the number of types of Views that will be
99
+    * created by getView().
100
+    */
101
+  @Override
102
+  public int getViewTypeCount() {
103
+    return(getCount());
104
+  }
105
+
106
+  /**
107
+    * Get the type of View that will be created by getView()
108
+    * for the specified item.
109
+    * @param position Position of the item whose data we want
110
+    */
111
+  @Override
112
+  public int getItemViewType(int position) {
113
+    return(position);
114
+  }
115
+
116
+  /**
117
+    * Are all items in this ListAdapter enabled? If yes it
118
+    * means all items are selectable and clickable.
119
+    */
120
+  @Override
121
+  public boolean areAllItemsEnabled() {
122
+    return(false);
123
+  }
124
+
125
+  /**
126
+    * Returns true if the item at the specified position is
127
+    * not a separator.
128
+    * @param position Position of the item whose data we want
129
+    */
130
+  @Override
131
+  public boolean isEnabled(int position) {
132
+    return(false);
133
+  }
134
+
135
+  /**
136
+    * Get a View that displays the data at the specified
137
+    * position in the data set.
138
+    * @param position Position of the item whose data we want
139
+    * @param convertView View to recycle, if not null
140
+    * @param parent ViewGroup containing the returned View
141
+    */
142
+  @Override
143
+  public View getView(int position, View convertView,
144
+                      ViewGroup parent) {
145
+    View result=views.get(position);
146
+    
147
+    if (result==null) {
148
+      result=newView(position, parent);
149
+      views.set(position, result);
150
+    }
151
+    
152
+    return(result);
153
+  }
154
+
155
+  /**
156
+    * Get the row id associated with the specified position
157
+    * in the list.
158
+    * @param position Position of the item whose data we want
159
+    */
160
+  @Override
161
+  public long getItemId(int position) {
162
+    return(position);
163
+  }
164
+  
165
+  public boolean hasView(View v) {
166
+    return(views.contains(v));
167
+  }
168
+  
169
+  /**
170
+    * Create a new View to go into the list at the specified
171
+    * position.
172
+    * @param position Position of the item whose data we want
173
+    * @param parent ViewGroup containing the returned View
174
+    */
175
+  protected View newView(int position, ViewGroup parent) {
176
+    throw new RuntimeException("You must override newView()!");
177
+  }
178
+}