> 41
42
    //用于在吸顶布局中保存viewType的key。
43
    private final int VIEW_TAG_TYPE = -101;
44
45
    //用于在吸顶布局中保存ViewHolder的key。
46
    private final int VIEW_TAG_HOLDER = -102;
47
48
    //记录当前吸顶的组。
49
    private int mCurrentStickyGroup = -1;
50
51
    //是否吸顶。
52
    private boolean isSticky = true;
53
54
    //是否已经注册了adapter刷新监听
55
    private boolean isRegisterDataObserver = false;
56
57
    public StickyHeaderLayout(@NonNull Context context) {
58
        super(context);
59
        mContext = context;
60
    }
61
62
    public StickyHeaderLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
63
        super(context, attrs);
64
        mContext = context;
65
    }
66
67
    public StickyHeaderLayout(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
68
        super(context, attrs, defStyleAttr);
69
        mContext = context;
70
    }
71
72
    @Override
73
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
74
        if (getChildCount() > 0 || !(child instanceof RecyclerView)) {
75
            //外界只能向StickyHeaderLayout添加一个RecyclerView,而且只能添加RecyclerView。
76
            throw new IllegalArgumentException("StickyHeaderLayout can host only one direct child --> RecyclerView");
77
        }
78
        super.addView(child, index, params);
79
        mRecyclerView = (RecyclerView) child;
80
        addOnScrollListener();
81
        addStickyLayout();
82
    }
83
84
    /**
85
     * 添加滚动监听
86
     */
87
    private void addOnScrollListener() {
88
        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
89
            @Override
90
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
91
                // 在滚动的时候,需要不断的更新吸顶布局。
92
                if (isSticky) {
93
                    updateStickyView(false);
94
                }
95
            }
96
        });
97
    }
98
99
    /**
100
     * 添加吸顶容器
101
     */
102
    private void addStickyLayout() {
103
        mStickyLayout = new FrameLayout(mContext);
104
        LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
105
                LayoutParams.WRAP_CONTENT);
106
        mStickyLayout.setLayoutParams(lp);
107
        super.addView(mStickyLayout, 1, lp);
108
    }
109
110
    /**
111
     * 强制更新吸顶布局。
112
     */
113
    public void updateStickyView() {
114
        updateStickyView(true);
115
    }
116
117
    /**
118
     * 更新吸顶布局。
119
     *
120
     * @param imperative 是否强制更新。
121
     */
122
    private void updateStickyView(boolean imperative) {
123
        RecyclerView.Adapter adapter = mRecyclerView.getAdapter();
124
        //只有RecyclerView的adapter是GroupedRecyclerViewAdapter的时候,才会添加吸顶布局。
125
        if (adapter instanceof GroupedRecyclerViewAdapter) {
126
            GroupedRecyclerViewAdapter gAdapter = (GroupedRecyclerViewAdapter) adapter;
127
            registerAdapterDataObserver(gAdapter);
128
            //获取列表显示的第一个项。
129
            int firstVisibleItem = getFirstVisibleItem();
130
            //通过显示的第一个项的position获取它所在的组。
131
            int groupPosition = gAdapter.getGroupPositionForPosition(firstVisibleItem);
132
133
            //如果当前吸顶的组头不是我们要吸顶的组头,就更新吸顶布局。这样做可以避免频繁的更新吸顶布局。
134
            if (imperative || mCurrentStickyGroup != groupPosition) {
135
                mCurrentStickyGroup = groupPosition;
136
                if (stickyHeaderPositionListener != null) {
137
                    stickyHeaderPositionListener.onHeaderPositionChange(mCurrentStickyGroup);
138
                }
139
                //通过groupPosition获取当前组的组头position。这个组头就是我们需要吸顶的布局。
140
                int groupHeaderPosition = gAdapter.getPositionForGroupHeader(groupPosition);
141
                if (groupHeaderPosition != -1) {
142
                    //获取吸顶布局的viewType。
143
                    int viewType = gAdapter.getItemViewType(groupHeaderPosition);
144
145
                    //如果当前的吸顶布局的类型和我们需要的一样,就直接获取它的ViewHolder,否则就回收。
146
                    BaseViewHolder holder = recycleStickyView(viewType);
147
148
                    //标志holder是否是从当前吸顶布局取出来的。
149
                    boolean flag = holder != null;
150
151
                    if (holder == null) {
152
                        //从缓存池中获取吸顶布局。
153
                        holder = getStickyViewByType(viewType);
154
                    }
155
156
                    if (holder == null) {
157
                        //如果没有从缓存池中获取到吸顶布局,则通过GroupedRecyclerViewAdapter创建。
158
                        holder = (BaseViewHolder) gAdapter.onCreateViewHolder(mStickyLayout, viewType);
159
                        holder.itemView.setTag(VIEW_TAG_TYPE, viewType);
160
                        holder.itemView.setTag(VIEW_TAG_HOLDER, holder);
161
                    }
162
163
                    //通过GroupedRecyclerViewAdapter更新吸顶布局的数据。
164
                    //这样可以保证吸顶布局的显示效果跟列表中的组头保持一致。
165
                    gAdapter.onBindViewHolder(holder, groupHeaderPosition);
166
167
                    //如果holder不是从当前吸顶布局取出来的,就需要把吸顶布局添加到容器里。
168
                    if (!flag) {
169
                        mStickyLayout.addView(holder.itemView);
170
                    }
171
                } else {
172
                    //如果当前组没有组头,则不显示吸顶布局。
173
                    //回收旧的吸顶布局。
174
                    recycle();
175
                }
176
            }
177
178
            //这是是处理第一次打开时,吸顶布局已经添加到StickyLayout,但StickyLayout的高依然为0的情况。
179
            if (mStickyLayout.getChildCount() > 0 && mStickyLayout.getHeight() == 0) {
180
                mStickyLayout.requestLayout();
181
            }
182
183
            //设置mStickyLayout的Y偏移量。
184
            mStickyLayout.setTranslationY(calculateOffset(gAdapter, firstVisibleItem, groupPosition + 1));
185
        }
186
    }
187
188
    /**
189
     * 注册adapter刷新监听
190
     */
191
    private void registerAdapterDataObserver(GroupedRecyclerViewAdapter adapter) {
192
        if (!isRegisterDataObserver) {
193
            isRegisterDataObserver = true;
194
            adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
195
                @Override
196
                public void onChanged() {
197
                    updateStickyViewDelayed();
198
                }
199
200
                @Override
201
                public void onItemRangeChanged(int positionStart, int itemCount) {
202
                    updateStickyViewDelayed();
203
                }
204
205
                @Override
206
                public void onItemRangeInserted(int positionStart, int itemCount) {
207
                    updateStickyViewDelayed();
208
                }
209
210
                @Override
211
                public void onItemRangeRemoved(int positionStart, int itemCount) {
212
                    updateStickyViewDelayed();
213
                }
214
215
            });
216
        }
217
    }
218
219
    private void updateStickyViewDelayed() {
220
        postDelayed(new Runnable() {
221
            @Override
222
            public void run() {
223
                updateStickyView(true);
224
            }
225
        }, 64);
226
    }
227
228
    /**
229
     * 判断是否需要先回收吸顶布局,如果要回收,则回收吸顶布局并返回null。
230
     * 如果不回收,则返回吸顶布局的ViewHolder。
231
     * 这样做可以避免频繁的添加和移除吸顶布局。
232
     *
233
     * @param viewType
234
     * @return
235
     */
236
    private BaseViewHolder recycleStickyView(int viewType) {
237
        if (mStickyLayout.getChildCount() > 0) {
238
            View view = mStickyLayout.getChildAt(0);
239
            int type = (int) view.getTag(VIEW_TAG_TYPE);
240
            if (type == viewType) {
241
                return (BaseViewHolder) view.getTag(VIEW_TAG_HOLDER);
242
            } else {
243
                recycle();
244
            }
245
        }
246
        return null;
247
    }
248
249
    /**
250
     * 回收并移除吸顶布局
251
     */
252
    private void recycle() {
253
        if (mStickyLayout.getChildCount() > 0) {
254
            View view = mStickyLayout.getChildAt(0);
255
            mStickyViews.put((int) (view.getTag(VIEW_TAG_TYPE)),
256
                    (BaseViewHolder) (view.getTag(VIEW_TAG_HOLDER)));
257
            mStickyLayout.removeAllViews();
258
        }
259
    }
260
261
    /**
262
     * 从缓存池中获取吸顶布局
263
     *
264
     * @param viewType 吸顶布局的viewType
265
     * @return
266
     */
267
    private BaseViewHolder getStickyViewByType(int viewType) {
268
        return mStickyViews.get(viewType);
269
    }
270
271
    /**
272
     * 计算StickyLayout的偏移量。因为如果下一个组的组头顶到了StickyLayout,
273
     * 就要把StickyLayout顶上去,直到下一个组的组头变成吸顶布局。否则会发生两个组头重叠的情况。
274
     *
275
     * @param gAdapter
276
     * @param firstVisibleItem 当前列表显示的第一个项。
277
     * @param groupPosition    下一个组的组下标。
278
     * @return 返回偏移量。
279
     */
280
    private float calculateOffset(GroupedRecyclerViewAdapter gAdapter, int firstVisibleItem, int groupPosition) {
281
        int groupHeaderPosition = gAdapter.getPositionForGroupHeader(groupPosition);
282
        if (groupHeaderPosition != -1) {
283
            int index = groupHeaderPosition - firstVisibleItem;
284
            if (mRecyclerView.getChildCount() > index) {
285
                //获取下一个组的组头的itemView。
286
                View view = mRecyclerView.getChildAt(index);
287
                float off = view.getY() - mStickyLayout.getHeight();
288
                if (off < 0) {
289
                    return off;
290
                }
291
            }
292
        }
293
        return 0;
294
    }
295
296
    /**
297
     * 获取当前第一个显示的item .
298
     */
299
    private int getFirstVisibleItem() {
300
        int firstVisibleItem = -1;
301
        RecyclerView.LayoutManager layout = mRecyclerView.getLayoutManager();
302
        if (layout != null) {
303
            if (layout instanceof GridLayoutManager) {
304
                firstVisibleItem = ((GridLayoutManager) layout).findFirstVisibleItemPosition();
305
            } else if (layout instanceof LinearLayoutManager) {
306
                firstVisibleItem = ((LinearLayoutManager) layout).findFirstVisibleItemPosition();
307
            } else if (layout instanceof StaggeredGridLayoutManager) {
308
                int[] firstPositions = new int[((StaggeredGridLayoutManager) layout).getSpanCount()];
309
                ((StaggeredGridLayoutManager) layout).findFirstVisibleItemPositions(firstPositions);
310
                firstVisibleItem = getMin(firstPositions);
311
            }
312
        }
313
        return firstVisibleItem;
314
    }
315
316
    private int getMin(int[] arr) {
317
        int min = arr[0];
318
        for (int x = 1; x < arr.length; x++) {
319
            if (arr[x] < min)
320
                min = arr[x];
321
        }
322
        return min;
323
    }
324
325
    /**
326
     * 是否吸顶
327
     *
328
     * @return
329
     */
330
    public boolean isSticky() {
331
        return isSticky;
332
    }
333
334
    /**
335
     * 设置是否吸顶。
336
     *
337
     * @param sticky
338
     */
339
    public void setSticky(boolean sticky) {
340
        if (isSticky != sticky) {
341
            isSticky = sticky;
342
            if (mStickyLayout != null) {
343
                if (isSticky) {
344
                    mStickyLayout.setVisibility(VISIBLE);
345
                    updateStickyView(false);
346
                } else {
347
                    recycle();
348
                    mStickyLayout.setVisibility(GONE);
349
                }
350
            }
351
        }
352
    }
353
354
    @Override
355
    protected int computeVerticalScrollOffset() {
356
        if (mRecyclerView != null) {
357
            try {
358
                Method method = View.class.getDeclaredMethod("computeVerticalScrollOffset");
359
                method.setAccessible(true);
360
                return (int) method.invoke(mRecyclerView);
361
            } catch (Exception e) {
362
                e.printStackTrace();
363
            }
364
        }
365
        return super.computeVerticalScrollOffset();
366
    }
367
368
369
    @Override
370
    protected int computeVerticalScrollRange() {
371
        if (mRecyclerView != null) {
372
            try {
373
                Method method = View.class.getDeclaredMethod("computeVerticalScrollRange");
374
                method.setAccessible(true);
375
                return (int) method.invoke(mRecyclerView);
376
            } catch (Exception e) {
377
                e.printStackTrace();
378
            }
379
        }
380
        return super.computeVerticalScrollRange();
381
    }
382
383
    @Override
384
    protected int computeVerticalScrollExtent() {
385
        if (mRecyclerView != null) {
386
            try {
387
                Method method = View.class.getDeclaredMethod("computeVerticalScrollExtent");
388
                method.setAccessible(true);
389
                return (int) method.invoke(mRecyclerView);
390
            } catch (Exception e) {
391
                e.printStackTrace();
392
            }
393
        }
394
        return super.computeVerticalScrollExtent();
395
    }
396
397
    @Override
398
    public void scrollBy(int x, int y) {
399
        if (mRecyclerView != null) {
400
            mRecyclerView.scrollBy(x, y);
401
        } else {
402
            super.scrollBy(x, y);
403
        }
404
    }
405
406
    @Override
407
    public void scrollTo(int x, int y) {
408
        if (mRecyclerView != null) {
409
            mRecyclerView.scrollTo(x, y);
410
        } else {
411
            super.scrollTo(x, y);
412
        }
413
    }
414
415
    private StickyHeaderPositionListener stickyHeaderPositionListener;
416
417
    /**
418
     * 添加监听,监控头部视图滑动到顶部对应的头部视图的position
419
     * add by huyuguo
420
     */
421
    public void setStickyHeaderPositionListener(StickyHeaderPositionListener listener) {
422
        stickyHeaderPositionListener = listener;
423
    }
424
425
    /**
426
     * 滑动到指定位置
427
     * https://blog.csdn.net/shanshan_1117/article/details/78780137
428
     * @param position
429
     */
430
    public void scrollToPosition(int position) {
431
        if (mRecyclerView != null) {
432
            mRecyclerView.scrollToPosition(position);
433
            LinearLayoutManager linearLayoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
434
            linearLayoutManager.scrollToPositionWithOffset(position, 0);
435
            updateStickyView();
436
        }
437
    }
438
439
}

+ 5 - 0
app/src/main/java/com/donkingliang/groupedadapter/widget/StickyHeaderPositionListener.java

@ -0,0 +1,5 @@
1
package com.donkingliang.groupedadapter.widget;
2
3
public interface StickyHeaderPositionListener {
4
    public void onHeaderPositionChange(int groupPosition);
5
}

+ 120 - 0
app/src/main/java/com/electric/chargingpile/activity/CarBrandActivity.java

@ -0,0 +1,120 @@
1
package com.electric.chargingpile.activity;
2
3
import androidx.appcompat.app.AppCompatActivity;
4
import androidx.recyclerview.widget.LinearLayoutManager;
5
import androidx.recyclerview.widget.RecyclerView;
6
7
import android.content.Intent;
8
import android.os.Bundle;
9
import android.view.View;
10
import android.widget.TextView;
11
12
import com.donkingliang.groupedadapter.adapter.GroupedRecyclerViewAdapter;
13
import com.donkingliang.groupedadapter.holder.BaseViewHolder;
14
import com.donkingliang.groupedadapter.widget.StickyHeaderLayout;
15
import com.donkingliang.groupedadapter.widget.StickyHeaderPositionListener;
16
import com.electric.chargingpile.R;
17
import com.electric.chargingpile.adapter.CarBrandGroupedListAdapter;
18
import com.electric.chargingpile.entity.CarBrandGroupEntity;
19
import com.electric.chargingpile.entity.CarCompanyEntity;
20
import com.electric.chargingpile.event.CarBrandEvent;
21
import com.electric.chargingpile.event.CarCompanyEvent;
22
import com.electric.chargingpile.util.BarColorUtil;
23
import com.electric.chargingpile.view.LetterSideView;
24
25
import org.greenrobot.eventbus.EventBus;
26
27
import java.util.ArrayList;
28
29
public class CarBrandActivity extends AppCompatActivity implements View.OnClickListener {
30
31
    private LetterSideView letter_side_view;
32
    private TextView text_view_dialog;
33
    private StickyHeaderLayout sticky_header_layout;
34
    private RecyclerView recycler_view;
35
    private CarBrandGroupedListAdapter adapter;
36
    private ArrayList<CarBrandGroupEntity> groups;
37
38
    @Override
39
    protected void onCreate(Bundle savedInstanceState) {
40
        super.onCreate(savedInstanceState);
41
        setContentView(R.layout.activity_car_brand);
42
        BarColorUtil.initStatusBarColor(CarBrandActivity.this);
43
        initViews();
44
    }
45
46
    private void initViews() {
47
48
        CarBrandEvent event = EventBus.getDefault().removeStickyEvent(CarBrandEvent.class);
49
        if (event != null) {
50
            groups = event.getGroups();
51
        }
52
53
        findViewById(R.id.iv_back).setOnClickListener(this::onClick);
54
        letter_side_view = findViewById(R.id.letter_side_view);
55
        text_view_dialog = findViewById(R.id.text_view_dialog);
56
        letter_side_view.setTextView(text_view_dialog);
57
        letter_side_view.setOnTouchLetterChangedListener(new LetterSideView.OnTouchLetterChangedListener() {
58
            @Override
59
            public void onTouchLetterChanged(String s) {
60
61
            }
62
63
            @Override
64
            public void onTouchLetterPosition(int position) {
65
                int count = 0;
66
                for (int i = 0; i < groups.size(); i++) {
67
                    if (i < position) {
68
                        count += groups.get(i).getBrandList().size();
69
                    } else {
70
                        break;
71
                    }
72
                }
73
                count += position;
74
                sticky_header_layout.scrollToPosition(count);
75
            }
76
        });
77
78
        String[] letters = new String[groups.size()];
79
        for (int i = 0; i < groups.size(); i++) {
80
            letters[i] = groups.get(i).getInitial();
81
        }
82
        LetterSideView.letters = letters;
83
        letter_side_view.setVisibility(View.VISIBLE);
84
85
        recycler_view = (RecyclerView) findViewById(R.id.recycler_view);
86
        sticky_header_layout = (StickyHeaderLayout) findViewById(R.id.sticky_header_layout);
87
88
        recycler_view.setLayoutManager(new LinearLayoutManager(this));
89
        adapter = new CarBrandGroupedListAdapter(this, groups);
90
        adapter.setOnChildClickListener(new GroupedRecyclerViewAdapter.OnChildClickListener() {
91
            @Override
92
            public void onChildClick(GroupedRecyclerViewAdapter adapter, BaseViewHolder holder, int groupPosition, int childPosition) {
93
                ArrayList<CarCompanyEntity> companyList = groups.get(groupPosition).getBrandList().get(childPosition).getCompanyList();
94
                EventBus.getDefault().postSticky(new CarCompanyEvent(companyList));
95
                startActivity(new Intent(CarBrandActivity.this, CarModelActivity.class));
96
            }
97
        });
98
99
        recycler_view.setAdapter(adapter);
100
        // 设置是否吸顶。
101
        sticky_header_layout.setSticky(true);
102
        // 头部滑动到视图顶部时,监听头部对应的groupPosition
103
        sticky_header_layout.setStickyHeaderPositionListener(new StickyHeaderPositionListener() {
104
            @Override
105
            public void onHeaderPositionChange(int groupPosition) {
106
                letter_side_view.setPosition(groupPosition);
107
            }
108
        });
109
110
    }
111
112
    @Override
113
    public void onClick(View v) {
114
        switch (v.getId()) {
115
            case R.id.iv_back:
116
                finish();
117
                break;
118
        }
119
    }
120
}

+ 75 - 0
app/src/main/java/com/electric/chargingpile/activity/CarModelActivity.java

@ -0,0 +1,75 @@
1
package com.electric.chargingpile.activity;
2
3
import androidx.appcompat.app.AppCompatActivity;
4
import androidx.recyclerview.widget.LinearLayoutManager;
5
import androidx.recyclerview.widget.RecyclerView;
6
7
import android.content.Intent;
8
import android.os.Bundle;
9
import android.view.View;
10
11
import com.donkingliang.groupedadapter.adapter.GroupedRecyclerViewAdapter;
12
import com.donkingliang.groupedadapter.holder.BaseViewHolder;
13
import com.donkingliang.groupedadapter.widget.StickyHeaderLayout;
14
import com.electric.chargingpile.R;
15
import com.electric.chargingpile.adapter.CarModelGroupedListAdapter;
16
import com.electric.chargingpile.entity.CarCompanyEntity;
17
import com.electric.chargingpile.entity.CarSeriesEntity;
18
import com.electric.chargingpile.event.CarCompanyEvent;
19
import com.electric.chargingpile.event.CarSerieEvent;
20
import com.electric.chargingpile.util.BarColorUtil;
21
22
import org.greenrobot.eventbus.EventBus;
23
24
import java.util.ArrayList;
25
26
public class CarModelActivity extends AppCompatActivity implements View.OnClickListener {
27
28
    private RecyclerView recycler_view;
29
    private StickyHeaderLayout sticky_header_layout;
30
    private CarModelGroupedListAdapter adapter;
31
    private ArrayList<CarCompanyEntity> companyList;
32
33
    @Override
34
    protected void onCreate(Bundle savedInstanceState) {
35
        super.onCreate(savedInstanceState);
36
        setContentView(R.layout.activity_car_model);
37
        BarColorUtil.initStatusBarColor(CarModelActivity.this);
38
        initViews();
39
    }
40
41
    private void initViews() {
42
        findViewById(R.id.nav_bar).setOnClickListener(this::onClick);
43
        CarCompanyEvent event = EventBus.getDefault().removeStickyEvent(CarCompanyEvent.class);
44
        if (event != null) {
45
            companyList = event.getCompanyList();
46
        }
47
48
        recycler_view = (RecyclerView) findViewById(R.id.recycler_view);
49
        sticky_header_layout = (StickyHeaderLayout) findViewById(R.id.sticky_header_layout);
50
51
        recycler_view.setLayoutManager(new LinearLayoutManager(this));
52
        adapter = new CarModelGroupedListAdapter(this, companyList);
53
        adapter.setOnChildClickListener(new GroupedRecyclerViewAdapter.OnChildClickListener() {
54
            @Override
55
            public void onChildClick(GroupedRecyclerViewAdapter adapter, BaseViewHolder holder, int groupPosition, int childPosition) {
56
                CarSeriesEntity carSeriesEntity = companyList.get(groupPosition).getSerieslist().get(childPosition);
57
                EventBus.getDefault().post(new CarSerieEvent(carSeriesEntity));
58
                startActivity(new Intent(CarModelActivity.this, CarOwnerCertificateActivity.class));
59
            }
60
        });
61
62
        recycler_view.setAdapter(adapter);
63
        // 设置是否吸顶。
64
        sticky_header_layout.setSticky(true);
65
    }
66
67
    @Override
68
    public void onClick(View v) {
69
        switch (v.getId()) {
70
            case R.id.nav_bar:
71
                finish();
72
                break;
73
        }
74
    }
75
}

+ 385 - 0
app/src/main/java/com/electric/chargingpile/activity/CarOwnerCertificateActivity.java

@ -0,0 +1,385 @@
1
package com.electric.chargingpile.activity;
2
3
import androidx.appcompat.app.AppCompatActivity;
4
import androidx.constraintlayout.widget.ConstraintLayout;
5
6
import android.app.ProgressDialog;
7
import android.content.Intent;
8
import android.graphics.Bitmap;
9
import android.graphics.BitmapFactory;
10
import android.graphics.Matrix;
11
import android.graphics.drawable.Drawable;
12
import android.net.Uri;
13
import android.os.Bundle;
14
import android.view.View;
15
import android.view.WindowManager;
16
import android.widget.Button;
17
import android.widget.ImageView;
18
import android.widget.TextView;
19
import android.widget.Toast;
20
21
import com.bumptech.glide.Glide;
22
import com.electric.chargingpile.R;
23
import com.electric.chargingpile.entity.CarBrandGroupEntity;
24
import com.electric.chargingpile.entity.CarSeriesEntity;
25
import com.electric.chargingpile.event.CarBrandEvent;
26
import com.electric.chargingpile.event.CarSerieEvent;
27
import com.electric.chargingpile.util.BarColorUtil;
28
import com.electric.chargingpile.util.FileUtils;
29
import com.electric.chargingpile.util.JsonUtils;
30
import com.electric.chargingpile.util.LoadingDialog;
31
import com.electric.chargingpile.util.ToastUtil;
32
import com.electric.chargingpile.view.TextImageView;
33
import com.electric.chargingpile.view.xrichtext.SDCardUtil;
34
import com.google.gson.Gson;
35
import com.google.gson.reflect.TypeToken;
36
import com.zhihu.matisse.Matisse;
37
import com.zhihu.matisse.MimeType;
38
import com.zhihu.matisse.engine.impl.GlideEngine;
39
import com.zhihu.matisse.internal.entity.CaptureStrategy;
40
import com.zhy.http.okhttp.OkHttpUtils;
41
import com.zhy.http.okhttp.callback.StringCallback;
42
43
import org.greenrobot.eventbus.EventBus;
44
import org.greenrobot.eventbus.Subscribe;
45
import org.greenrobot.eventbus.ThreadMode;
46
47
import java.io.ByteArrayOutputStream;
48
import java.io.File;
49
import java.util.ArrayList;
50
import java.util.List;
51
52
import io.reactivex.Observable;
53
import io.reactivex.ObservableEmitter;
54
import io.reactivex.ObservableOnSubscribe;
55
import io.reactivex.Observer;
56
import io.reactivex.android.schedulers.AndroidSchedulers;
57
import io.reactivex.disposables.Disposable;
58
import io.reactivex.schedulers.Schedulers;
59
import okhttp3.Call;
60
61
/**
62
 * 车主认证
63
 */
64
65
public class CarOwnerCertificateActivity extends AppCompatActivity implements View.OnClickListener {
66
67
    private static final int RC_ALBUM_PERM = 123;
68
    private static final int REQUEST_CODE_CHOOSE = 342;
69
    private Bitmap insertBitmap;
70
    private String u_path = "";
71
    private int drivingLicenseType = 1;
72
    private ProgressDialog insertDialog;
73
74
    private TextView nav_title;
75
    private Button submit_btn;
76
    private TextImageView driving_license_type_first;
77
    private TextImageView driving_license_type_second;
78
    private TextImageView driving_license_type_third;
79
    private TextView add_car_model_btn;
80
    private LoadingDialog loadDialog;
81
    private ArrayList<CarBrandGroupEntity> groups;
82
    private CarSeriesEntity carSeriesEntity;
83
    private ConstraintLayout car_model_constraint_layout;
84
    private ConstraintLayout car_model_selected_constraint_layout;
85
    private ImageView car_icon;
86
    private TextView car_name;
87
    private TextView car_series;
88
    private ConstraintLayout driving_license;
89
    private ImageView driving_license_icon;
90
    private ImageView driving_license_upload_icon;
91
    private TextView driving_license_text_view;
92
    private Drawable selected;
93
    private Drawable normal;
94
95
    @Override
96
    protected void onCreate(Bundle savedInstanceState) {
97
        super.onCreate(savedInstanceState);
98
        // 禁止顶部固定部分滑动
99
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
100
        setContentView(R.layout.activity_car_owner_certificate);
101
        BarColorUtil.initStatusBarColor(CarOwnerCertificateActivity.this);
102
        initViews();
103
        brandListRequest(false);
104
        add_car_model_btn.setVisibility(View.GONE);
105
        EventBus.getDefault().register(this);
106
    }
107
108
    private void initViews() {
109
        loadDialog = new LoadingDialog(this);
110
        loadDialog.setCanceledOnTouchOutside(false);
111
112
        insertDialog = new ProgressDialog(this);
113
        insertDialog.setMessage("正在插入图片...");
114
        insertDialog.setCanceledOnTouchOutside(false);
115
116
        nav_title = findViewById(R.id.nav_title);
117
        findViewById(R.id.iv_back).setOnClickListener(new View.OnClickListener() {
118
            @Override
119
            public void onClick(View v) {
120
                finish();
121
            }
122
        });
123
124
        add_car_model_btn = findViewById(R.id.add_car_model_btn);
125
        car_model_constraint_layout = findViewById(R.id.car_model_constraint_layout);
126
        car_model_selected_constraint_layout = findViewById(R.id.car_model_selected_constraint_layout);
127
        add_car_model_btn.setOnClickListener(this);
128
        car_model_selected_constraint_layout.setOnClickListener(this);
129
130
        car_icon = findViewById(R.id.car_icon);
131
        car_name = findViewById(R.id.car_name);
132
        car_series = findViewById(R.id.car_series);
133
134
        driving_license = findViewById(R.id.driving_license);
135
        driving_license.setOnClickListener(this);
136
        driving_license_icon = findViewById(R.id.driving_license_icon);
137
        driving_license_upload_icon = findViewById(R.id.driving_license_upload_icon);
138
        driving_license_text_view = findViewById(R.id.driving_license_text_view);
139
140
141
        driving_license_type_first = findViewById(R.id.driving_license_type_first);
142
        driving_license_type_second = findViewById(R.id.driving_license_type_second);
143
        driving_license_type_third = findViewById(R.id.driving_license_type_third);
144
        driving_license_type_first.setOnClickListener(this);
145
        driving_license_type_second.setOnClickListener(this);
146
        driving_license_type_third.setOnClickListener(this);
147
148
        selected = getResources().getDrawable(R.drawable.icon_radio_selected, null);
149
        selected.setBounds(0, 0, selected.getMinimumWidth(), selected.getMinimumHeight());
150
        normal = getResources().getDrawable(R.drawable.icon_radio_normal, null);
151
        normal.setBounds(0, 0, normal.getMinimumWidth(), normal.getMinimumHeight());
152
153
        submit_btn = findViewById(R.id.submit_btn);
154
        submit_btn.setOnClickListener(this);
155
    }
156
157
    private void brandListRequest(Boolean showLoading) {
158
        if (showLoading)
159
            loadDialog.show();
160
        // https://www.jianshu.com/p/10382cc71127
161
//        String url = "https://api.touchev.com:83/car/api/v1000/brand/list.do";
162
        String url = "http://car.d1ev.com/car/api/v1000/brand/list.do";
163
//        String url = MainApplication.url + "/zhannew/basic/web/index.php/member/get-score?id=" + MainApplication.userId +
164
//                "&phone=" + MainApplication.userPhone + "&password=" + MainApplication.userPassword + "&token=" + "xxxxxx";
165
        OkHttpUtils.get().url(url).build().connTimeOut(5000).readTimeOut(5000).execute(new StringCallback() {
166
            @Override
167
            public void onError(Call call, Exception e) {
168
                Toast.makeText(getApplicationContext(), "网络不给力,请检查网络状态", Toast.LENGTH_SHORT).show();
169
                loadDialog.dismiss();
170
                add_car_model_btn.setVisibility(View.VISIBLE);
171
            }
172
173
            @Override
174
            public void onResponse(String response) {
175
                loadDialog.dismiss();
176
                add_car_model_btn.setVisibility(View.VISIBLE);
177
                String code = JsonUtils.getKeyResult(response, "code");
178
                String desc = JsonUtils.getKeyResult(response, "desc");
179
                if ("1000".equals(code)) {
180
                    String data = JsonUtils.getKeyResult(response, "data");
181
                    Gson gson = new Gson();
182
                    groups = gson.fromJson(data, new TypeToken<ArrayList<CarBrandGroupEntity>>() {
183
                    }.getType());
184
                    if (groups == null || groups.size() == 0) {
185
                        if (showLoading)
186
                            ToastUtil.showToast(getApplicationContext(), desc, Toast.LENGTH_SHORT);
187
                    } else {
188
                        if (showLoading) {
189
                            EventBus.getDefault().postSticky(new CarBrandEvent(groups));
190
                            startActivity(new Intent(CarOwnerCertificateActivity.this, CarBrandActivity.class));
191
                        }
192
                    }
193
                } else {
194
                    if (showLoading)
195
                        ToastUtil.showToast(getApplicationContext(), desc, Toast.LENGTH_SHORT);
196
                }
197
            }
198
        });
199
    }
200
201
    @Override
202
    public void onClick(View v) {
203
        switch (v.getId()) {
204
            case R.id.add_car_model_btn:
205
            case R.id.car_model_selected_constraint_layout:
206
                if (groups == null || groups.size() == 0) {
207
                    brandListRequest(true);
208
                } else {
209
                    EventBus.getDefault().postSticky(new CarBrandEvent(groups));
210
                    startActivity(new Intent(CarOwnerCertificateActivity.this, CarBrandActivity.class));
211
                }
212
                break;
213
            case R.id.driving_license:
214
                Matisse.from(CarOwnerCertificateActivity.this)
215
                        .choose(MimeType.of(MimeType.JPEG, MimeType.PNG))
216
                        .showSingleMediaType(true)
217
                        .countable(true)
218
                        .maxSelectable(1)
219
                        .capture(true)
220
                        .captureStrategy(new CaptureStrategy(true, "com.electric.chargingpile.provider"))
221
                        .imageEngine(new GlideEngine())
222
                        .forResult(REQUEST_CODE_CHOOSE);
223
                break;
224
            case R.id.driving_license_type_first:
225
                drivingLicenseType = 1;
226
                driving_license_type_first.setCompoundDrawables(selected, null, null, null);
227
                driving_license_type_second.setCompoundDrawables(normal, null, null, null);
228
                driving_license_type_third.setCompoundDrawables(normal, null, null, null);
229
                break;
230
            case R.id.driving_license_type_second:
231
                drivingLicenseType = 2;
232
                driving_license_type_first.setCompoundDrawables(normal, null, null, null);
233
                driving_license_type_second.setCompoundDrawables(selected, null, null, null);
234
                driving_license_type_third.setCompoundDrawables(normal, null, null, null);
235
                break;
236
            case R.id.driving_license_type_third:
237
                drivingLicenseType = 3;
238
                driving_license_type_first.setCompoundDrawables(normal, null, null, null);
239
                driving_license_type_second.setCompoundDrawables(normal, null, null, null);
240
                driving_license_type_third.setCompoundDrawables(selected, null, null, null);
241
                break;
242
            case R.id.submit_btn:
243
                if (carSeriesEntity == null) {
244
                    ToastUtil.showToast(this, "请添加车型" + drivingLicenseType, Toast.LENGTH_SHORT);
245
                    return;
246
                }
247
                break;
248
        }
249
    }
250
251
    @Override
252
    protected void onDestroy() {
253
        super.onDestroy();
254
        EventBus.getDefault().unregister(this);
255
    }
256
257
    @Subscribe(threadMode = ThreadMode.MAIN)
258
    public void onCarSeriesMessage(CarSerieEvent event) {
259
        if (event != null && event.getCarSeriesEntity() != null) {
260
            carSeriesEntity = event.getCarSeriesEntity();
261
            car_model_constraint_layout.setVisibility(View.GONE);
262
            car_model_selected_constraint_layout.setVisibility(View.VISIBLE);
263
            car_name.setText(carSeriesEntity.getBrandName());
264
            car_series.setText(carSeriesEntity.getSeriesName());
265
            Glide.with(CarOwnerCertificateActivity.this).load(carSeriesEntity.getIcon()).placeholder(android.R.color.white).fitCenter().into(car_icon);
266
        } else {
267
            carSeriesEntity = null;
268
            car_model_constraint_layout.setVisibility(View.VISIBLE);
269
            car_model_selected_constraint_layout.setVisibility(View.GONE);
270
        }
271
    }
272
273
    @Override
274
    protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
275
        super.onActivityResult(requestCode, resultCode, data);
276
        if (resultCode == RESULT_OK) {
277
            if (data != null) {
278
                if (requestCode == REQUEST_CODE_CHOOSE) {
279
                    insertImagesSync(data);
280
                }
281
            }
282
        }
283
    }
284
285
    private Bitmap imageZoom(Bitmap bm) {
286
        // 图片允许最大空间 单位:KB
287
        double maxSize = 200.00;
288
        // 将bitmap放至数组中,意在bitmap的大小(与实际读取的原文件要大)
289
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
290
        bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);
291
        byte[] b = baos.toByteArray();
292
        // 将字节换成KB
293
        double mid = b.length / 1024;
294
        // 判断bitmap占用空间是否大于允许最大空间 如果大于则压缩 小于则不压缩
295
        if (mid > maxSize) {
296
            // 获取bitmap大小 是允许最大大小的多少倍
297
            double i = mid / maxSize;
298
            // 开始压缩 此处用到平方根 将宽带和高度压缩掉对应的平方根倍
299
            // (1.保持刻度和高度和原bitmap比率一致,压缩后也达到了最大大小占用空间的大小)
300
            bm = zoomImage(bm, bm.getWidth() / Math.sqrt(i), bm.getHeight()
301
                    / Math.sqrt(i));
302
        }
303
304
305
        return bm;
306
    }
307
308
    public Bitmap zoomImage(Bitmap bgimage, double newWidth, double newHeight) {
309
        // 获取这个图片的宽和高
310
        float width = bgimage.getWidth();
311
        float height = bgimage.getHeight();
312
        // 创建操作图片用的matrix对象
313
        Matrix matrix = new Matrix();
314
        // 计算宽高缩放率
315
        float scaleWidth = ((float) newWidth) / width;
316
        float scaleHeight = ((float) newHeight) / height;
317
        // 缩放图片动作
318
        matrix.postScale(scaleWidth, scaleHeight);
319
        Bitmap bitmap = Bitmap.createBitmap(bgimage, 0, 0, (int) width,
320
                (int) height, matrix, true);
321
        return bitmap;
322
    }
323
324
    /**
325
     * 异步方式插入图片
326
     *
327
     * @param data
328
     */
329
    private void insertImagesSync(final Intent data) {
330
        insertDialog.show();
331
332
        Observable.create(new ObservableOnSubscribe<String>() {
333
            @Override
334
            public void subscribe(ObservableEmitter<String> subscriber) throws Exception {
335
336
                try {
337
                    List<Uri> uriList = Matisse.obtainResult(data);
338
                    Uri uri = uriList.get(0);
339
                    Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
340
                    File file = FileUtils.from(CarOwnerCertificateActivity.this, uri);
341
342
                    bitmap = FileUtils.rotateIfRequired(file, bitmap);
343
                    bitmap = imageZoom(bitmap);
344
                    insertBitmap = bitmap;
345
346
                    u_path = SDCardUtil.saveToSdCard(bitmap);
347
348
                    subscriber.onNext(u_path);
349
                    subscriber.onComplete();
350
                } catch (Exception e) {
351
                    e.printStackTrace();
352
                    subscriber.onError(e);
353
                }
354
            }
355
        })
356
                .subscribeOn(Schedulers.io())//生产事件在io
357
                .observeOn(AndroidSchedulers.mainThread())//消费事件在UI线程
358
                .subscribe(new Observer<String>() {
359
                    @Override
360
                    public void onComplete() {
361
                        insertDialog.dismiss();
362
                        driving_license_icon.setImageBitmap(insertBitmap);
363
                        driving_license_upload_icon.setVisibility(View.GONE);
364
                        driving_license_text_view.setVisibility(View.GONE);
365
//                        uploadPic(insertBitmap, u_path); // TODO EditAnswerActivity
366
                    }
367
368
                    @Override
369
                    public void onError(Throwable e) {
370
                        insertDialog.dismiss();
371
                        ToastUtil.showToast(getApplicationContext(), "图片插入失败", Toast.LENGTH_SHORT);
372
                    }
373
374
                    @Override
375
                    public void onSubscribe(Disposable d) {
376
377
                    }
378
379
                    @Override
380
                    public void onNext(String imagePath) {
381
382
                    }
383
                });
384
    }
385
}

+ 29 - 133
app/src/main/java/com/electric/chargingpile/activity/UserCenterActivity.java

@ -21,7 +21,9 @@ import android.os.Environment;
21 21
import android.os.Handler;
22 22
import android.os.Message;
23 23
import android.os.Process;
24
24 25
import androidx.annotation.NonNull;
26
25 27
import android.util.Log;
26 28
import android.view.KeyEvent;
27 29
import android.view.View;
@ -98,7 +100,7 @@ public class UserCenterActivity extends Activity implements View.OnClickListener
98 100
    private NetworkChangeReceiver networkChangeReceiver;
99 101
    private ImageView iv_back, iv_message, iv_qiandao, iv_share_prompt, iv_find, iv_main, iv_screening, iv_point;
100 102
    private RelativeLayout rl_addZhan, rl_collection, rl_more,
101
            rl_offline, rl_shop, rl_message, rl_feedback, rl_shareNo, rl_offline_upload, rl_chongzhi, rl_myaccount, rl_yue, rl_chongdianbi, rl_hongbao;
103
            rl_offline, rl_shop, rl_message, rl_feedback, rl_shareNo, rl_offline_upload, rl_chongzhi, rl_myaccount, rl_yue, rl_chongdianbi, rl_hongbao, rl_car_owner_certificate, rl_publish_price;
102 104
    private ToggleButton mTogBtn;
103 105
    private TextView tv_exit, userLogin, userRegister, chongdianbi, yue, hongbao, tv_our;
104 106
    private LinearLayout ll_userLogin;
@ -148,73 +150,11 @@ public class UserCenterActivity extends Activity implements View.OnClickListener
148 150
149 151
                        Log.d("pingLunNum+++", pingLunNum);
150 152
                        MainMapActivity.have_pinglun = Integer.parseInt(pingLunNum);
151
152 153
                        Log.d("pinglun===yonghu", MainMapActivity.have_message + "");
153
//                        if (MainMapActivity.have_message == 0 && MainMapActivity.have_pinglun == 0) {
154
////            ivRight.setImageResource(R.drawable.icon_user2_0);
155
////                        iv_havemessage.setVisibility(View.GONE);
156
//                            iv_message.setVisibility(View.INVISIBLE);
157
//                            if (MainApplication.festival_time.equals("1")){
158
//                                iv_our.setImageResource(R.drawable.icon_cj4);
159
//                            }else if (MainApplication.festival_time.equals("2")){
160
//                                iv_our.setImageResource(R.drawable.icon_yx4);
161
//                            }else {
162
//                                iv_our.setImageResource(R.drawable.tab_our_selected);
163
//                            }
164
////                            iv_our.setImageResource(R.drawable.tab_our_selected);
165
//                        } else if (MainMapActivity.have_message == 1) {
166
//                            if (MainApplication.festival_time.equals("1")){
167
//                                iv_our.setImageResource(R.drawable.icon_cjh4);
168
//                            }else if (MainApplication.festival_time.equals("2")){
169
//                                iv_our.setImageResource(R.drawable.icon_yxh4);
170
//                            }else {
171
//                                iv_our.setImageResource(R.drawable.tab_our_selected_h);
172
//                            }
173
////                            iv_our.setImageResource(R.drawable.tab_our_selected_h);
174
////                        iv_havemessage.setVisibility(View.VISIBLE);
175
//                            iv_message.setVisibility(View.VISIBLE);
176
//                        } else if (MainMapActivity.have_pinglun > 0) {
177
////                        iv_havemessage.setVisibility(View.VISIBLE);
178
//                            iv_message.setVisibility(View.VISIBLE);
179
//                            if (MainApplication.festival_time.equals("1")){
180
//                                iv_our.setImageResource(R.drawable.icon_cjh4);
181
//                            }else if (MainApplication.festival_time.equals("2")){
182
//                                iv_our.setImageResource(R.drawable.icon_yxh4);
183
//                            }else {
184
//                        }
185
//                                iv_our.setImageResource(R.drawable.tab_our_selected_h);
186
//                            }
187
//                        }
188 154
                    } catch (JSONException e) {
189 155
                        e.printStackTrace();
190 156
                    }
191
192 157
                    break;
193
194
//                case 5:
195
////                    Log.e("log",msg.obj.toString());
196
//                    try {
197
//                        JSONArray jsonArray = new JSONArray(msg.obj.toString());
198
//                        Log.e("???",jsonArray.length()+"");
199
//                        Log.e("???",msg.obj.toString());
200
//                        if (jsonArray.length() == 0){
201
//                            Log.e("!!!",jsonArray.length()+"");
202
//                            iv_message.setVisibility(View.INVISIBLE);
203
//                            have_message = 0;
204
//                        }else{
205
//                            Log.e("@@@",jsonArray.length()+"");
206
//                            iv_message.setVisibility(View.VISIBLE);
207
//                            have_message = 1;
208
//                        }
209
//                    } catch (JSONException e) {
210
//                        e.printStackTrace();
211
//                    }
212
////                    if (msg.obj.toString() == null || msg.obj.toString().equals("") ||msg.obj.toString().equals("null")){
213
////                       iv_message.setVisibility(View.INVISIBLE);
214
////                    }
215
//                    break;
216
217
218 158
                default:
219 159
220 160
                    break;
@ -268,21 +208,12 @@ public class UserCenterActivity extends Activity implements View.OnClickListener
268 208
        registerReceiver(networkChangeReceiver, intentFilter);
269 209
        //透明状态栏
270 210
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
271
        //透明导航栏
272
//        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
273
274 211
        initView();
275 212
        activity = this;
276 213
        if (MainApplication.isLogin()) {
277 214
            getPingLun();
278 215
        }
279 216
280
281
//        getMessage();
282
283
//        getIntegration();
284
285
286 217
        // ATTENTION: This was auto-generated to implement the App Indexing API.
287 218
        // See https://g.co/AppIndexing/AndroidStudio for more information.
288 219
        client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
@ -298,12 +229,7 @@ public class UserCenterActivity extends Activity implements View.OnClickListener
298 229
                    } catch (Exception e) {
299 230
                        e.printStackTrace();
300 231
                    }
301
302
//                    saveBitmap(bm);
303
304 232
                    break;
305
306
307 233
                default:
308 234
                    break;
309 235
            }
@ -364,7 +290,6 @@ public class UserCenterActivity extends Activity implements View.OnClickListener
364 290
        iv_hongbao = (ImageView) findViewById(R.id.iv_hongbao);
365 291
        iv_chongdianbi = (ImageView) findViewById(R.id.iv_chongdianbi);
366 292
        yue = (TextView) findViewById(R.id.tv_yue);
367
//        iv_message = (ImageView) findViewById(R.id.iv_message);
368 293
        iv_message = (ImageView) findViewById(R.id.iv_have_message);
369 294
370 295
        ll_tab_find = (RelativeLayout) findViewById(R.id.ll_tab_find);
@ -379,39 +304,13 @@ public class UserCenterActivity extends Activity implements View.OnClickListener
379 304
380 305
381 306
        iv_our = (ImageView) findViewById(R.id.iv_our);
382
//        if (MainMapActivity.have_message == 1) {
383
//            Log.e("userCenter==",MainMapActivity.have_message+"");
384
//            iv_message.setVisibility(View.VISIBLE);
385
//        } else {
386
//            iv_message.setVisibility(View.INVISIBLE);
387
//        }
388
389
390
//        iv_havemessage = (ImageView) findViewById(R.id.iv_havemessage);
391
//        if (MainFragment.have_message == 1){
392
//            iv_havemessage.setVisibility(View.VISIBLE);
393
//        }else if(MainFragment.have_message == 0){
394
//            iv_havemessage.setVisibility(View.GONE);
395
//        }
396
397
398
//        if (have_message == 1){
399
//            iv_message.setVisibility(View.VISIBLE);
400
//        }else{
401
//            iv_message.setVisibility(View.INVISIBLE);
402
//        }
403 307
404 308
        rl_collection = (RelativeLayout) findViewById(R.id.rl_collection);
405 309
        rl_collection.setOnClickListener(this);
406 310
407
408
//        rl_more = (RelativeLayout) findViewById(R.id.rl_more);
409
//        rl_more.setOnClickListener(this);
410
411 311
        rl_message = (RelativeLayout) findViewById(R.id.rl_message);
412 312
        rl_message.setOnClickListener(this);
413 313
414
415 314
        rl_shareNo = (RelativeLayout) findViewById(R.id.rl_shareNo);
416 315
        rl_shareNo.setOnClickListener(this);
417 316
@ -422,6 +321,11 @@ public class UserCenterActivity extends Activity implements View.OnClickListener
422 321
        chat_share_bar = findViewById(R.id.chat_share_bar);
423 322
        chat_share_bar.setOnClickListener(this);
424 323
324
        rl_car_owner_certificate = findViewById(R.id.rl_car_owner_certificate);
325
        rl_car_owner_certificate.setOnClickListener(this);
326
327
        rl_publish_price = findViewById(R.id.rl_publish_price);
328
        rl_publish_price.setOnClickListener(this);
425 329
426 330
        rl_chongzhi = (RelativeLayout) findViewById(R.id.rl_chongzhi);
427 331
        rl_chongzhi.setOnClickListener(this);
@ -437,30 +341,6 @@ public class UserCenterActivity extends Activity implements View.OnClickListener
437 341
438 342
        rl_yue = (RelativeLayout) findViewById(R.id.rl_yue);
439 343
        rl_yue.setOnClickListener(this);
440
//        mTogBtn = (ToggleButton) findViewById(R.id.iosbutton); // 获取到控件
441
//        if (MainApplication.userTpye == "1") {
442
//            mTogBtn.setChecked(false);
443
//        } else if (MainApplication.userTpye == "2") {
444
//            mTogBtn.setChecked(true);
445
//        }
446
//
447
//        mTogBtn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
448
//
449
//            @Override
450
//            public void onCheckedChanged(CompoundButton buttonView,
451
//                                         boolean isChecked) {
452
//                // TODO Auto-generated method stub
453
//                if (isChecked) {
454
//                    MainApplication.userTpye = "2";
455
//                    Log.e("suit_car", "特斯拉");
456
//                    MainFragment.firstSelect();
457
//                } else {
458
//                    MainApplication.userTpye = "1";
459
//                    Log.e("suit_car", "国标");
460
//                    MainFragment.firstSelect();
461
//                }
462
//            }
463
//        });
464 344
465 345
        tab_main = (LinearLayout) findViewById(R.id.tab_main);
466 346
        tab_main.setOnClickListener(this);
@ -478,11 +358,6 @@ public class UserCenterActivity extends Activity implements View.OnClickListener
478 358
        llPerson = (RelativeLayout) findViewById(R.id.ll_person);
479 359
        llPerson.setOnClickListener(this);
480 360
481
482
        //退出登录按钮
483
//        tv_exit = (TextView) findViewById(R.id.tv_exit);
484
//        tv_exit.setOnClickListener(this);
485
486 361
        //登陆按钮
487 362
        userLogin = (TextView) findViewById(R.id.userLogin);
488 363
        userLogin.setOnClickListener(this);
@ -901,6 +776,27 @@ public class UserCenterActivity extends Activity implements View.OnClickListener
901 776
                MobclickAgent.onEvent(getApplicationContext(), "0815");
902 777
                break;
903 778
779
            case R.id.rl_car_owner_certificate: // 车主认证
780
                if (!MainApplication.isLogin()) {
781
                    Toast.makeText(getApplication(), "请先登录", Toast.LENGTH_SHORT).show();
782
                    startActivity(new Intent(getApplication(), LoginActivity.class));
783
                } else {
784
                    // 列表接口
785
                    // 1.无认证记录
786
                    startActivity(new Intent(getApplication(), CarOwnerCertificateActivity.class));
787
//                    MobclickAgent.onEvent(getApplicationContext(), "0810"); // TODO
788
                }
789
                break;
790
            case R.id.rl_publish_price: // 发表成交价
791
                if (!MainApplication.isLogin()) {
792
                    Toast.makeText(getApplication(), "请先登录", Toast.LENGTH_SHORT).show();
793
                    startActivity(new Intent(getApplication(), LoginActivity.class));
794
                } else {
795
                    // TODO 跳转html
796
                    System.out.println("come on");
797
                }
798
                break;
799
904 800
            case R.id.rl_chongzhi:
905 801
                if (!MainApplication.isLogin()) {
906 802
                    Toast.makeText(getApplication(), "请先登录", Toast.LENGTH_SHORT).show();

+ 97 - 0
app/src/main/java/com/electric/chargingpile/adapter/CarBrandGroupedListAdapter.java

@ -0,0 +1,97 @@
1
package com.electric.chargingpile.adapter;
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.Button;
8
import android.widget.ImageView;
9
10
import com.bumptech.glide.Glide;
11
import com.bumptech.glide.load.engine.DiskCacheStrategy;
12
import com.donkingliang.groupedadapter.adapter.GroupedRecyclerViewAdapter;
13
import com.donkingliang.groupedadapter.holder.BaseViewHolder;
14
import com.electric.chargingpile.R;
15
import com.electric.chargingpile.entity.CarBrandChildEntity;
16
import com.electric.chargingpile.entity.CarBrandGroupEntity;
17
18
import java.util.ArrayList;
19
20
public class CarBrandGroupedListAdapter extends GroupedRecyclerViewAdapter {
21
22
    protected ArrayList<CarBrandGroupEntity> groups;
23
24
    public CarBrandGroupedListAdapter(Context context, ArrayList<CarBrandGroupEntity> groups) {
25
        super(context);
26
        this.groups = groups;
27
    }
28
29
    public void clear() {
30
        groups.clear();
31
        notifyDataChanged();
32
    }
33
34
    public void setGroups(ArrayList<CarBrandGroupEntity> groups) {
35
        this.groups = groups;
36
        notifyDataChanged();
37
    }
38
39
    @Override
40
    public int getGroupCount() {
41
        return groups == null ? 0 : groups.size();
42
    }
43
44
    @Override
45
    public int getChildrenCount(int groupPosition) {
46
        ArrayList<CarBrandChildEntity> children = groups.get(groupPosition).getBrandList();
47
        return children == null ? 0 : children.size();
48
    }
49
50
    @Override
51
    public boolean hasHeader(int groupPosition) {
52
        return true;
53
    }
54
55
    @Override
56
    public boolean hasFooter(int groupPosition) {
57
        return false;
58
    }
59
60
    @Override
61
    public int getHeaderLayout(int viewType) {
62
        return R.layout.adapter_header_car_brand;
63
    }
64
65
    @Override
66
    public int getFooterLayout(int viewType) {
67
        return 0;
68
    }
69
70
    @Override
71
    public int getChildLayout(int viewType) {
72
        return R.layout.adapter_child_car_brand;
73
    }
74
75
    @Override
76
    public void onBindHeaderViewHolder(BaseViewHolder holder, int groupPosition) {
77
        CarBrandGroupEntity entity = groups.get(groupPosition);
78
        holder.setText(R.id.title, entity.getInitial());
79
    }
80
81
    @Override
82
    public void onBindFooterViewHolder(BaseViewHolder holder, int groupPosition) {
83
    }
84
85
    @Override
86
    public void onBindChildViewHolder(BaseViewHolder holder, int groupPosition, int childPosition) {
87
        CarBrandChildEntity entity = groups.get(groupPosition).getBrandList().get(childPosition);
88
        holder.setText(R.id.title, entity.getBrandName());
89
        if (childPosition == 0) {
90
            holder.setVisible(R.id.line, View.GONE);
91
        } else {
92
            holder.setVisible(R.id.line, View.VISIBLE);
93
        }
94
        ImageView icon = holder.getImageView(R.id.icon);
95
        Glide.with(mContext).load(entity.getIcon()).placeholder(android.R.color.white).fitCenter().into(icon);
96
    }
97
}

+ 95 - 0
app/src/main/java/com/electric/chargingpile/adapter/CarModelGroupedListAdapter.java

@ -0,0 +1,95 @@
1
package com.electric.chargingpile.adapter;
2
3
import android.content.Context;
4
import android.view.View;
5
import android.widget.ImageView;
6
7
import com.bumptech.glide.Glide;
8
import com.bumptech.glide.load.engine.DiskCacheStrategy;
9
import com.donkingliang.groupedadapter.adapter.GroupedRecyclerViewAdapter;
10
import com.donkingliang.groupedadapter.holder.BaseViewHolder;
11
import com.electric.chargingpile.R;
12
import com.electric.chargingpile.entity.CarCompanyEntity;
13
import com.electric.chargingpile.entity.CarSeriesEntity;
14
15
import java.util.ArrayList;
16
17
public class CarModelGroupedListAdapter extends GroupedRecyclerViewAdapter {
18
    protected ArrayList<CarCompanyEntity> groups;
19
20
    public CarModelGroupedListAdapter(Context context, ArrayList<CarCompanyEntity> groups) {
21
        super(context);
22
        this.groups = groups;
23
    }
24
25
    public void clear() {
26
        groups.clear();
27
        notifyDataChanged();
28
    }
29
30
    public void setGroups(ArrayList<CarCompanyEntity> groups) {
31
        this.groups = groups;
32
        notifyDataChanged();
33
    }
34
35
    @Override
36
    public int getGroupCount() {
37
        return groups == null ? 0 : groups.size();
38
    }
39
40
    @Override
41
    public int getChildrenCount(int groupPosition) {
42
        ArrayList<CarSeriesEntity> children = groups.get(groupPosition).getSerieslist();
43
        return children == null ? 0 : children.size();
44
    }
45
46
    @Override
47
    public boolean hasHeader(int groupPosition) {
48
        return true;
49
    }
50
51
    @Override
52
    public boolean hasFooter(int groupPosition) {
53
        return false;
54
    }
55
56
    @Override
57
    public int getHeaderLayout(int viewType) {
58
        return R.layout.adapter_header_car_model;
59
    }
60
61
    @Override
62
    public int getFooterLayout(int viewType) {
63
        return 0;
64
    }
65
66
    @Override
67
    public int getChildLayout(int viewType) {
68
        return R.layout.adapter_child_car_model;
69
    }
70
71
    @Override
72
    public void onBindHeaderViewHolder(BaseViewHolder holder, int groupPosition) {
73
        CarCompanyEntity entity = groups.get(groupPosition);
74
        holder.setText(R.id.title, entity.getCompanyName());
75
    }
76
77
    @Override
78
    public void onBindFooterViewHolder(BaseViewHolder holder, int groupPosition) {
79
80
    }
81
82
    @Override
83
    public void onBindChildViewHolder(BaseViewHolder holder, int groupPosition, int childPosition) {
84
        CarSeriesEntity entity = groups.get(groupPosition).getSerieslist().get(childPosition);
85
        holder.setText(R.id.title, entity.getSeriesName());
86
        if (childPosition == 0) {
87
            holder.setVisible(R.id.line, View.GONE);
88
        } else {
89
            holder.setVisible(R.id.line, View.VISIBLE);
90
        }
91
        ImageView icon = holder.getImageView(R.id.icon);
92
        Glide.with(mContext).load(entity.getIcon()).placeholder(android.R.color.white).diskCacheStrategy(DiskCacheStrategy.RESOURCE).fitCenter().into(icon);
93
    }
94
95
}

+ 59 - 0
app/src/main/java/com/electric/chargingpile/entity/CarBrandChildEntity.java

@ -0,0 +1,59 @@
1
package com.electric.chargingpile.entity;
2
3
import java.util.ArrayList;
4
5
public class CarBrandChildEntity {
6
    private int brandId;
7
    private String brandName;
8
    private int seriesNum;
9
    private String icon;
10
    private ArrayList<CarCompanyEntity> companyList;
11
12
    public CarBrandChildEntity(int brandId, String brandName, int seriesNum, String icon, ArrayList<CarCompanyEntity> companyList) {
13
        this.brandId = brandId;
14
        this.brandName = brandName;
15
        this.seriesNum = seriesNum;
16
        this.icon = icon;
17
        this.companyList = companyList;
18
    }
19
20
    public int getBrandId() {
21
        return brandId;
22
    }
23
24
    public void setBrandId(int brandId) {
25
        this.brandId = brandId;
26
    }
27
28
    public String getBrandName() {
29
        return brandName;
30
    }
31
32
    public void setBrandName(String brandName) {
33
        this.brandName = brandName;
34
    }
35
36
    public int getSeriesNum() {
37
        return seriesNum;
38
    }
39
40
    public void setSeriesNum(int seriesNum) {
41
        this.seriesNum = seriesNum;
42
    }
43
44
    public String getIcon() {
45
        return icon;
46
    }
47
48
    public void setIcon(String icon) {
49
        this.icon = icon;
50
    }
51
52
    public ArrayList<CarCompanyEntity> getCompanyList() {
53
        return companyList;
54
    }
55
56
    public void setCompanyList(ArrayList<CarCompanyEntity> companyList) {
57
        this.companyList = companyList;
58
    }
59
}

+ 30 - 0
app/src/main/java/com/electric/chargingpile/entity/CarBrandGroupEntity.java

@ -0,0 +1,30 @@
1
package com.electric.chargingpile.entity;
2
3
4
import java.util.ArrayList;
5
6
public class CarBrandGroupEntity {
7
    private String initial; // header
8
    private ArrayList<CarBrandChildEntity> brandList; // children
9
10
    public CarBrandGroupEntity(String initial, ArrayList<CarBrandChildEntity> brandList) {
11
        this.initial = initial;
12
        this.brandList = brandList;
13
    }
14
15
    public String getInitial() {
16
        return initial;
17
    }
18
19
    public void setInitial(String initial) {
20
        this.initial = initial;
21
    }
22
23
    public ArrayList<CarBrandChildEntity> getBrandList() {
24
        return brandList;
25
    }
26
27
    public void setBrandList(ArrayList<CarBrandChildEntity> brandList) {
28
        this.brandList = brandList;
29
    }
30
}

+ 50 - 0
app/src/main/java/com/electric/chargingpile/entity/CarCompanyEntity.java

@ -0,0 +1,50 @@
1
package com.electric.chargingpile.entity;
2
3
import java.util.ArrayList;
4
5
public class CarCompanyEntity {
6
    private int companyId;
7
    private String companyName;
8
    private int brandId;
9
    private ArrayList<CarSeriesEntity> serieslist;
10
11
    public CarCompanyEntity(int companyId, String companyName, int brandId, ArrayList<CarSeriesEntity> serieslist) {
12
        this.companyId = companyId;
13
        this.companyName = companyName;
14
        this.brandId = brandId;
15
        this.serieslist = serieslist;
16
    }
17
18
19
    public int getCompanyId() {
20
        return companyId;
21
    }
22
23
    public void setCompanyId(int companyId) {
24
        this.companyId = companyId;
25
    }
26
27
    public String getCompanyName() {
28
        return companyName;
29
    }
30
31
    public void setCompanyName(String companyName) {
32
        this.companyName = companyName;
33
    }
34
35
    public int getBrandId() {
36
        return brandId;
37
    }
38
39
    public void setBrandId(int brandId) {
40
        this.brandId = brandId;
41
    }
42
43
    public ArrayList<CarSeriesEntity> getSerieslist() {
44
        return serieslist;
45
    }
46
47
    public void setSerieslist(ArrayList<CarSeriesEntity> serieslist) {
48
        this.serieslist = serieslist;
49
    }
50
}

+ 67 - 0
app/src/main/java/com/electric/chargingpile/entity/CarSeriesEntity.java

@ -0,0 +1,67 @@
1
package com.electric.chargingpile.entity;
2
3
public class CarSeriesEntity {
4
    private int brandId;
5
    private String brandName;
6
    private int companyId;
7
    private int seriesId;
8
    private String seriesName;
9
    private String icon;
10
11
    public CarSeriesEntity(int brandId, String brandName, int companyId, int seriesId, String seriesName, String icon) {
12
        this.brandId = brandId;
13
        this.brandName = brandName;
14
        this.companyId = companyId;
15
        this.seriesId = seriesId;
16
        this.seriesName = seriesName;
17
        this.icon = icon;
18
    }
19
20
    public int getBrandId() {
21
        return brandId;
22
    }
23
24
    public void setBrandId(int brandId) {
25
        this.brandId = brandId;
26
    }
27
28
    public String getBrandName() {
29
        return brandName;
30
    }
31
32
    public void setBrandName(String brandName) {
33
        this.brandName = brandName;
34
    }
35
36
    public int getCompanyId() {
37
        return companyId;
38
    }
39
40
    public void setCompanyId(int companyId) {
41
        this.companyId = companyId;
42
    }
43
44
    public int getSeriesId() {
45
        return seriesId;
46
    }
47
48
    public void setSeriesId(int seriesId) {
49
        this.seriesId = seriesId;
50
    }
51
52
    public String getSeriesName() {
53
        return seriesName;
54
    }
55
56
    public void setSeriesName(String seriesName) {
57
        this.seriesName = seriesName;
58
    }
59
60
    public String getIcon() {
61
        return icon;
62
    }
63
64
    public void setIcon(String icon) {
65
        this.icon = icon;
66
    }
67
}

+ 21 - 0
app/src/main/java/com/electric/chargingpile/event/CarBrandEvent.java

@ -0,0 +1,21 @@
1
package com.electric.chargingpile.event;
2
3
import com.electric.chargingpile.entity.CarBrandGroupEntity;
4
5
import java.util.ArrayList;
6
7
public class CarBrandEvent {
8
    private ArrayList<CarBrandGroupEntity> groups;
9
10
    public CarBrandEvent(ArrayList<CarBrandGroupEntity> groups) {
11
        this.groups = groups;
12
    }
13
14
    public ArrayList<CarBrandGroupEntity> getGroups() {
15
        return groups;
16
    }
17
18
    public void setGroups(ArrayList<CarBrandGroupEntity> groups) {
19
        this.groups = groups;
20
    }
21
}

+ 20 - 0
app/src/main/java/com/electric/chargingpile/event/CarCompanyEvent.java

@ -0,0 +1,20 @@
1
package com.electric.chargingpile.event;
2
3
import com.electric.chargingpile.entity.CarCompanyEntity;
4
5
import java.util.ArrayList;
6
7
public class CarCompanyEvent {
8
    private ArrayList<CarCompanyEntity> companyList;
9
    public ArrayList<CarCompanyEntity> getCompanyList() {
10
        return companyList;
11
    }
12
13
    public void setCompanyList(ArrayList<CarCompanyEntity> companyList) {
14
        this.companyList = companyList;
15
    }
16
17
    public CarCompanyEvent(ArrayList<CarCompanyEntity> companyList) {
18
        this.companyList = companyList;
19
    }
20
}

+ 19 - 0
app/src/main/java/com/electric/chargingpile/event/CarSerieEvent.java

@ -0,0 +1,19 @@
1
package com.electric.chargingpile.event;
2
3
import com.electric.chargingpile.entity.CarSeriesEntity;
4
5
public class CarSerieEvent {
6
    private CarSeriesEntity carSeriesEntity;
7
8
    public CarSerieEvent(CarSeriesEntity carSeriesEntity) {
9
        this.carSeriesEntity = carSeriesEntity;
10
    }
11
12
    public CarSeriesEntity getCarSeriesEntity() {
13
        return carSeriesEntity;
14
    }
15
16
    public void setCarSeriesEntity(CarSeriesEntity carSeriesEntity) {
17
        this.carSeriesEntity = carSeriesEntity;
18
    }
19
}

+ 12 - 0
app/src/main/java/com/electric/chargingpile/util/DensityUtil.java

@ -28,4 +28,16 @@ public class DensityUtil {
28 28
        final float scale = context.getResources().getDisplayMetrics().density;
29 29
        return (int) (pxValue / scale + 0.5f);
30 30
    }
31

32
    /**
33
     * 将sp值转换为px值,保证文字大小不变
34
     *
35
     * @param spValue fontScale(DisplayMetrics类中属性scaledDensity)
36
     * @return
37
     */
38
    public static int sp2px(Context context, float spValue) {
39
        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
40
        return (int) (spValue * fontScale + 0.5f);
41
    }
42

31 43
}

+ 154 - 0
app/src/main/java/com/electric/chargingpile/view/LetterSideView.java

@ -0,0 +1,154 @@
1
package com.electric.chargingpile.view;
2
3
import android.content.Context;
4
import android.graphics.Canvas;
5
import android.graphics.Color;
6
import android.graphics.Paint;
7
import android.graphics.Rect;
8
import android.util.AttributeSet;
9
import android.view.MotionEvent;
10
import android.view.View;
11
import android.widget.TextView;
12
13
import com.electric.chargingpile.util.DensityUtil;
14
15
public class LetterSideView extends View {
16
    // 26个字母
17
    public static String[] letters = {
18
            "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
19
            "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "#"
20
    };
21
    private int choose = -1;  // 选中的字母的y坐标
22
    private int chosen = -1;
23
    private Paint paint = new Paint(); // 字母画笔
24
    private Paint circle = new Paint(); // 选中字符背景
25
    private TextView mTextDialog;  // 显示当前字母的文本框
26
    private int singleHeight;      // 一个字母的空间
27
    Rect rect = new Rect();     // 存放文字的高度
28
29
    public LetterSideView(Context context, AttributeSet attrs) {
30
        super(context, attrs);
31
    }
32
33
    @Override
34
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
35
        super.onLayout(changed, left, top, right, bottom);
36
        paint.setAntiAlias(true); // 设置抗锯齿
37
        paint.setTextSize(DensityUtil.sp2px(getContext(), 12f)); // 设置字母字体大小为12sp
38
        paint.getTextBounds("A", 0, 1, rect);  // 获取一个字母实际的宽高到rect
39
        singleHeight = (getHeight() - (getPaddingTop() + getPaddingBottom())) / letters.length;   // 获取一个字母的空间
40
41
        circle.setAntiAlias(true); // 设置抗锯齿
42
        circle.setColor(Color.parseColor("#C1CCD5"));
43
    }
44
45
    /**
46
     * 为SideBar设置显示字母的TextView
47
     *
48
     * @param mTextDialog 在activity传递过来的textView
49
     */
50
    public void setTextView(TextView mTextDialog) {
51
        this.mTextDialog = mTextDialog;
52
    }
53
54
    public void setPosition(int position) {
55
        chosen = position;
56
        invalidate();
57
    }
58
59
    /**
60
     * 绘制
61
     */
62
    @Override
63
    protected void onDraw(Canvas canvas) {
64
        super.onDraw(canvas);
65
        // 循环绘制字母
66
        for (int i = 0; i < letters.length; i++) {
67
            //paint.setTypeface(Typeface.DEFAULT_BOLD); // 设置默认字体加粗
68
69
70
            // 选中的状态
71
            if (i == chosen) {
72
                paint.setColor(Color.parseColor("#FFFFFF")); // 选中的字母改变颜色
73
                paint.setFakeBoldText(true); // 设置字体为粗体
74
                float yPos = getPaddingTop() + singleHeight * i + rect.height() / 2f;
75
                canvas.drawCircle(getWidth() / 2f, yPos, getWidth() * 0.35f, circle);
76
            } else {
77
                paint.setColor(Color.parseColor("#6F6F7D")); // 设置字体颜色
78
                paint.setFakeBoldText(false); // 设置字体为正常
79
            }
80
81
            // x坐标等于中间-字符宽度的一半.
82
            float xPos = getWidth() / 2 - paint.measureText(letters[i]) / 2;
83
            // Y轴坐标
84
            float yPos = getPaddingTop() + singleHeight * i + rect.height();
85
            canvas.drawText(letters[i], xPos, yPos, paint); // 绘制字母
86
        }
87
    }
88
89
    /**
90
     * 分发触摸事件
91
     *
92
     * @param event
93
     * @return
94
     */
95
    @Override
96
    public boolean dispatchTouchEvent(MotionEvent event) {
97
        final int action = event.getAction();
98
        final float y = event.getY(); // 点击y坐标
99
        chosen = choose;  // 上一个选中的字母
100
        // 点击y坐标所占总高度的比例  *   数组的长度就等于点击了 数组中的位置.
101
        final int c = (int) (y / (getHeight() - getPaddingTop() - getPaddingBottom()) * letters.length);
102
        switch (action) {
103
            case MotionEvent.ACTION_UP:
104
                //抬起来的时候设置背景为透明
105
                //setBackgroundDrawable(new ColorDrawable(0x00000000));
106
                choose = -1;
107
                invalidate();
108
                if (mTextDialog != null) {
109
                    mTextDialog.setVisibility(View.INVISIBLE);
110
                }
111
                break;
112
            default:
113
                //按下,滑动的时候设置背景为灰色
114
                //setBackgroundDrawable(new ColorDrawable(0x44000000));
115
                //setBackgroundResource(R.drawable.sidebar_background);
116
                if (chosen != c) { // 判断选中字母是否发生改变
117
                    if (c >= 0 && c < letters.length) {
118
                        if (listener != null) {
119
                            listener.onTouchLetterChanged(letters[c]);
120
                            listener.onTouchLetterPosition(c);
121
                        }
122
                        if (mTextDialog != null) {
123
                            mTextDialog.setText(letters[c]);
124
                            mTextDialog.setVisibility(View.VISIBLE);
125
                        }
126
                        // 设置选中字母在数组的位置
127
                        choose = c;
128
                        chosen = choose;
129
                        invalidate();
130
                    }
131
                }
132
                break;
133
        }
134
        return true;
135
    }
136
137
    // 触摸回调接口
138
    private OnTouchLetterChangedListener listener;
139
140
141
    public void setOnTouchLetterChangedListener(OnTouchLetterChangedListener onTouchLetterChangedListener) {
142
        this.listener = onTouchLetterChangedListener;
143
    }
144
145
    public interface OnTouchLetterChangedListener {
146
        /**
147
         * 触摸字母回调
148
         *
149
         * @param s 触摸的字符
150
         */
151
        void onTouchLetterChanged(String s);
152
        void onTouchLetterPosition(int position);
153
    }
154
}

+ 92 - 0
app/src/main/java/com/electric/chargingpile/view/TextImageView.java

@ -0,0 +1,92 @@
1
package com.electric.chargingpile.view;
2
3
import android.content.Context;
4
import android.content.res.TypedArray;
5
import android.graphics.Rect;
6
import android.graphics.drawable.Drawable;
7
import android.util.AttributeSet;
8
9
import androidx.appcompat.widget.AppCompatTextView;
10
11
import com.electric.chargingpile.R;
12
13
public class TextImageView extends AppCompatTextView {
14
    private int leftWidth;
15
    private int leftHeight;
16
    private int topWidth;
17
    private int topHeight;
18
    private int rightWidth;
19
    private int rightHeight;
20
    private int bottomWidth;
21
    private int bottomHeight;
22
23
24
    public TextImageView(Context context) {
25
        super(context);
26
    }
27
28
    public TextImageView(Context context, AttributeSet attrs) {
29
        super(context, attrs);
30
        init(context, attrs);
31
    }
32
33
    public TextImageView(Context context, AttributeSet attrs, int defStyleAttr) {
34
        super(context, attrs, defStyleAttr);
35
        init(context, attrs);
36
    }
37
38
    private void init(Context context, AttributeSet attrs) {
39
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TextImageView);
40
        leftWidth = typedArray.getDimensionPixelOffset(R.styleable.TextImageView_drawableLeftWidth, 0);
41
        leftHeight = typedArray.getDimensionPixelOffset(R.styleable.TextImageView_drawableLeftHeight, 0);
42
        topWidth = typedArray.getDimensionPixelOffset(R.styleable.TextImageView_drawableTopWidth, 0);
43
        topHeight = typedArray.getDimensionPixelOffset(R.styleable.TextImageView_drawableTopHeight, 0);
44
        rightWidth = typedArray.getDimensionPixelOffset(R.styleable.TextImageView_drawableRightWidth, 0);
45
        rightHeight = typedArray.getDimensionPixelOffset(R.styleable.TextImageView_drawableRightHeight, 0);
46
        bottomWidth = typedArray.getDimensionPixelOffset(R.styleable.TextImageView_drawableBottomWidth, 0);
47
        bottomHeight = typedArray.getDimensionPixelOffset(R.styleable.TextImageView_drawableBottomHeight, 0);
48
        typedArray.recycle();
49
        setDrawablesSize();
50
    }
51
52
    private void setDrawablesSize() {
53
        Drawable[] compoundDrawables = getCompoundDrawables();
54
        for (int i = 0; i < compoundDrawables.length; i++) {
55
            switch (i) {
56
                case 0:
57
                    setDrawableBounds(compoundDrawables[0], leftWidth, leftHeight);
58
                    break;
59
                case 1:
60
                    setDrawableBounds(compoundDrawables[1], topWidth, topHeight);
61
                    break;
62
                case 2:
63
                    setDrawableBounds(compoundDrawables[2], rightWidth, rightHeight);
64
                    break;
65
                case 3:
66
                    setDrawableBounds(compoundDrawables[3], bottomWidth, bottomHeight);
67
                    break;
68
                default:
69
                    break;
70
            }
71
        }
72
        setCompoundDrawables(compoundDrawables[0], compoundDrawables[1], compoundDrawables[2], compoundDrawables[3]);
73
    }
74
75
    private void setDrawableBounds(Drawable drawable, int width, int height) {
76
        if (drawable != null) {
77
            double scale = ((double) drawable.getIntrinsicHeight()) / ((double) drawable.getIntrinsicWidth());
78
            drawable.setBounds(0, 0, width, height);
79
            Rect bounds = drawable.getBounds();
80
            // 高宽只给一个值时,自适应
81
            if (bounds.right != 0 | bounds.bottom != 0) {
82
                bounds.right = (int) (bounds.bottom / scale);
83
                drawable.setBounds(bounds);
84
            }
85
            if (bounds.bottom == 0) {
86
                bounds.bottom = (int) (bounds.right * scale);
87
                drawable.setBounds(bounds);
88
            }
89
        }
90
    }
91
92
}

二进制
app/src/main/res/drawable-hdpi/icon_radio_normal.png


二进制
app/src/main/res/drawable-hdpi/icon_radio_selected.png


二进制
app/src/main/res/drawable-mdpi/icon_radio_normal.png


二进制
app/src/main/res/drawable-mdpi/icon_radio_selected.png


二进制
app/src/main/res/drawable-xhdpi/icon_radio_normal.png


二进制
app/src/main/res/drawable-xhdpi/icon_radio_selected.png


二进制
app/src/main/res/drawable-xxhdpi/icon_radio_normal.png


二进制
app/src/main/res/drawable-xxhdpi/icon_radio_selected.png


二进制
app/src/main/res/drawable-xxxhdpi/icon_radio_normal.png


二进制
app/src/main/res/drawable-xxxhdpi/icon_radio_selected.png


+ 8 - 0
app/src/main/res/drawable/bg_add_car_model_shape.xml

@ -0,0 +1,8 @@
1
<?xml version="1.0" encoding="utf-8"?>
2
<shape xmlns:android="http://schemas.android.com/apk/res/android"
3
    android:shape="rectangle">
4
    <corners android:radius="48dp" /> <!-- 圆角大小 -->
5
    <stroke
6
        android:width="1dp"
7
        android:color="#CFE5D6" /> <!-- 边框颜色 -->
8
</shape>

二进制
app/src/main/res/drawable/group_adapter_empty_view_image.png


+ 83 - 0
app/src/main/res/layout/activity_car_brand.xml

@ -0,0 +1,83 @@
1
<?xml version="1.0" encoding="utf-8"?>
2
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
    xmlns:app="http://schemas.android.com/apk/res-auto"
4
    xmlns:tools="http://schemas.android.com/tools"
5
    android:layout_width="match_parent"
6
    android:layout_height="match_parent"
7
    android:background="@color/white"
8
    tools:context=".activity.CarBrandActivity">
9
10
    <androidx.constraintlayout.widget.ConstraintLayout
11
        android:id="@+id/nav_bar"
12
        android:layout_width="match_parent"
13
        android:layout_height="44dp"
14
        app:layout_constraintTop_toTopOf="parent">
15
16
        <TextView
17
            android:id="@+id/nav_title"
18
            android:layout_width="match_parent"
19
            android:layout_height="match_parent"
20
            android:gravity="center"
21
            android:text="品牌"
22
            android:textColor="#444444"
23
            android:textSize="18sp" />
24
25
        <ImageView
26
            android:id="@+id/iv_back"
27
            android:layout_width="wrap_content"
28
            android:layout_height="match_parent"
29
            android:layout_alignParentLeft="true"
30
            android:layout_centerVertical="true"
31
            android:contentDescription="@null"
32
            android:paddingLeft="15dp"
33
            android:paddingRight="15dp"
34
            android:src="@drawable/icon_lvback1119"
35
            app:layout_constraintLeft_toLeftOf="parent" />
36
37
        <View
38
            android:layout_width="match_parent"
39
            android:layout_height="0.5dp"
40
            android:background="@color/ui_titleline"
41
            app:layout_constraintBottom_toBottomOf="parent" />
42
    </androidx.constraintlayout.widget.ConstraintLayout>
43
44
    <com.donkingliang.groupedadapter.widget.StickyHeaderLayout
45
        android:id="@+id/sticky_header_layout"
46
        android:layout_width="match_parent"
47
        android:layout_height="0dp"
48
        app:layout_constraintBottom_toBottomOf="parent"
49
        app:layout_constraintTop_toBottomOf="@+id/nav_bar">
50
51
        <androidx.recyclerview.widget.RecyclerView
52
            android:id="@+id/recycler_view"
53
            android:layout_width="match_parent"
54
            android:layout_height="match_parent" />
55
    </com.donkingliang.groupedadapter.widget.StickyHeaderLayout>
56
57
    <com.electric.chargingpile.view.LetterSideView
58
        android:id="@+id/letter_side_view"
59
        android:layout_width="30dp"
60
        android:layout_height="0dp"
61
        android:background="#F8FBFE"
62
        android:paddingTop="25dp"
63
        android:paddingBottom="25dp"
64
        android:visibility="gone"
65
        app:layout_constraintBottom_toBottomOf="parent"
66
        app:layout_constraintRight_toRightOf="parent"
67
        app:layout_constraintTop_toBottomOf="@+id/nav_bar"
68
        tools:visibility="visible" />
69
70
    <TextView
71
        android:id="@+id/text_view_dialog"
72
        android:layout_width="match_parent"
73
        android:layout_height="0dp"
74
        android:gravity="center"
75
        android:textColor="#CCCCCC"
76
        android:textSize="40sp"
77
        android:visibility="gone"
78
        app:layout_constraintBottom_toBottomOf="parent"
79
        app:layout_constraintTop_toBottomOf="@+id/nav_bar"
80
        tools:text="X"
81
        tools:visibility="visible" />
82
83
</androidx.constraintlayout.widget.ConstraintLayout>

+ 57 - 0
app/src/main/res/layout/activity_car_model.xml

@ -0,0 +1,57 @@
1
<?xml version="1.0" encoding="utf-8"?>
2
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
    xmlns:app="http://schemas.android.com/apk/res-auto"
4
    xmlns:tools="http://schemas.android.com/tools"
5
    android:layout_width="match_parent"
6
    android:layout_height="match_parent"
7
    android:background="@color/white"
8
    tools:context=".activity.CarModelActivity">
9
10
    <androidx.constraintlayout.widget.ConstraintLayout
11
        android:id="@+id/nav_bar"
12
        android:layout_width="match_parent"
13
        android:layout_height="44dp"
14
        app:layout_constraintTop_toTopOf="parent">
15
16
        <TextView
17
            android:id="@+id/nav_title"
18
            android:layout_width="match_parent"
19
            android:layout_height="match_parent"
20
            android:gravity="center"
21
            android:text="车型"
22
            android:textColor="#444444"
23
            android:textSize="18sp" />
24
25
        <ImageView
26
            android:id="@+id/iv_back"
27
            android:layout_width="wrap_content"
28
            android:layout_height="match_parent"
29
            android:layout_alignParentLeft="true"
30
            android:layout_centerVertical="true"
31
            android:contentDescription="@null"
32
            android:paddingLeft="15dp"
33
            android:paddingRight="15dp"
34
            android:src="@drawable/icon_lvback1119"
35
            app:layout_constraintLeft_toLeftOf="parent" />
36
37
        <View
38
            android:layout_width="match_parent"
39
            android:layout_height="0.5dp"
40
            android:background="@color/ui_titleline"
41
            app:layout_constraintBottom_toBottomOf="parent" />
42
    </androidx.constraintlayout.widget.ConstraintLayout>
43
44
    <com.donkingliang.groupedadapter.widget.StickyHeaderLayout
45
        android:id="@+id/sticky_header_layout"
46
        android:layout_width="match_parent"
47
        android:layout_height="0dp"
48
        android:background="#FFF2F6F9"
49
        app:layout_constraintBottom_toBottomOf="parent"
50
        app:layout_constraintTop_toBottomOf="@+id/nav_bar">
51
52
        <androidx.recyclerview.widget.RecyclerView
53
            android:id="@+id/recycler_view"
54
            android:layout_width="match_parent"
55
            android:layout_height="match_parent" />
56
    </com.donkingliang.groupedadapter.widget.StickyHeaderLayout>
57
</androidx.constraintlayout.widget.ConstraintLayout>

+ 363 - 0
app/src/main/res/layout/activity_car_owner_certificate.xml

@ -0,0 +1,363 @@
1
<?xml version="1.0" encoding="utf-8"?>
2
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
    xmlns:app="http://schemas.android.com/apk/res-auto"
4
    xmlns:tools="http://schemas.android.com/tools"
5
    android:layout_width="match_parent"
6
    android:layout_height="match_parent"
7
    android:background="@color/white"
8
    android:focusableInTouchMode="true"
9
    tools:context=".activity.CarOwnerCertificateActivity">
10
11
    <androidx.constraintlayout.widget.ConstraintLayout
12
        android:id="@+id/nav_bar"
13
        android:layout_width="match_parent"
14
        android:layout_height="44dp"
15
        app:layout_constraintTop_toTopOf="parent">
16
17
        <TextView
18
            android:id="@+id/nav_title"
19
            android:layout_width="match_parent"
20
            android:layout_height="match_parent"
21
            android:gravity="center"
22
            android:text="车主认证"
23
            android:textColor="#444444"
24
            android:textSize="18sp" />
25
26
        <ImageView
27
            android:id="@+id/iv_back"
28
            android:layout_width="wrap_content"
29
            android:layout_height="match_parent"
30
            android:layout_alignParentLeft="true"
31
            android:layout_centerVertical="true"
32
            android:contentDescription="@null"
33
            android:paddingLeft="15dp"
34
            android:paddingRight="15dp"
35
            android:src="@drawable/icon_lvback1119"
36
            app:layout_constraintLeft_toLeftOf="parent" />
37
38
        <View
39
            android:layout_width="match_parent"
40
            android:layout_height="0.5dp"
41
            android:background="@color/ui_titleline"
42
            app:layout_constraintBottom_toBottomOf="parent" />
43
    </androidx.constraintlayout.widget.ConstraintLayout>
44
45
    <ScrollView
46
        android:layout_width="match_parent"
47
        android:layout_height="0dp"
48
        android:orientation="vertical"
49
        android:scrollbars="none"
50
        app:layout_constraintBottom_toTopOf="@+id/submit_btn"
51
        app:layout_constraintTop_toBottomOf="@+id/nav_bar">
52
53
        <androidx.constraintlayout.widget.ConstraintLayout
54
            android:layout_width="match_parent"
55
            android:layout_height="wrap_content"
56
            android:paddingLeft="15dp"
57
            android:paddingRight="15dp">
58
59
            <!-- 车型 -->
60
            <androidx.constraintlayout.widget.ConstraintLayout
61
                android:id="@+id/car_model_constraint_layout"
62
                android:layout_width="match_parent"
63
                android:layout_height="0dp"
64
                android:layout_marginTop="15dp"
65
                app:layout_constraintDimensionRatio="h,518:95"
66
                app:layout_constraintTop_toTopOf="parent">
67
68
                <ImageView
69
                    android:id="@+id/add_car_model_icon"
70
                    android:layout_width="match_parent"
71
                    android:layout_height="match_parent"
72
                    android:scaleType="fitXY"
73
                    android:src="@drawable/icon_car_model"
74
                    app:layout_constraintBottom_toBottomOf="parent"
75
                    app:layout_constraintTop_toTopOf="parent" />
76
77
                <TextView
78
                    android:id="@+id/add_car_model_btn"
79
                    android:layout_width="80dp"
80
                    android:layout_height="32dp"
81
                    android:layout_marginRight="15dp"
82
                    android:background="@drawable/bg_add_car_model_shape"
83
                    android:gravity="center"
84
                    android:text="添加车型"
85
                    android:textColor="#506857"
86
                    android:textSize="14sp"
87
                    app:layout_constraintBottom_toBottomOf="parent"
88
                    app:layout_constraintRight_toRightOf="parent"
89
                    app:layout_constraintTop_toTopOf="parent" />
90
            </androidx.constraintlayout.widget.ConstraintLayout>
91
92
            <androidx.constraintlayout.widget.ConstraintLayout
93
                android:id="@+id/car_model_selected_constraint_layout"
94
                android:layout_width="match_parent"
95
                android:layout_height="wrap_content"
96
                android:layout_marginTop="15dp"
97
                android:background="@color/white"
98
                android:visibility="gone"
99
                app:layout_constraintTop_toBottomOf="@+id/car_model_constraint_layout"
100
                tools:background="#cccccc"
101
                tools:visibility="visible">
102
103
                <ImageView
104
                    android:id="@+id/car_icon"
105
                    android:layout_width="95dp"
106
                    android:layout_height="63dp"
107
                    android:scaleType="fitCenter"
108
                    app:layout_constraintBottom_toBottomOf="parent"
109
                    app:layout_constraintLeft_toLeftOf="parent"
110
                    app:layout_constraintTop_toTopOf="parent"
111
                    tools:background="#00ff00" />
112
113
                <TextView
114
                    android:id="@+id/car_name"
115
                    android:layout_width="wrap_content"
116
                    android:layout_height="wrap_content"
117
                    android:layout_marginLeft="10dp"
118
                    android:layout_marginTop="12dp"
119
                    android:textColor="#FF222222"
120
                    android:textSize="14sp"
121
                    app:layout_constraintLeft_toRightOf="@+id/car_icon"
122
                    app:layout_constraintTop_toTopOf="parent"
123
                    tools:text="蔚来ES6" />
124
125
                <TextView
126
                    android:id="@+id/car_series"
127
                    android:layout_width="wrap_content"
128
                    android:layout_height="wrap_content"
129
                    android:layout_marginBottom="10dp"
130
                    android:textColor="#FF0D1120"
131
                    android:textSize="14sp"
132
                    app:layout_constraintBottom_toBottomOf="parent"
133
                    app:layout_constraintLeft_toLeftOf="@+id/car_name"
134
135
                    tools:text="2020款 420KM 运动版" />
136
137
                <ImageView
138
                    android:layout_width="wrap_content"
139
                    android:layout_height="wrap_content"
140
                    android:src="@drawable/icon_right_cursor"
141
                    app:layout_constraintBottom_toBottomOf="parent"
142
                    app:layout_constraintRight_toRightOf="parent"
143
                    app:layout_constraintTop_toTopOf="parent" />
144
145
146
            </androidx.constraintlayout.widget.ConstraintLayout>
147
148
149
            <!-- 行驶证图片 -->
150
            <androidx.constraintlayout.widget.ConstraintLayout
151
                android:id="@+id/driving_license"
152
                android:layout_width="match_parent"
153
                android:layout_height="0dp"
154
                android:layout_marginTop="10dp"
155
                app:layout_constraintDimensionRatio="h,518:315"
156
                app:layout_constraintTop_toBottomOf="@+id/car_model_selected_constraint_layout">
157
158
                <ImageView
159
                    android:id="@+id/driving_license_icon"
160
                    android:layout_width="match_parent"
161
                    android:layout_height="match_parent"
162
                    android:src="@drawable/icon_driving_license" />
163
164
                <TextView
165
                    android:id="@+id/driving_license_text_view"
166
                    android:layout_width="wrap_content"
167
                    android:layout_height="wrap_content"
168
                    android:text="上传行驶证首页(选填)"
169
                    android:textColor="#3D5545"
170
                    android:textSize="14sp"
171
                    app:layout_constraintBottom_toBottomOf="parent"
172
                    app:layout_constraintLeft_toLeftOf="parent"
173
                    app:layout_constraintRight_toRightOf="parent"
174
                    app:layout_constraintTop_toTopOf="parent" />
175
176
                <ImageView
177
                    android:id="@+id/driving_license_upload_icon"
178
                    android:layout_width="wrap_content"
179
                    android:layout_height="wrap_content"
180
                    android:layout_marginBottom="5dp"
181
                    android:src="@drawable/icon_upload"
182
                    app:layout_constraintBottom_toTopOf="@+id/driving_license_text_view"
183
                    app:layout_constraintLeft_toLeftOf="parent"
184
                    app:layout_constraintRight_toRightOf="parent" />
185
186
            </androidx.constraintlayout.widget.ConstraintLayout>
187
188
            <!-- 行驶证信息 -->
189
            <LinearLayout
190
                android:id="@+id/driving_license_info"
191
                android:layout_width="match_parent"
192
                android:layout_height="wrap_content"
193
                android:layout_marginTop="5dp"
194
                android:layout_marginBottom="50dp"
195
                android:orientation="vertical"
196
                app:layout_constraintTop_toBottomOf="@+id/driving_license">
197
198
                <LinearLayout
199
                    android:layout_width="match_parent"
200
                    android:layout_height="50dp"
201
                    android:gravity="center_vertical"
202
                    android:orientation="horizontal">
203
204
                    <TextView
205
                        android:layout_width="90dp"
206
                        android:layout_height="wrap_content"
207
                        android:text="* 车牌号"
208
                        android:textColor="#0D1120"
209
                        android:textSize="14sp"
210
                        android:textStyle="bold" />
211
212
                    <EditText
213
                        android:layout_width="0dp"
214
                        android:layout_height="match_parent"
215
                        android:layout_weight="1"
216
                        android:background="@null"
217
                        android:hint="请输入正确的车牌号"
218
                        android:inputType="text"
219
                        android:textColor="#0D1120"
220
                        android:textColorHint="#CBCBCB"
221
                        android:textSize="14sp" />
222
                </LinearLayout>
223
224
                <View
225
                    android:layout_width="match_parent"
226
                    android:layout_height="1dp"
227
                    android:background="#F8F8F8" />
228
229
                <LinearLayout
230
                    android:layout_width="match_parent"
231
                    android:layout_height="50dp"
232
                    android:gravity="center_vertical"
233
                    android:orientation="horizontal">
234
235
                    <TextView
236
                        android:layout_width="90dp"
237
                        android:layout_height="wrap_content"
238
                        android:text="* 发动机号"
239
                        android:textColor="#0D1120"
240
                        android:textSize="14sp"
241
                        android:textStyle="bold" />
242
243
                    <EditText
244
                        android:layout_width="0dp"
245
                        android:layout_height="match_parent"
246
                        android:layout_weight="1"
247
                        android:background="@null"
248
                        android:hint="请输入发动机号"
249
                        android:inputType="text"
250
                        android:textColor="#0D1120"
251
                        android:textColorHint="#CBCBCB"
252
                        android:textSize="14sp" />
253
                </LinearLayout>
254
255
                <View
256
                    android:layout_width="match_parent"
257
                    android:layout_height="1dp"
258
                    android:background="#F8F8F8" />
259
260
                <LinearLayout
261
                    android:layout_width="match_parent"
262
                    android:layout_height="50dp"
263
                    android:gravity="center_vertical"
264
                    android:orientation="horizontal">
265
266
                    <TextView
267
                        android:layout_width="90dp"
268
                        android:layout_height="wrap_content"
269
                        android:text="注册时间"
270
                        android:textColor="#0D1120"
271
                        android:textSize="14sp"
272
                        android:textStyle="bold" />
273
274
                    <EditText
275
                        android:layout_width="0dp"
276
                        android:layout_height="match_parent"
277
                        android:layout_weight="1"
278
                        android:background="@null"
279
                        android:hint="请输入有效日期"
280
                        android:inputType="text"
281
                        android:textColor="#0D1120"
282
                        android:textColorHint="#CBCBCB"
283
                        android:textSize="14sp" />
284
                </LinearLayout>
285
286
                <View
287
                    android:layout_width="match_parent"
288
                    android:layout_height="1dp"
289
                    android:background="#F8F8F8" />
290
            </LinearLayout>
291
            <!-- 行驶证类型 -->
292
            <LinearLayout
293
                android:id="@+id/driving_license_type"
294
                android:layout_width="match_parent"
295
                android:layout_height="50dp"
296
                android:layout_marginTop="10dp"
297
                android:gravity="center_vertical"
298
                android:orientation="horizontal"
299
                app:layout_constraintTop_toBottomOf="@+id/driving_license_info">
300
301
                <com.electric.chargingpile.view.TextImageView
302
                    android:id="@+id/driving_license_type_first"
303
                    android:layout_width="wrap_content"
304
                    android:layout_height="match_parent"
305
                    android:drawableLeft="@drawable/icon_radio_selected"
306
                    android:drawablePadding="10dp"
307
                    android:gravity="center_vertical"
308
                    android:paddingRight="40dp"
309
                    android:text="自用"
310
                    app:drawableLeftHeight="17dp"
311
                    app:drawableLeftWidth="17dp" />
312
313
                <com.electric.chargingpile.view.TextImageView
314
                    android:id="@+id/driving_license_type_second"
315
                    android:layout_width="wrap_content"
316
                    android:layout_height="match_parent"
317
                    android:drawableLeft="@drawable/icon_radio_normal"
318
                    android:drawablePadding="10dp"
319
                    android:gravity="center_vertical"
320
                    android:paddingRight="40dp"
321
                    android:text="营运"
322
                    app:drawableLeftHeight="17dp"
323
                    app:drawableLeftWidth="17dp" />
324
325
326
                <com.electric.chargingpile.view.TextImageView
327
                    android:id="@+id/driving_license_type_third"
328
                    android:layout_width="wrap_content"
329
                    android:layout_height="match_parent"
330
                    android:drawableLeft="@drawable/icon_radio_normal"
331
                    android:drawablePadding="10dp"
332
                    android:gravity="center_vertical"
333
                    android:paddingRight="40dp"
334
                    android:text="公务"
335
                    app:drawableLeftHeight="17dp"
336
                    app:drawableLeftWidth="17dp" />
337
338
            </LinearLayout>
339
            <!-- 认证说明信息 -->
340
            <TextView
341
                android:layout_width="match_parent"
342
                android:layout_height="wrap_content"
343
                android:layout_marginTop="10dp"
344
                android:layout_marginBottom="30dp"
345
                android:text="认证说明\n\n1.车型信息和行驶证主页为必填项;\n2.最多可认证三款车型;\n3.默认首款认证车型为主车型;\n4.上传行驶证详细页面,并保证所有信息清晰;\n5.认证成功的首个车型可获得50元充电红包。"
346
                android:textColor="#0D1120"
347
                android:textSize="14sp"
348
                app:layout_constraintBottom_toBottomOf="parent"
349
                app:layout_constraintTop_toBottomOf="@+id/driving_license_type" />
350
        </androidx.constraintlayout.widget.ConstraintLayout>
351
    </ScrollView>
352
353
    <Button
354
        android:id="@+id/submit_btn"
355
        android:layout_width="match_parent"
356
        android:layout_height="44dp"
357
        android:background="#00CA42"
358
        android:text="确认提交"
359
        android:textColor="#ffffff"
360
        android:textSize="16sp"
361
        app:layout_constraintBottom_toBottomOf="parent" />
362
363
</androidx.constraintlayout.widget.ConstraintLayout>

+ 81 - 0
app/src/main/res/layout/activity_user_center.xml

@ -479,6 +479,87 @@
479 479
                        android:layout_width="match_parent"
480 480
                        android:layout_height="0.5dp"
481 481
                        android:background="@color/ui_line" />
482
                    <RelativeLayout
483
                        android:id="@+id/rl_car_owner_certificate"
484
                        android:layout_width="fill_parent"
485
                        android:layout_height="44dp"
486
                        android:background="@drawable/item_selector">
487
488
                        <TextView
489
                            android:layout_width="wrap_content"
490
                            android:layout_height="wrap_content"
491
                            android:layout_alignParentStart="true"
492
                            android:layout_alignParentLeft="true"
493
                            android:layout_alignParentTop="true"
494
                            android:layout_alignParentBottom="true"
495
                            android:layout_marginLeft="15dp"
496
                            android:drawableLeft="@drawable/icon_car_user_certificate"
497
                            android:drawablePadding="15dp"
498
                            android:gravity="center_vertical"
499
                            android:text="车主认证"
500
                            android:textColor="@color/ui_62"
501
                            android:textSize="15sp" />
502
503
                        <TextView
504
                            android:layout_width="wrap_content"
505
                            android:layout_height="wrap_content"
506
                            android:layout_alignParentTop="true"
507
                            android:layout_alignParentRight="true"
508
                            android:layout_alignParentBottom="true"
509
                            android:layout_marginRight="15dp"
510
                            android:drawableRight="@drawable/icon_more2_0"
511
                            android:drawablePadding="30px"
512
                            android:gravity="center_vertical"
513
                            android:text=""
514
                            android:textColor="@color/ui_68"
515
                            android:textSize="14sp" />
516
                    </RelativeLayout>
517
                    <View
518
                        android:layout_width="match_parent"
519
                        android:layout_height="0.5dp"
520
                        android:layout_marginLeft="16dp"
521
                        android:background="@color/ui_line" />
522
523
                    <RelativeLayout
524
                        android:id="@+id/rl_publish_price"
525
                        android:layout_width="fill_parent"
526
                        android:layout_height="44dp"
527
                        android:background="@drawable/item_selector">
528
529
                        <TextView
530
                            android:layout_width="wrap_content"
531
                            android:layout_height="wrap_content"
532
                            android:layout_alignParentStart="true"
533
                            android:layout_alignParentLeft="true"
534
                            android:layout_alignParentTop="true"
535
                            android:layout_alignParentBottom="true"
536
                            android:layout_marginLeft="15dp"
537
                            android:drawableLeft="@drawable/icon_publish_price"
538
                            android:drawablePadding="15dp"
539
                            android:gravity="center_vertical"
540
                            android:text="发表成交价"
541
                            android:textColor="@color/ui_62"
542
                            android:textSize="15sp" />
543
544
                        <TextView
545
                            android:layout_width="wrap_content"
546
                            android:layout_height="wrap_content"
547
                            android:layout_alignParentTop="true"
548
                            android:layout_alignParentRight="true"
549
                            android:layout_alignParentBottom="true"
550
                            android:layout_marginRight="15dp"
551
                            android:drawableRight="@drawable/icon_more2_0"
552
                            android:drawablePadding="30px"
553
                            android:gravity="center_vertical"
554
                            android:text=""
555
                            android:textColor="@color/ui_68"
556
                            android:textSize="14sp" />
557
                    </RelativeLayout>
558
                    <View
559
                        android:layout_width="match_parent"
560
                        android:layout_height="0.5dp"
561
                        android:layout_marginLeft="16dp"
562
                        android:background="@color/ui_line" />
482 563
483 564
                    <RelativeLayout
484 565
                        android:id="@+id/rl_chongzhi"

+ 42 - 0
app/src/main/res/layout/adapter_child_car_brand.xml

@ -0,0 +1,42 @@
1
<?xml version="1.0" encoding="utf-8"?>
2
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
    xmlns:app="http://schemas.android.com/apk/res-auto"
4
    xmlns:tools="http://schemas.android.com/tools"
5
    android:layout_width="match_parent"
6
    android:layout_height="55dp"
7
    android:orientation="vertical"
8
    android:paddingLeft="15dp"
9
    android:background="@color/white"
10
    tools:background="#cccccc">
11
12
    <View
13
        android:id="@+id/line"
14
        android:layout_width="match_parent"
15
        android:layout_height="1dp"
16
        android:background="#E6E6E6"
17
        app:layout_constraintTop_toTopOf="parent" />
18
19
    <ImageView
20
        android:id="@+id/icon"
21
        android:layout_width="40dp"
22
        android:layout_height="40dp"
23
        android:scaleType="fitCenter"
24
        app:layout_constraintBottom_toBottomOf="parent"
25
        app:layout_constraintLeft_toLeftOf="parent"
26
        app:layout_constraintTop_toTopOf="parent"
27
        tools:background="#00ff00" />
28
29
    <TextView
30
        android:id="@+id/title"
31
        android:layout_width="wrap_content"
32
        android:layout_height="wrap_content"
33
        android:layout_gravity="center_vertical"
34
        android:layout_marginLeft="10dp"
35
        android:textColor="#FF222222"
36
        android:textSize="14sp"
37
        app:layout_constraintBottom_toBottomOf="parent"
38
        app:layout_constraintLeft_toRightOf="@+id/icon"
39
        app:layout_constraintTop_toTopOf="parent"
40
        tools:text="奥迪" />
41
42
</androidx.constraintlayout.widget.ConstraintLayout>

+ 77 - 0
app/src/main/res/layout/adapter_child_car_model.xml

@ -0,0 +1,77 @@
1
<?xml version="1.0" encoding="utf-8"?>
2
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
    xmlns:app="http://schemas.android.com/apk/res-auto"
4
    xmlns:tools="http://schemas.android.com/tools"
5
    android:layout_width="match_parent"
6
    android:layout_height="100dp"
7
    android:paddingLeft="15dp"
8
    android:background="@color/white"
9
    tools:background="#cccccc">
10
11
    <View
12
        android:id="@+id/line"
13
        android:layout_width="match_parent"
14
        android:layout_height="1dp"
15
        android:background="#E6E6E6"
16
        app:layout_constraintTop_toTopOf="parent" />
17
18
    <ImageView
19
        android:id="@+id/icon"
20
        android:layout_width="120dp"
21
        android:layout_height="80dp"
22
        android:scaleType="fitCenter"
23
        app:layout_constraintBottom_toBottomOf="parent"
24
        app:layout_constraintLeft_toLeftOf="parent"
25
        app:layout_constraintTop_toTopOf="parent"
26
        tools:background="#00ff00" />
27
28
    <TextView
29
        android:id="@+id/title"
30
        android:layout_width="wrap_content"
31
        android:layout_height="wrap_content"
32
        android:layout_gravity="center_vertical"
33
        android:layout_marginLeft="10dp"
34
        android:layout_marginTop="27dp"
35
        android:textColor="#FF222222"
36
        android:textSize="14sp"
37
        app:layout_constraintLeft_toRightOf="@+id/icon"
38
        app:layout_constraintTop_toTopOf="parent"
39
        tools:text="奥迪" />
40
41
    <LinearLayout
42
        android:layout_width="wrap_content"
43
        android:layout_height="wrap_content"
44
        android:layout_marginLeft="10dp"
45
        android:layout_marginBottom="28dp"
46
        android:orientation="horizontal"
47
        app:layout_constraintBottom_toBottomOf="parent"
48
        app:layout_constraintLeft_toRightOf="@+id/icon">
49
50
        <TextView
51
            android:layout_width="wrap_content"
52
            android:layout_height="wrap_content"
53
            android:textColor="#FFE02020"
54
            android:textSize="14sp"
55
            tools:text="33.8-52.3" />
56
57
        <TextView
58
            android:id="@+id/price"
59
            android:layout_width="wrap_content"
60
            android:layout_height="wrap_content"
61
            android:layout_gravity="center_vertical"
62
            android:layout_marginLeft="5dp"
63
            android:text="万"
64
            android:textColor="#FF222222"
65
            android:textSize="12sp" />
66
67
        <TextView
68
            android:id="@+id/endurance"
69
            android:layout_width="wrap_content"
70
            android:layout_height="wrap_content"
71
            android:layout_marginLeft="20dp"
72
            android:textColor="#FF222222"
73
            android:textSize="12sp"
74
            tools:text="续航:300km" />
75
    </LinearLayout>
76
77
</androidx.constraintlayout.widget.ConstraintLayout>

+ 19 - 0
app/src/main/res/layout/adapter_header_car_brand.xml

@ -0,0 +1,19 @@
1
<?xml version="1.0" encoding="utf-8"?>
2
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
    xmlns:tools="http://schemas.android.com/tools"
4
    android:layout_width="match_parent"
5
    android:layout_height="25dp"
6
    android:background="#FFF2F6F9"
7
    android:paddingLeft="15dp"
8
    android:paddingRight="15dp">
9
    
10
    <TextView
11
        android:id="@+id/title"
12
        android:layout_width="match_parent"
13
        android:layout_height="match_parent"
14
        android:gravity="center_vertical"
15
        android:lines="1"
16
        android:textColor="#FF6F6F7D"
17
        android:textSize="12sp"
18
        tools:text="A" />
19
</LinearLayout>

+ 19 - 0
app/src/main/res/layout/adapter_header_car_model.xml

@ -0,0 +1,19 @@
1
<?xml version="1.0" encoding="utf-8"?>
2
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
    xmlns:tools="http://schemas.android.com/tools"
4
    android:layout_width="match_parent"
5
    android:layout_height="25dp"
6
    android:background="#FFF2F6F9"
7
    android:paddingLeft="15dp"
8
    android:paddingRight="15dp">
9
    
10
    <TextView
11
        android:id="@+id/title"
12
        android:layout_width="match_parent"
13
        android:layout_height="match_parent"
14
        android:gravity="center_vertical"
15
        android:lines="1"
16
        android:textColor="#FF6F6F7D"
17
        android:textSize="12sp"
18
        tools:text="A" />
19
</LinearLayout>

+ 13 - 0
app/src/main/res/layout/group_adapter_default_empty_view.xml

@ -0,0 +1,13 @@
1
<?xml version="1.0" encoding="utf-8"?>
2
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
    android:layout_width="match_parent"
4
    android:layout_height="match_parent"
5
    android:orientation="vertical">
6
7
    <ImageView
8
        android:layout_width="wrap_content"
9
        android:layout_height="wrap_content"
10
        android:layout_gravity="center"
11
        android:src="@drawable/group_adapter_empty_view_image"/>
12
13
</FrameLayout>

+ 5 - 0
app/src/main/res/values/strings.xml

@ -208,4 +208,9 @@
208 208
    <string name="personal_shar_info_content">快来分享吧\n小主大家都很期待你的精彩内容哦</string>
209 209
    <string name="query_all_addresses"><u>查看全部目的地</u></string>
210 210
    <string name="query_all_points"><u>查看全部站点</u></string>
211
212
    <item name="type_header" type="integer" />
213
    <item name="type_footer" type="integer" />
214
    <item name="type_child" type="integer" />
215
    <item name="type_empty" type="integer" />
211 216
</resources>

+ 11 - 0
app/src/main/res/values/styles.xml

@ -355,4 +355,15 @@
355 355
        <!--相册文件夹列表选中图标-->
356 356
        <item name="picture.folder_checked_dot">@drawable/picture_orange_oval</item>
357 357
    </style>
358

359
    <declare-styleable name="TextImageView">
360
        <attr name="drawableLeftWidth" format="dimension" />
361
        <attr name="drawableLeftHeight" format="dimension" />
362
        <attr name="drawableTopWidth" format="dimension" />
363
        <attr name="drawableTopHeight" format="dimension" />
364
        <attr name="drawableRightWidth" format="dimension" />
365
        <attr name="drawableRightHeight" format="dimension" />
366
        <attr name="drawableBottomWidth" format="dimension" />
367
        <attr name="drawableBottomHeight" format="dimension" />
368
    </declare-styleable>
358 369
</resources>

remove · b072f07861 - Gogs: Go Git Service
1145873331@qq.com 7 years ago
parent
commit
b072f07861

+ 8 - 9
app/src/main/java/com/electric/chargingpile/activity/GalleryActivity.java

@ -1,8 +1,5 @@
1 1
package com.electric.chargingpile.activity;
2 2
3
import java.util.ArrayList;
4
import java.util.List;
5
6 3
import android.app.Activity;
7 4
import android.content.Context;
8 5
import android.content.Intent;
@ -21,9 +18,11 @@ import com.electric.chargingpile.R;
21 18
import com.electric.chargingpile.util.Bimp;
22 19
import com.electric.chargingpile.util.PublicWayFour;
23 20
import com.electric.chargingpile.util.Res;
24
import com.electric.chargingpile.zoom.PhotoView;
25
import com.electric.chargingpile.zoom.ViewPagerFixed;
21
import com.electric.chargingpile.widge.photoview.PhotoView;
22
import com.electric.chargingpile.widge.photoview.ZoomingViewpager;
26 23
24
import java.util.ArrayList;
25
import java.util.List;
27 26
public class GalleryActivity extends Activity {
28 27
    private Intent intent;
29 28
    // 返回按钮
@ -40,7 +39,7 @@ public class GalleryActivity extends Activity {
40 39
    private int location = 0;
41 40
42 41
    private ArrayList<View> listViews = null;
43
    private ViewPagerFixed pager;
42
    private ZoomingViewpager pager;
44 43
    private MyPageAdapter adapter;
45 44
46 45
    public List<Bitmap> bmp = new ArrayList<Bitmap>();
@ -67,7 +66,7 @@ public class GalleryActivity extends Activity {
67 66
        position = Integer.parseInt(intent.getStringExtra("position"));
68 67
        isShowOkBt();
69 68
        // 为发送按钮设置文字
70
        pager = (ViewPagerFixed) findViewById(Res.getWidgetID("gallery01"));
69
        pager = (ZoomingViewpager) findViewById(Res.getWidgetID("gallery01"));
71 70
        pager.setOnPageChangeListener(pageChangeListener);
72 71
        for (int i = 0; i < Bimp.tempSelectBitmap.size(); i++) {
73 72
            initListViews( Bimp.tempSelectBitmap.get(i).getBitmap() );
@ -206,7 +205,7 @@ public class GalleryActivity extends Activity {
206 205
        }
207 206
208 207
        public void destroyItem(View arg0, int arg1, Object arg2) {
209
            ((ViewPagerFixed) arg0).removeView(listViews.get(arg1 % size));
208
            ((ZoomingViewpager) arg0).removeView(listViews.get(arg1 % size));
210 209
        }
211 210
212 211
        public void finishUpdate(View arg0) {
@ -214,7 +213,7 @@ public class GalleryActivity extends Activity {
214 213
215 214
        public Object instantiateItem(View arg0, int arg1) {
216 215
            try {
217
                ((ViewPagerFixed) arg0).addView(listViews.get(arg1 % size), 0);
216
                ((ZoomingViewpager) arg0).addView(listViews.get(arg1 % size), 0);
218 217
219 218
            } catch (Exception e) {
220 219
            }

+ 14 - 6
app/src/main/java/com/electric/chargingpile/activity/GalleryActivity4Claim.java

@ -22,8 +22,8 @@ import android.widget.TextView;
22 22
import com.electric.chargingpile.util.Bimp;
23 23
import com.electric.chargingpile.util.PublicWay;
24 24
import com.electric.chargingpile.util.Res;
25
import com.electric.chargingpile.zoom.PhotoView;
26
import com.electric.chargingpile.zoom.ViewPagerFixed;
25
import com.electric.chargingpile.widge.photoview.PhotoView;
26
import com.electric.chargingpile.widge.photoview.ZoomingViewpager;
27 27
28 28
public class GalleryActivity4Claim extends Activity {
29 29
@ -42,7 +42,7 @@ public class GalleryActivity4Claim extends Activity {
42 42
    private int location = 0;
43 43
44 44
    private ArrayList<View> listViews = null;
45
    private ViewPagerFixed pager;
45
    private ZoomingViewpager pager;
46 46
    private MyPageAdapter adapter;
47 47
48 48
    public List<Bitmap> bmp = new ArrayList<Bitmap>();
@ -69,7 +69,7 @@ public class GalleryActivity4Claim extends Activity {
69 69
        position = Integer.parseInt(intent.getStringExtra("position"));
70 70
        isShowOkBt();
71 71
        // 为发送按钮设置文字
72
        pager = (ViewPagerFixed) findViewById(Res.getWidgetID("gallery01"));
72
        pager = (ZoomingViewpager) findViewById(Res.getWidgetID("gallery01"));
73 73
        pager.setOnPageChangeListener(pageChangeListener);
74 74
        for (int i = 0; i < Bimp.tempSelectBitmap.size(); i++) {
75 75
            initListViews( Bimp.tempSelectBitmap.get(i).getBitmap() );
@ -84,14 +84,17 @@ public class GalleryActivity4Claim extends Activity {
84 84
85 85
    private OnPageChangeListener pageChangeListener = new OnPageChangeListener() {
86 86
87
        @Override
87 88
        public void onPageSelected(int arg0) {
88 89
            location = arg0;
89 90
        }
90 91
92
        @Override
91 93
        public void onPageScrolled(int arg0, float arg1, int arg2) {
92 94
93 95
        }
94 96
97
        @Override
95 98
        public void onPageScrollStateChanged(int arg0) {
96 99
97 100
        }
@ -120,6 +123,7 @@ public class GalleryActivity4Claim extends Activity {
120 123
    // 删除按钮添加的监听器
121 124
    private class DelListener implements OnClickListener {
122 125
126
        @Override
123 127
        public void onClick(View v) {
124 128
            if (listViews.size() == 1) {
125 129
                Bimp.tempSelectBitmap.clear();
@ -142,6 +146,7 @@ public class GalleryActivity4Claim extends Activity {
142 146
143 147
    // 完成按钮的监听
144 148
    private class GallerySendListener implements OnClickListener {
149
        @Override
145 150
        public void onClick(View v) {
146 151
            finish();
147 152
//            intent.setClass(mContext,ClaimSurveyTwoActivity.class);
@ -199,16 +204,18 @@ public class GalleryActivity4Claim extends Activity {
199 204
            size = listViews == null ? 0 : listViews.size();
200 205
        }
201 206
207
        @Override
202 208
        public int getCount() {
203 209
            return size;
204 210
        }
205 211
212
        @Override
206 213
        public int getItemPosition(Object object) {
207 214
            return POSITION_NONE;
208 215
        }
209 216
210 217
        public void destroyItem(View arg0, int arg1, Object arg2) {
211
            ((ViewPagerFixed) arg0).removeView(listViews.get(arg1 % size));
218
            ((ZoomingViewpager) arg0).removeView(listViews.get(arg1 % size));
212 219
        }
213 220
214 221
        public void finishUpdate(View arg0) {
@ -216,13 +223,14 @@ public class GalleryActivity4Claim extends Activity {
216 223
217 224
        public Object instantiateItem(View arg0, int arg1) {
218 225
            try {
219
                ((ViewPagerFixed) arg0).addView(listViews.get(arg1 % size), 0);
226
                ((ZoomingViewpager) arg0).addView(listViews.get(arg1 % size), 0);
220 227
221 228
            } catch (Exception e) {
222 229
            }
223 230
            return listViews.get(arg1 % size);
224 231
        }
225 232
233
        @Override
226 234
        public boolean isViewFromObject(View arg0, Object arg1) {
227 235
            return arg0 == arg1;
228 236
        }

+ 15 - 15
app/src/main/java/com/electric/chargingpile/activity/GalleryActivityAlter.java

@ -24,8 +24,8 @@ import com.electric.chargingpile.R;
24 24
import com.electric.chargingpile.util.Bimp;
25 25
import com.electric.chargingpile.util.PublicWay;
26 26
import com.electric.chargingpile.util.Res;
27
import com.electric.chargingpile.zoom.PhotoView;
28
import com.electric.chargingpile.zoom.ViewPagerFixed;
27
import com.electric.chargingpile.widge.photoview.PhotoView;
28
import com.electric.chargingpile.widge.photoview.ZoomingViewpager;
29 29
30 30
public class GalleryActivityAlter extends Activity {
31 31
    private Intent intent;
@ -43,7 +43,7 @@ public class GalleryActivityAlter extends Activity {
43 43
    private int location = 0;
44 44
45 45
    private ArrayList<View> listViews = null;
46
    private ViewPagerFixed pager;
46
    private ZoomingViewpager pager;
47 47
    private MyPageAdapter adapter;
48 48
49 49
    public List<Bitmap> bmp = new ArrayList<Bitmap>();
@ -70,7 +70,7 @@ public class GalleryActivityAlter extends Activity {
70 70
        position = Integer.parseInt(intent.getStringExtra("position"));
71 71
        isShowOkBt();
72 72
        // 为发送按钮设置文字
73
        pager = (ViewPagerFixed) findViewById(Res.getWidgetID("gallery01"));
73
        pager = (ZoomingViewpager) findViewById(Res.getWidgetID("gallery01"));
74 74
        pager.setOnPageChangeListener(pageChangeListener);
75 75
        for (int i = 0; i < Bimp.tempSelectBitmap.size(); i++) {
76 76
            initListViews(compressBmpFromBmp(Bimp.tempSelectBitmap.get(i).getBitmap())  );
@ -85,14 +85,17 @@ public class GalleryActivityAlter extends Activity {
85 85
86 86
    private OnPageChangeListener pageChangeListener = new OnPageChangeListener() {
87 87
88
        @Override
88 89
        public void onPageSelected(int arg0) {
89 90
            location = arg0;
90 91
        }
91 92
93
        @Override
92 94
        public void onPageScrolled(int arg0, float arg1, int arg2) {
93 95
94 96
        }
95 97
98
        @Override
96 99
        public void onPageScrollStateChanged(int arg0) {
97 100
98 101
        }
@ -108,19 +111,12 @@ public class GalleryActivityAlter extends Activity {
108 111
                LayoutParams.MATCH_PARENT));
109 112
        listViews.add(img);
110 113
    }
111
112
    // 返回按钮添加的监听器
113
//    private class BackListener implements OnClickListener {
114
//
115
//        public void onClick(View v) {
116
//            intent.setClass(GalleryActivityAlter.this, ImageFileAlter.class);
117
//            startActivity(intent);
118
//        }
119
//    }
114
 
120 115
121 116
    // 删除按钮添加的监听器
122 117
    private class DelListener implements OnClickListener {
123 118
119
        @Override
124 120
        public void onClick(View v) {
125 121
            if (listViews.size() == 1) {
126 122
                Bimp.tempSelectBitmap.clear();
@ -143,6 +139,7 @@ public class GalleryActivityAlter extends Activity {
143 139
144 140
    // 完成按钮的监听
145 141
    private class GallerySendListener implements OnClickListener {
142
        @Override
146 143
        public void onClick(View v) {
147 144
            finish();
148 145
            intent.setClass(GalleryActivityAlter.this,AlterOneActivity.class);
@ -200,16 +197,18 @@ public class GalleryActivityAlter extends Activity {
200 197
            size = listViews == null ? 0 : listViews.size();
201 198
        }
202 199
200
        @Override
203 201
        public int getCount() {
204 202
            return size;
205 203
        }
206 204
205
        @Override
207 206
        public int getItemPosition(Object object) {
208 207
            return POSITION_NONE;
209 208
        }
210 209
211 210
        public void destroyItem(View arg0, int arg1, Object arg2) {
212
            ((ViewPagerFixed) arg0).removeView(listViews.get(arg1 % size));
211
            ((ZoomingViewpager) arg0).removeView(listViews.get(arg1 % size));
213 212
        }
214 213
215 214
        public void finishUpdate(View arg0) {
@ -217,13 +216,14 @@ public class GalleryActivityAlter extends Activity {
217 216
218 217
        public Object instantiateItem(View arg0, int arg1) {
219 218
            try {
220
                ((ViewPagerFixed) arg0).addView(listViews.get(arg1 % size), 0);
219
                ((ZoomingViewpager) arg0).addView(listViews.get(arg1 % size), 0);
221 220
222 221
            } catch (Exception e) {
223 222
            }
224 223
            return listViews.get(arg1 % size);
225 224
        }
226 225
226
        @Override
227 227
        public boolean isViewFromObject(View arg0, Object arg1) {
228 228
            return arg0 == arg1;
229 229
        }

+ 13 - 12
app/src/main/java/com/electric/chargingpile/activity/GalleryActivityCharging.java

@ -4,11 +4,6 @@ package com.electric.chargingpile.activity;
4 4
 * Created by demon on 2017/3/7.
5 5
 */
6 6
7
import java.io.ByteArrayInputStream;
8
import java.io.ByteArrayOutputStream;
9
import java.util.ArrayList;
10
import java.util.List;
11
12 7
import android.app.Activity;
13 8
import android.content.Context;
14 9
import android.content.Intent;
@ -26,11 +21,15 @@ import android.widget.TextView;
26 21
27 22
import com.electric.chargingpile.R;
28 23
import com.electric.chargingpile.util.Bimp;
29
import com.electric.chargingpile.util.PublicWay;
30 24
import com.electric.chargingpile.util.PublicWayONE;
31 25
import com.electric.chargingpile.util.Res;
32
import com.electric.chargingpile.zoom.PhotoView;
33
import com.electric.chargingpile.zoom.ViewPagerFixed;
26
import com.electric.chargingpile.widge.photoview.PhotoView;
27
import com.electric.chargingpile.widge.photoview.ZoomingViewpager;
28
29
import java.io.ByteArrayInputStream;
30
import java.io.ByteArrayOutputStream;
31
import java.util.ArrayList;
32
import java.util.List;
34 33
35 34
public class GalleryActivityCharging extends Activity {
36 35
    private Intent intent;
@ -48,7 +47,7 @@ public class GalleryActivityCharging extends Activity {
48 47
    private int location = 0;
49 48
50 49
    private ArrayList<View> listViews = null;
51
    private ViewPagerFixed pager;
50
    private ZoomingViewpager pager;
52 51
    private MyPageAdapter adapter;
53 52
54 53
    public List<Bitmap> bmp = new ArrayList<Bitmap>();
@ -75,7 +74,7 @@ public class GalleryActivityCharging extends Activity {
75 74
        position = Integer.parseInt(intent.getStringExtra("position"));
76 75
        isShowOkBt();
77 76
        // 为发送按钮设置文字
78
        pager = (ViewPagerFixed) findViewById(Res.getWidgetID("gallery01"));
77
        pager = (ZoomingViewpager) findViewById(Res.getWidgetID("gallery01"));
79 78
        pager.setBackgroundColor(getResources().getColor(R.color.white));
80 79
        pager.setOnPageChangeListener(pageChangeListener);
81 80
        for (int i = 0; i < Bimp.tempSelectBitmap.size(); i++) {
@ -215,21 +214,23 @@ public class GalleryActivityCharging extends Activity {
215 214
        }
216 215
217 216
        public void destroyItem(View arg0, int arg1, Object arg2) {
218
            ((ViewPagerFixed) arg0).removeView(listViews.get(arg1 % size));
217
            ((ZoomingViewpager) arg0).removeView(listViews.get(arg1 % size));
219 218
        }
220 219
221 220
        public void finishUpdate(View arg0) {
222 221
        }
223 222
223
        @Override
224 224
        public Object instantiateItem(View arg0, int arg1) {
225 225
            try {
226
                ((ViewPagerFixed) arg0).addView(listViews.get(arg1 % size), 0);
226
                ((ZoomingViewpager) arg0).addView(listViews.get(arg1 % size), 0);
227 227
228 228
            } catch (Exception e) {
229 229
            }
230 230
            return listViews.get(arg1 % size);
231 231
        }
232 232
233
        @Override
233 234
        public boolean isViewFromObject(View arg0, Object arg1) {
234 235
            return arg0 == arg1;
235 236
        }

+ 9 - 6
app/src/main/java/com/electric/chargingpile/activity/GalleryActivityComment.java

@ -29,8 +29,8 @@ import com.electric.chargingpile.util.Bimp;
29 29
import com.electric.chargingpile.util.PublicWay;
30 30
import com.electric.chargingpile.util.PublicWayONE;
31 31
import com.electric.chargingpile.util.Res;
32
import com.electric.chargingpile.zoom.PhotoView;
33
import com.electric.chargingpile.zoom.ViewPagerFixed;
32
import com.electric.chargingpile.widge.photoview.PhotoView;
33
import com.electric.chargingpile.widge.photoview.ZoomingViewpager;
34 34
35 35
public class GalleryActivityComment extends Activity {
36 36
    private Intent intent;
@ -48,7 +48,7 @@ public class GalleryActivityComment extends Activity {
48 48
    private int location = 0;
49 49
50 50
    private ArrayList<View> listViews = null;
51
    private ViewPagerFixed pager;
51
    private ZoomingViewpager pager;
52 52
    private MyPageAdapter adapter;
53 53
54 54
    public List<Bitmap> bmp = new ArrayList<Bitmap>();
@ -75,7 +75,7 @@ public class GalleryActivityComment extends Activity {
75 75
        position = Integer.parseInt(intent.getStringExtra("position"));
76 76
        isShowOkBt();
77 77
        // 为发送按钮设置文字
78
        pager = (ViewPagerFixed) findViewById(Res.getWidgetID("gallery01"));
78
        pager = (ZoomingViewpager) findViewById(Res.getWidgetID("gallery01"));
79 79
        pager.setBackgroundColor(getResources().getColor(R.color.white));
80 80
        pager.setOnPageChangeListener(pageChangeListener);
81 81
        for (int i = 0; i < Bimp.tempSelectBitmap.size(); i++) {
@ -91,14 +91,17 @@ public class GalleryActivityComment extends Activity {
91 91
92 92
    private OnPageChangeListener pageChangeListener = new OnPageChangeListener() {
93 93
94
        @Override
94 95
        public void onPageSelected(int arg0) {
95 96
            location = arg0;
96 97
        }
97 98
99
        @Override
98 100
        public void onPageScrolled(int arg0, float arg1, int arg2) {
99 101
100 102
        }
101 103
104
        @Override
102 105
        public void onPageScrollStateChanged(int arg0) {
103 106
104 107
        }
@ -215,7 +218,7 @@ public class GalleryActivityComment extends Activity {
215 218
        }
216 219
217 220
        public void destroyItem(View arg0, int arg1, Object arg2) {
218
            ((ViewPagerFixed) arg0).removeView(listViews.get(arg1 % size));
221
            ((ZoomingViewpager) arg0).removeView(listViews.get(arg1 % size));
219 222
        }
220 223
221 224
        public void finishUpdate(View arg0) {
@ -223,7 +226,7 @@ public class GalleryActivityComment extends Activity {
223 226
224 227
        public Object instantiateItem(View arg0, int arg1) {
225 228
            try {
226
                ((ViewPagerFixed) arg0).addView(listViews.get(arg1 % size), 0);
229
                ((ZoomingViewpager) arg0).addView(listViews.get(arg1 % size), 0);
227 230
228 231
            } catch (Exception e) {
229 232
            }

+ 7 - 9
app/src/main/java/com/electric/chargingpile/activity/GalleryActivityFeedback.java

@ -6,10 +6,9 @@ import android.content.Intent;
6 6
import android.graphics.Bitmap;
7 7
import android.graphics.BitmapFactory;
8 8
import android.graphics.Color;
9
import android.os.Bundle;
9 10
import android.support.v4.view.PagerAdapter;
10 11
import android.support.v4.view.ViewPager;
11
import android.support.v7.app.AppCompatActivity;
12
import android.os.Bundle;
13 12
import android.view.View;
14 13
import android.view.ViewGroup;
15 14
import android.widget.RelativeLayout;
@ -18,10 +17,9 @@ import android.widget.TextView;
18 17
import com.electric.chargingpile.R;
19 18
import com.electric.chargingpile.util.Bimp;
20 19
import com.electric.chargingpile.util.PublicWay;
21
import com.electric.chargingpile.util.PublicWayONE;
22 20
import com.electric.chargingpile.util.Res;
23
import com.electric.chargingpile.zoom.PhotoView;
24
import com.electric.chargingpile.zoom.ViewPagerFixed;
21
import com.electric.chargingpile.widge.photoview.PhotoView;
22
import com.electric.chargingpile.widge.photoview.ZoomingViewpager;
25 23
26 24
import java.io.ByteArrayInputStream;
27 25
import java.io.ByteArrayOutputStream;
@ -44,7 +42,7 @@ public class GalleryActivityFeedback extends Activity {
44 42
    private int location = 0;
45 43
46 44
    private ArrayList<View> listViews = null;
47
    private ViewPagerFixed pager;
45
    private ZoomingViewpager pager;
48 46
    private MyPageAdapter adapter;
49 47
50 48
    public List<Bitmap> bmp = new ArrayList<Bitmap>();
@ -71,7 +69,7 @@ public class GalleryActivityFeedback extends Activity {
71 69
        position = Integer.parseInt(intent.getStringExtra("position"));
72 70
        isShowOkBt();
73 71
        // 为发送按钮设置文字
74
        pager = (ViewPagerFixed) findViewById(Res.getWidgetID("gallery01"));
72
        pager = (ZoomingViewpager) findViewById(Res.getWidgetID("gallery01"));
75 73
        pager.setBackgroundColor(getResources().getColor(R.color.white));
76 74
        pager.setOnPageChangeListener(pageChangeListener);
77 75
        for (int i = 0; i < Bimp.tempSelectBitmap.size(); i++) {
@ -191,7 +189,7 @@ public class GalleryActivityFeedback extends Activity {
191 189
        }
192 190
193 191
        public void destroyItem(View arg0, int arg1, Object arg2) {
194
            ((ViewPagerFixed) arg0).removeView(listViews.get(arg1 % size));
192
            ((ZoomingViewpager) arg0).removeView(listViews.get(arg1 % size));
195 193
        }
196 194
197 195
        public void finishUpdate(View arg0) {
@ -199,7 +197,7 @@ public class GalleryActivityFeedback extends Activity {
199 197
200 198
        public Object instantiateItem(View arg0, int arg1) {
201 199
            try {
202
                ((ViewPagerFixed) arg0).addView(listViews.get(arg1 % size), 0);
200
                ((ZoomingViewpager) arg0).addView(listViews.get(arg1 % size), 0);
203 201
204 202
            } catch (Exception e) {
205 203
            }

+ 0 - 19
app/src/main/java/com/electric/chargingpile/zoom/Compat.java

@ -1,19 +0,0 @@
1
package com.electric.chargingpile.zoom;
2
3
import android.os.Build.VERSION;
4
import android.os.Build.VERSION_CODES;
5
import android.view.View;
6
7
public class Compat {
8
	
9
	private static final int SIXTY_FPS_INTERVAL = 1000 / 60;
10
	
11
	public static void postOnAnimation(View view, Runnable runnable) {
12
		if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
13
			SDK16.postOnAnimation(view, runnable);
14
		} else {
15
			view.postDelayed(runnable, SIXTY_FPS_INTERVAL);
16
		}
17
	}
18
19
}

+ 0 - 128
app/src/main/java/com/electric/chargingpile/zoom/IPhotoView.java

@ -1,128 +0,0 @@
1
package com.electric.chargingpile.zoom;
2
3
import android.graphics.RectF;
4
import android.view.View;
5
import android.widget.ImageView;
6
7
8
public interface IPhotoView {
9
    /**
10
     * Returns true if the PhotoView is set to allow zooming of Photos.
11
     *
12
     * @return true if the PhotoView allows zooming.
13
     */
14
    boolean canZoom();
15
16
    /**
17
     * Gets the Display Rectangle of the currently displayed Drawable. The
18
     * Rectangle is relative to this View and includes all scaling and
19
     * translations.
20
     *
21
     * @return - RectF of Displayed Drawable
22
     */
23
    RectF getDisplayRect();
24
25
    /**
26
     * @return The current minimum scale level. What this value represents depends on the current {@link ImageView.ScaleType}.
27
     */
28
    float getMinScale();
29
30
    /**
31
     * @return The current middle scale level. What this value represents depends on the current {@link ImageView.ScaleType}.
32
     */
33
    float getMidScale();
34
35
    /**
36
     * @return The current maximum scale level. What this value represents depends on the current {@link ImageView.ScaleType}.
37
     */
38
    float getMaxScale();
39
40
    /**
41
     * Returns the current scale value
42
     *
43
     * @return float - current scale value
44
     */
45
    float getScale();
46
47
    /**
48
     * Return the current scale type in use by the ImageView.
49
     */
50
    ImageView.ScaleType getScaleType();
51
52
    /**
53
     * Whether to allow the ImageView's parent to intercept the touch event when the photo is scroll to it's horizontal edge.
54
     */
55
    void setAllowParentInterceptOnEdge(boolean allow);
56
57
    /**
58
     * Sets the minimum scale level. What this value represents depends on the current {@link ImageView.ScaleType}.
59
     */
60
    void setMinScale(float minScale);
61
62
    /**
63
     * Sets the middle scale level. What this value represents depends on the current {@link ImageView.ScaleType}.
64
     */
65
    void setMidScale(float midScale);
66
67
    /**
68
     * Sets the maximum scale level. What this value represents depends on the current {@link ImageView.ScaleType}.
69
     */
70
    void setMaxScale(float maxScale);
71
72
    /**
73
     * Register a callback to be invoked when the Photo displayed by this view is long-pressed.
74
     *
75
     * @param listener - Listener to be registered.
76
     */
77
    void setOnLongClickListener(View.OnLongClickListener listener);
78
79
    /**
80
     * Register a callback to be invoked when the Matrix has changed for this
81
     * View. An example would be the user panning or scaling the Photo.
82
     *
83
     * @param listener - Listener to be registered.
84
     */
85
    void setOnMatrixChangeListener(PhotoViewAttacher.OnMatrixChangedListener listener);
86
87
    /**
88
     * Register a callback to be invoked when the Photo displayed by this View
89
     * is tapped with a single tap.
90
     *
91
     * @param listener - Listener to be registered.
92
     */
93
    void setOnPhotoTapListener(PhotoViewAttacher.OnPhotoTapListener listener);
94
95
    /**
96
     * Register a callback to be invoked when the View is tapped with a single
97
     * tap.
98
     *
99
     * @param listener - Listener to be registered.
100
     */
101
    void setOnViewTapListener(PhotoViewAttacher.OnViewTapListener listener);
102
103
    /**
104
     * Controls how the image should be resized or moved to match the size of
105
     * the ImageView. Any scaling or panning will happen within the confines of
106
     * this {@link ImageView.ScaleType}.
107
     *
108
     * @param scaleType - The desired scaling mode.
109
     */
110
    void setScaleType(ImageView.ScaleType scaleType);
111
112
    /**
113
     * Allows you to enable/disable the zoom functionality on the ImageView.
114
     * When disable the ImageView reverts to using the FIT_CENTER matrix.
115
     *
116
     * @param zoomable - Whether the zoom functionality is enabled.
117
     */
118
    void setZoomable(boolean zoomable);
119
120
    /**
121
     * Zooms to the specified scale, around the focal point given.
122
     *
123
     * @param scale  - Scale to zoom to
124
     * @param focalX - X Focus Point
125
     * @param focalY - Y Focus Point
126
     */
127
    void zoomTo(float scale, float focalX, float focalY);
128
}

+ 0 - 165
app/src/main/java/com/electric/chargingpile/zoom/PhotoView.java

@ -1,165 +0,0 @@
1
package com.electric.chargingpile.zoom;
2
3
4
import android.content.Context;
5
import android.graphics.RectF;
6
import android.graphics.drawable.Drawable;
7
import android.net.Uri;
8
import android.util.AttributeSet;
9
import android.widget.ImageView;
10
11
import com.electric.chargingpile.zoom.PhotoViewAttacher.OnMatrixChangedListener;
12
import com.electric.chargingpile.zoom.PhotoViewAttacher.OnPhotoTapListener;
13
import com.electric.chargingpile.zoom.PhotoViewAttacher.OnViewTapListener;
14
15
public class PhotoView extends ImageView implements IPhotoView {
16
17
	private final PhotoViewAttacher mAttacher;
18
19
	private ScaleType mPendingScaleType;
20
21
	public PhotoView(Context context) {
22
		this(context, null);
23
	}
24
25
	public PhotoView(Context context, AttributeSet attr) {
26
		this(context, attr, 0);
27
	}
28
	
29
	public PhotoView(Context context, AttributeSet attr, int defStyle) {
30
		super(context, attr, defStyle);
31
		super.setScaleType(ScaleType.MATRIX);
32
		mAttacher = new PhotoViewAttacher(this);
33
34
		if (null != mPendingScaleType) {
35
			setScaleType(mPendingScaleType);
36
			mPendingScaleType = null;
37
		}
38
	}
39
40
	@Override
41
	public boolean canZoom() {
42
		return mAttacher.canZoom();
43
	}
44
45
	@Override
46
	public RectF getDisplayRect() {
47
		return mAttacher.getDisplayRect();
48
	}
49
50
	@Override
51
	public float getMinScale() {
52
		return mAttacher.getMinScale();
53
	}
54
55
	@Override
56
	public float getMidScale() {
57
		return mAttacher.getMidScale();
58
	}
59
60
	@Override
61
	public float getMaxScale() {
62
		return mAttacher.getMaxScale();
63
	}
64
65
	@Override
66
	public float getScale() {
67
		return mAttacher.getScale();
68
	}
69
70
	@Override
71
	public ScaleType getScaleType() {
72
		return mAttacher.getScaleType();
73
	}
74
75
    @Override
76
    public void setAllowParentInterceptOnEdge(boolean allow) {
77
        mAttacher.setAllowParentInterceptOnEdge(allow);
78
    }
79
80
    @Override
81
	public void setMinScale(float minScale) {
82
		mAttacher.setMinScale(minScale);
83
	}
84
85
	@Override
86
	public void setMidScale(float midScale) {
87
		mAttacher.setMidScale(midScale);
88
	}
89
90
	@Override
91
	public void setMaxScale(float maxScale) {
92
		mAttacher.setMaxScale(maxScale);
93
	}
94
95
	@Override
96
	// setImageBitmap calls through to this method
97
	public void setImageDrawable(Drawable drawable) {
98
		super.setImageDrawable(drawable);
99
		if (null != mAttacher) {
100
			mAttacher.update();
101
		}
102
	}
103
104
	@Override
105
	public void setImageResource(int resId) {
106
		super.setImageResource(resId);
107
		if (null != mAttacher) {
108
			mAttacher.update();
109
		}
110
	}
111
112
	@Override
113
	public void setImageURI(Uri uri) {
114
		super.setImageURI(uri);
115
		if (null != mAttacher) {
116
			mAttacher.update();
117
		}
118
	}
119
120
	@Override
121
	public void setOnMatrixChangeListener(OnMatrixChangedListener listener) {
122
		mAttacher.setOnMatrixChangeListener(listener);
123
	}
124
125
	@Override
126
	public void setOnLongClickListener(OnLongClickListener l) {
127
		mAttacher.setOnLongClickListener(l);
128
	}
129
130
	@Override
131
	public void setOnPhotoTapListener(OnPhotoTapListener listener) {
132
		mAttacher.setOnPhotoTapListener(listener);
133
	}
134
135
	@Override
136
	public void setOnViewTapListener(OnViewTapListener listener) {
137
		mAttacher.setOnViewTapListener(listener);
138
	}
139
140
	@Override
141
	public void setScaleType(ScaleType scaleType) {
142
		if (null != mAttacher) {
143
			mAttacher.setScaleType(scaleType);
144
		} else {
145
			mPendingScaleType = scaleType;
146
		}
147
	}
148
149
	@Override
150
	public void setZoomable(boolean zoomable) {
151
		mAttacher.setZoomable(zoomable);
152
	}
153
154
	@Override
155
	public void zoomTo(float scale, float focalX, float focalY) {
156
		mAttacher.zoomTo(scale, focalX, focalY);
157
	}
158
159
	@Override
160
	protected void onDetachedFromWindow() {
161
		mAttacher.cleanup();
162
		super.onDetachedFromWindow();
163
	}
164
165
}

+ 0 - 990
app/src/main/java/com/electric/chargingpile/zoom/PhotoViewAttacher.java

@ -1,990 +0,0 @@
1
package com.electric.chargingpile.zoom;
2
3
import android.annotation.SuppressLint;
4
import android.content.Context;
5
import android.graphics.Matrix;
6
import android.graphics.Matrix.ScaleToFit;
7
import android.graphics.RectF;
8
import android.graphics.drawable.Drawable;
9
import android.os.Build.VERSION;
10
import android.os.Build.VERSION_CODES;
11
import android.util.Log;
12
import android.view.GestureDetector;
13
import android.view.MotionEvent;
14
import android.view.View;
15
import android.view.View.OnLongClickListener;
16
import android.view.ViewTreeObserver;
17
import android.widget.ImageView;
18
import android.widget.ImageView.ScaleType;
19
import java.lang.ref.WeakReference;
20
21
public class PhotoViewAttacher implements IPhotoView, View.OnTouchListener,
22
		VersionedGestureDetector.OnGestureListener,
23
		GestureDetector.OnDoubleTapListener,
24
		ViewTreeObserver.OnGlobalLayoutListener {
25
26
	static final String LOG_TAG = "PhotoViewAttacher";
27
28
	// let debug flag be dynamic, but still Proguard can be used to remove from
29
	// release builds
30
	static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG);
31
32
	static final int EDGE_NONE = -1;
33
	static final int EDGE_LEFT = 0;
34
	static final int EDGE_RIGHT = 1;
35
	static final int EDGE_BOTH = 2;
36
37
	public static final float DEFAULT_MAX_SCALE = 3.0f;
38
	public static final float DEFAULT_MID_SCALE = 1.75f;
39
	public static final float DEFAULT_MIN_SCALE = 1.0f;
40
41
	private float mMinScale = DEFAULT_MIN_SCALE;
42
	private float mMidScale = DEFAULT_MID_SCALE;
43
	private float mMaxScale = DEFAULT_MAX_SCALE;
44
45
	private boolean mAllowParentInterceptOnEdge = true;
46
47
	private static void checkZoomLevels(float minZoom, float midZoom,
48
			float maxZoom) {
49
		if (minZoom >= midZoom) {
50
			throw new IllegalArgumentException(
51
					"MinZoom should be less than MidZoom");
52
		} else if (midZoom >= maxZoom) {
53
			throw new IllegalArgumentException(
54
					"MidZoom should be less than MaxZoom");
55
		}
56
	}
57
58
	/**
59
	 * @return true if the ImageView exists, and it's Drawable existss
60
	 */
61
	private static boolean hasDrawable(ImageView imageView) {
62
		return null != imageView && null != imageView.getDrawable();
63
	}
64
65
	/**
66
	 * @return true if the ScaleType is supported.
67
	 */
68
	private static boolean isSupportedScaleType(final ScaleType scaleType) {
69
		if (null == scaleType) {
70
			return false;
71
		}
72
73
		switch (scaleType) {
74
		case MATRIX:
75
			throw new IllegalArgumentException(scaleType.name()
76
					+ " is not supported in PhotoView");
77
78
		default:
79
			return true;
80
		}
81
	}
82
83
	/**
84
	 * Set's the ImageView's ScaleType to Matrix.
85
	 */
86
	private static void setImageViewScaleTypeMatrix(ImageView imageView) {
87
		if (null != imageView) {
88
			if (imageView instanceof PhotoView) {
89
				/**
90
				 * PhotoView sets it's own ScaleType to Matrix, then diverts all
91
				 * calls setScaleType to this.setScaleType. Basically we don't
92
				 * need to do anything here
93
				 */
94
			} else {
95
				imageView.setScaleType(ScaleType.MATRIX);
96
			}
97
		}
98
	}
99
100
	private WeakReference<ImageView> mImageView;
101
	private ViewTreeObserver mViewTreeObserver;
102
103
	// Gesture Detectors
104
	private GestureDetector mGestureDetector;
105
	private VersionedGestureDetector mScaleDragDetector;
106
107
	// These are set so we don't keep allocating them on the heap
108
	private final Matrix mBaseMatrix = new Matrix();
109
	private final Matrix mDrawMatrix = new Matrix();
110
	private final Matrix mSuppMatrix = new Matrix();
111
	private final RectF mDisplayRect = new RectF();
112
	private final float[] mMatrixValues = new float[9];
113
114
	// Listeners
115
	private OnMatrixChangedListener mMatrixChangeListener;
116
	private OnPhotoTapListener mPhotoTapListener;
117
	private OnViewTapListener mViewTapListener;
118
	private OnLongClickListener mLongClickListener;
119
120
	private int mIvTop, mIvRight, mIvBottom, mIvLeft;
121
	private FlingRunnable mCurrentFlingRunnable;
122
	private int mScrollEdge = EDGE_BOTH;
123
124
	private boolean mZoomEnabled;
125
	private ScaleType mScaleType = ScaleType.FIT_CENTER;
126
127
	public PhotoViewAttacher(ImageView imageView) {
128
		mImageView = new WeakReference<ImageView>(imageView);
129
130
		imageView.setOnTouchListener(this);
131
132
		mViewTreeObserver = imageView.getViewTreeObserver();
133
		mViewTreeObserver.addOnGlobalLayoutListener(this);
134
135
		// Make sure we using MATRIX Scale Type
136
		setImageViewScaleTypeMatrix(imageView);
137
138
		if (!imageView.isInEditMode()) {
139
			// Create Gesture Detectors...
140
			mScaleDragDetector = VersionedGestureDetector.newInstance(
141
					imageView.getContext(), this);
142
143
			mGestureDetector = new GestureDetector(imageView.getContext(),
144
					new GestureDetector.SimpleOnGestureListener() {
145
146
						// forward long click listener
147
						@Override
148
						public void onLongPress(MotionEvent e) {
149
							if (null != mLongClickListener) {
150
								mLongClickListener.onLongClick(mImageView.get());
151
							}
152
						}
153
					});
154
155
			mGestureDetector.setOnDoubleTapListener(this);
156
157
			// Finally, update the UI so that we're zoomable
158
			setZoomable(true);
159
		}
160
	}
161
162
	@Override
163
	public final boolean canZoom() {
164
		return mZoomEnabled;
165
	}
166
167
	/**
168
	 * Clean-up the resources attached to this object. This needs to be called
169
	 * when the ImageView is no longer used. A good example is from
170
	 * {@link View#onDetachedFromWindow()} or from
171
	 * {@link android.app.Activity#onDestroy()}. This is automatically called if
172
	 */
173
	@SuppressLint("NewApi")
174
	// @SuppressWarnings("deprecation")
175
	// public final void cleanup() {
176
	// if (null != mImageView) {
177
	// mImageView.get().getViewTreeObserver().removeGlobalOnLayoutListener(this);
178
	// }
179
	// mViewTreeObserver = null;
180
	//
181
	// // Clear listeners too
182
	// mMatrixChangeListener = null;
183
	// mPhotoTapListener = null;
184
	// mViewTapListener = null;
185
	//
186
	// // Finally, clear ImageView
187
	// mImageView = null;
188
	// }
189
	@SuppressWarnings("deprecation")
190
	public final void cleanup() {
191
		if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
192
			if (null != mImageView) {
193
				mImageView.get().getViewTreeObserver()
194
						.removeOnGlobalLayoutListener(this);
195
			}
196
197
			if (null != mViewTreeObserver && mViewTreeObserver.isAlive()) {
198
				mViewTreeObserver.removeOnGlobalLayoutListener(this);
199
200
				mViewTreeObserver = null;
201
202
				// Clear listeners too
203
				mMatrixChangeListener = null;
204
				mPhotoTapListener = null;
205
				mViewTapListener = null;
206
				// Finally, clear ImageView
207
				mImageView = null;
208
			}
209
210
		} else {
211
			if (null != mImageView) {
212
				mImageView.get().getViewTreeObserver()
213
						.removeGlobalOnLayoutListener(this);
214
			}
215
216
			if (null != mViewTreeObserver && mViewTreeObserver.isAlive()) {
217
				mViewTreeObserver.removeGlobalOnLayoutListener(this);
218
219
				mViewTreeObserver = null;
220
221
				// Clear listeners too
222
				mMatrixChangeListener = null;
223
				mPhotoTapListener = null;
224
				mViewTapListener = null;
225
				// Finally, clear ImageView
226
				mImageView = null;
227
			}
228
		}
229
	}
230
231
	@Override
232
	public final RectF getDisplayRect() {
233
		checkMatrixBounds();
234
		return getDisplayRect(getDisplayMatrix());
235
	}
236
237
	public final ImageView getImageView() {
238
		ImageView imageView = null;
239
240
		if (null != mImageView) {
241
			imageView = mImageView.get();
242
		}
243
244
		// If we don't have an ImageView, call cleanup()
245
		if (null == imageView) {
246
			cleanup();
247
			throw new IllegalStateException(
248
					"ImageView no longer exists. You should not use this PhotoViewAttacher any more.");
249
		}
250
251
		return imageView;
252
	}
253
254
	@Override
255
	public float getMinScale() {
256
		return mMinScale;
257
	}
258
259
	@Override
260
	public float getMidScale() {
261
		return mMidScale;
262
	}
263
264
	@Override
265
	public float getMaxScale() {
266
		return mMaxScale;
267
	}
268
269
	@Override
270
	public final float getScale() {
271
		return getValue(mSuppMatrix, Matrix.MSCALE_X);
272
	}
273
274
	@Override
275
	public final ScaleType getScaleType() {
276
		return mScaleType;
277
	}
278
279
	@Override
280
	public final boolean onDoubleTap(MotionEvent ev) {
281
		try {
282
			float scale = getScale();
283
			float x = ev.getX();
284
			float y = ev.getY();
285
286
			if (scale < mMidScale) {
287
				zoomTo(mMidScale, x, y);
288
			} else if (scale >= mMidScale && scale < mMaxScale) {
289
				zoomTo(mMaxScale, x, y);
290
			} else {
291
				zoomTo(mMinScale, x, y);
292
			}
293
		} catch (ArrayIndexOutOfBoundsException e) {
294
			// Can sometimes happen when getX() and getY() is called
295
		}
296
297
		return true;
298
	}
299
300
	@Override
301
	public final boolean onDoubleTapEvent(MotionEvent e) {
302
		// Wait for the confirmed onDoubleTap() instead
303
		return false;
304
	}
305
306
	@Override
307
	public final void onDrag(float dx, float dy) {
308
		if (DEBUG) {
309
			Log.d(LOG_TAG, String.format("onDrag: dx: %.2f. dy: %.2f", dx, dy));
310
		}
311
312
		ImageView imageView = getImageView();
313
314
		if (null != imageView && hasDrawable(imageView)) {
315
			mSuppMatrix.postTranslate(dx, dy);
316
			checkAndDisplayMatrix();
317
318
			/**
319
			 * Here we decide whether to let the ImageView's parent to start
320
			 * taking over the touch event.
321
			 * 
322
			 * First we check whether this function is enabled. We never want
323
			 * the parent to take over if we're scaling. We then check the edge
324
			 * we're on, and the direction of the scroll (i.e. if we're pulling
325
			 * against the edge, aka 'overscrolling', let the parent take over).
326
			 */
327
			if (mAllowParentInterceptOnEdge && !mScaleDragDetector.isScaling()) {
328
				if (mScrollEdge == EDGE_BOTH
329
						|| (mScrollEdge == EDGE_LEFT && dx >= 1f)
330
						|| (mScrollEdge == EDGE_RIGHT && dx <= -1f)) {
331
					imageView.getParent().requestDisallowInterceptTouchEvent(
332
							false);
333
				}
334
			}
335
		}
336
	}
337
338
	@Override
339
	public final void onFling(float startX, float startY, float velocityX,
340
			float velocityY) {
341
		if (DEBUG) {
342
			Log.d(LOG_TAG, "onFling. sX: " + startX + " sY: " + startY
343
					+ " Vx: " + velocityX + " Vy: " + velocityY);
344
		}
345
346
		ImageView imageView = getImageView();
347
		if (hasDrawable(imageView)) {
348
			mCurrentFlingRunnable = new FlingRunnable(imageView.getContext());
349
			mCurrentFlingRunnable.fling(imageView.getWidth(),
350
					imageView.getHeight(), (int) velocityX, (int) velocityY);
351
			imageView.post(mCurrentFlingRunnable);
352
		}
353
	}
354
355
	@Override
356
	public final void onGlobalLayout() {
357
		ImageView imageView = getImageView();
358
359
		if (null != imageView && mZoomEnabled) {
360
			final int top = imageView.getTop();
361
			final int right = imageView.getRight();
362
			final int bottom = imageView.getBottom();
363
			final int left = imageView.getLeft();
364
365
			/**
366
			 * We need to check whether the ImageView's bounds have changed.
367
			 * This would be easier if we targeted API 11+ as we could just use
368
			 * View.OnLayoutChangeListener. Instead we have to replicate the
369
			 * work, keeping track of the ImageView's bounds and then checking
370
			 * if the values change.
371
			 */
372
			if (top != mIvTop || bottom != mIvBottom || left != mIvLeft
373
					|| right != mIvRight) {
374
				// Update our base matrix, as the bounds have changed
375
				updateBaseMatrix(imageView.getDrawable());
376
377
				// Update values as something has changed
378
				mIvTop = top;
379
				mIvRight = right;
380
				mIvBottom = bottom;
381
				mIvLeft = left;
382
			}
383
		}
384
	}
385
386
	@Override
387
	public final void onScale(float scaleFactor, float focusX, float focusY) {
388
		if (DEBUG) {
389
			Log.d(LOG_TAG, String.format(
390
					"onScale: scale: %.2f. fX: %.2f. fY: %.2f", scaleFactor,
391
					focusX, focusY));
392
		}
393
394
		if (hasDrawable(getImageView())
395
				&& (getScale() < mMaxScale || scaleFactor < 1f)) {
396
			mSuppMatrix.postScale(scaleFactor, scaleFactor, focusX, focusY);
397
			checkAndDisplayMatrix();
398
		}
399
	}
400
401
	@Override
402
	public final boolean onSingleTapConfirmed(MotionEvent e) {
403
		ImageView imageView = getImageView();
404
405
		if (null != imageView) {
406
			if (null != mPhotoTapListener) {
407
				final RectF displayRect = getDisplayRect();
408
409
				if (null != displayRect) {
410
					final float x = e.getX(), y = e.getY();
411
412
					// Check to see if the user tapped on the photo
413
					if (displayRect.contains(x, y)) {
414
415
						float xResult = (x - displayRect.left)
416
								/ displayRect.width();
417
						float yResult = (y - displayRect.top)
418
								/ displayRect.height();
419
420
						mPhotoTapListener.onPhotoTap(imageView, xResult,
421
								yResult);
422
						return true;
423
					}
424
				}
425
			}
426
			if (null != mViewTapListener) {
427
				mViewTapListener.onViewTap(imageView, e.getX(), e.getY());
428
			}
429
		}
430
431
		return false;
432
	}
433
434
	@Override
435
	public final boolean onTouch(View v, MotionEvent ev) {
436
		boolean handled = false;
437
438
		if (mZoomEnabled) {
439
			switch (ev.getAction()) {
440
			case MotionEvent.ACTION_DOWN:
441
				// First, disable the Parent from intercepting the touch
442
				// event
443
				v.getParent().requestDisallowInterceptTouchEvent(true);
444
445
				// If we're flinging, and the user presses down, cancel
446
				// fling
447
				cancelFling();
448
				break;
449
450
			case MotionEvent.ACTION_CANCEL:
451
			case MotionEvent.ACTION_UP:
452
				// If the user has zoomed less than min scale, zoom back
453
				// to min scale
454
				if (getScale() < mMinScale) {
455
					RectF rect = getDisplayRect();
456
					if (null != rect) {
457
						v.post(new AnimatedZoomRunnable(getScale(), mMinScale,
458
								rect.centerX(), rect.centerY()));
459
						handled = true;
460
					}
461
				}
462
				break;
463
			}
464
465
			// Check to see if the user double tapped
466
			if (null != mGestureDetector && mGestureDetector.onTouchEvent(ev)) {
467
				handled = true;
468
			}
469
470
			// Finally, try the Scale/Drag detector
471
			if (null != mScaleDragDetector
472
					&& mScaleDragDetector.onTouchEvent(ev)) {
473
				handled = true;
474
			}
475
		}
476
477
		return handled;
478
	}
479
480
	@Override
481
	public void setAllowParentInterceptOnEdge(boolean allow) {
482
		mAllowParentInterceptOnEdge = allow;
483
	}
484
485
	@Override
486
	public void setMinScale(float minScale) {
487
		checkZoomLevels(minScale, mMidScale, mMaxScale);
488
		mMinScale = minScale;
489
	}
490
491
	@Override
492
	public void setMidScale(float midScale) {
493
		checkZoomLevels(mMinScale, midScale, mMaxScale);
494
		mMidScale = midScale;
495
	}
496
497
	@Override
498
	public void setMaxScale(float maxScale) {
499
		checkZoomLevels(mMinScale, mMidScale, maxScale);
500
		mMaxScale = maxScale;
501
	}
502
503
	@Override
504
	public final void setOnLongClickListener(OnLongClickListener listener) {
505
		mLongClickListener = listener;
506
	}
507
508
	@Override
509
	public final void setOnMatrixChangeListener(OnMatrixChangedListener listener) {
510
		mMatrixChangeListener = listener;
511
	}
512
513
	@Override
514
	public final void setOnPhotoTapListener(OnPhotoTapListener listener) {
515
		mPhotoTapListener = listener;
516
	}
517
518
	@Override
519
	public final void setOnViewTapListener(OnViewTapListener listener) {
520
		mViewTapListener = listener;
521
	}
522
523
	@Override
524
	public final void setScaleType(ScaleType scaleType) {
525
		if (isSupportedScaleType(scaleType) && scaleType != mScaleType) {
526
			mScaleType = scaleType;
527
528
			// Finally update
529
			update();
530
		}
531
	}
532
533
	@Override
534
	public final void setZoomable(boolean zoomable) {
535
		mZoomEnabled = zoomable;
536
		update();
537
	}
538
539
	public final void update() {
540
		ImageView imageView = getImageView();
541
542
		if (null != imageView) {
543
			if (mZoomEnabled) {
544
				// Make sure we using MATRIX Scale Type
545
				setImageViewScaleTypeMatrix(imageView);
546
547
				// Update the base matrix using the current drawable
548
				updateBaseMatrix(imageView.getDrawable());
549
			} else {
550
				// Reset the Matrix...
551
				resetMatrix();
552
			}
553
		}
554
	}
555
556
	@Override
557
	public final void zoomTo(float scale, float focalX, float focalY) {
558
		ImageView imageView = getImageView();
559
560
		if (null != imageView) {
561
			imageView.post(new AnimatedZoomRunnable(getScale(), scale, focalX,
562
					focalY));
563
		}
564
	}
565
566
	protected Matrix getDisplayMatrix() {
567
		mDrawMatrix.set(mBaseMatrix);
568
		mDrawMatrix.postConcat(mSuppMatrix);
569
		return mDrawMatrix;
570
	}
571
572
	private void cancelFling() {
573
		if (null != mCurrentFlingRunnable) {
574
			mCurrentFlingRunnable.cancelFling();
575
			mCurrentFlingRunnable = null;
576
		}
577
	}
578
579
	/**
580
	 * Helper method that simply checks the Matrix, and then displays the result
581
	 */
582
	private void checkAndDisplayMatrix() {
583
		checkMatrixBounds();
584
		setImageViewMatrix(getDisplayMatrix());
585
	}
586
587
	private void checkImageViewScaleType() {
588
		ImageView imageView = getImageView();
589
590
		/**
591
		 * PhotoView's getScaleType() will just divert to this.getScaleType() so
592
		 * only call if we're not attached to a PhotoView.
593
		 */
594
		if (null != imageView && !(imageView instanceof PhotoView)) {
595
			if (imageView.getScaleType() != ScaleType.MATRIX) {
596
				throw new IllegalStateException(
597
						"The ImageView's ScaleType has been changed since attaching a PhotoViewAttacher");
598
			}
599
		}
600
	}
601
602
	private void checkMatrixBounds() {
603
		final ImageView imageView = getImageView();
604
		if (null == imageView) {
605
			return;
606
		}
607
608
		final RectF rect = getDisplayRect(getDisplayMatrix());
609
		if (null == rect) {
610
			return;
611
		}
612
613
		final float height = rect.height(), width = rect.width();
614
		float deltaX = 0, deltaY = 0;
615
616
		final int viewHeight = imageView.getHeight();
617
		if (height <= viewHeight) {
618
			switch (mScaleType) {
619
			case FIT_START:
620
				deltaY = -rect.top;
621
				break;
622
			case FIT_END:
623
				deltaY = viewHeight - height - rect.top;
624
				break;
625
			default:
626
				deltaY = (viewHeight - height) / 2 - rect.top;
627
				break;
628
			}
629
		} else if (rect.top > 0) {
630
			deltaY = -rect.top;
631
		} else if (rect.bottom < viewHeight) {
632
			deltaY = viewHeight - rect.bottom;
633
		}
634
635
		final int viewWidth = imageView.getWidth();
636
		if (width <= viewWidth) {
637
			switch (mScaleType) {
638
			case FIT_START:
639
				deltaX = -rect.left;
640
				break;
641
			case FIT_END:
642
				deltaX = viewWidth - width - rect.left;
643
				break;
644
			default:
645
				deltaX = (viewWidth - width) / 2 - rect.left;
646
				break;
647
			}
648
			mScrollEdge = EDGE_BOTH;
649
		} else if (rect.left > 0) {
650
			mScrollEdge = EDGE_LEFT;
651
			deltaX = -rect.left;
652
		} else if (rect.right < viewWidth) {
653
			deltaX = viewWidth - rect.right;
654
			mScrollEdge = EDGE_RIGHT;
655
		} else {
656
			mScrollEdge = EDGE_NONE;
657
		}
658
659
		// Finally actually translate the matrix
660
		mSuppMatrix.postTranslate(deltaX, deltaY);
661
	}
662
663
	/**
664
	 * Helper method that maps the supplied Matrix to the current Drawable
665
	 * 
666
	 * @param matrix
667
	 *            - Matrix to map Drawable against
668
	 * @return RectF - Displayed Rectangle
669
	 */
670
	private RectF getDisplayRect(Matrix matrix) {
671
		ImageView imageView = getImageView();
672
673
		if (null != imageView) {
674
			Drawable d = imageView.getDrawable();
675
			if (null != d) {
676
				mDisplayRect.set(0, 0, d.getIntrinsicWidth(),
677
						d.getIntrinsicHeight());
678
				matrix.mapRect(mDisplayRect);
679
				return mDisplayRect;
680
			}
681
		}
682
		return null;
683
	}
684
685
	/**
686
	 * Helper method that 'unpacks' a Matrix and returns the required value
687
	 * 
688
	 * @param matrix
689
	 *            - Matrix to unpack
690
	 * @param whichValue
691
	 *            - Which value from Matrix.M* to return
692
	 * @return float - returned value
693
	 */
694
	private float getValue(Matrix matrix, int whichValue) {
695
		matrix.getValues(mMatrixValues);
696
		return mMatrixValues[whichValue];
697
	}
698
699
	/**
700
	 * Resets the Matrix back to FIT_CENTER, and then displays it.s
701
	 */
702
	private void resetMatrix() {
703
		mSuppMatrix.reset();
704
		setImageViewMatrix(getDisplayMatrix());
705
		checkMatrixBounds();
706
	}
707
708
	private void setImageViewMatrix(Matrix matrix) {
709
		ImageView imageView = getImageView();
710
		if (null != imageView) {
711
712
			checkImageViewScaleType();
713
			imageView.setImageMatrix(matrix);
714
715
			// Call MatrixChangedListener if needed
716
			if (null != mMatrixChangeListener) {
717
				RectF displayRect = getDisplayRect(matrix);
718
				if (null != displayRect) {
719
					mMatrixChangeListener.onMatrixChanged(displayRect);
720
				}
721
			}
722
		}
723
	}
724
725
	/**
726
	 * Calculate Matrix for FIT_CENTER
727
	 * 
728
	 * @param d
729
	 *            - Drawable being displayed
730
	 */
731
	private void updateBaseMatrix(Drawable d) {
732
		ImageView imageView = getImageView();
733
		if (null == imageView || null == d) {
734
			return;
735
		}
736
737
		final float viewWidth = imageView.getWidth();
738
		final float viewHeight = imageView.getHeight();
739
		final int drawableWidth = d.getIntrinsicWidth();
740
		final int drawableHeight = d.getIntrinsicHeight();
741
742
		mBaseMatrix.reset();
743
744
		final float widthScale = viewWidth / drawableWidth;
745
		final float heightScale = viewHeight / drawableHeight;
746
747
		if (mScaleType == ScaleType.CENTER) {
748
			mBaseMatrix.postTranslate((viewWidth - drawableWidth) / 2F,
749
					(viewHeight - drawableHeight) / 2F);
750
751
		} else if (mScaleType == ScaleType.CENTER_CROP) {
752
			float scale = Math.max(widthScale, heightScale);
753
			mBaseMatrix.postScale(scale, scale);
754
			mBaseMatrix.postTranslate((viewWidth - drawableWidth * scale) / 2F,
755
					(viewHeight - drawableHeight * scale) / 2F);
756
757
		} else if (mScaleType == ScaleType.CENTER_INSIDE) {
758
			float scale = Math.min(1.0f, Math.min(widthScale, heightScale));
759
			mBaseMatrix.postScale(scale, scale);
760
			mBaseMatrix.postTranslate((viewWidth - drawableWidth * scale) / 2F,
761
					(viewHeight - drawableHeight * scale) / 2F);
762
763
		} else {
764
			RectF mTempSrc = new RectF(0, 0, drawableWidth, drawableHeight);
765
			RectF mTempDst = new RectF(0, 0, viewWidth, viewHeight);
766
767
			switch (mScaleType) {
768
			case FIT_CENTER:
769
				mBaseMatrix
770
						.setRectToRect(mTempSrc, mTempDst, ScaleToFit.CENTER);
771
				break;
772
773
			case FIT_START:
774
				mBaseMatrix.setRectToRect(mTempSrc, mTempDst, ScaleToFit.START);
775
				break;
776
777
			case FIT_END:
778
				mBaseMatrix.setRectToRect(mTempSrc, mTempDst, ScaleToFit.END);
779
				break;
780
781
			case FIT_XY:
782
				mBaseMatrix.setRectToRect(mTempSrc, mTempDst, ScaleToFit.FILL);
783
				break;
784
785
			default:
786
				break;
787
			}
788
		}
789
790
		resetMatrix();
791
	}
792
793
	/**
794
	 * Interface definition for a callback to be invoked when the internal
795
	 * Matrix has changed for this View.
796
	 * 
797
	 * @author Chris Banes
798
	 */
799
	public static interface OnMatrixChangedListener {
800
		/**
801
		 * Callback for when the Matrix displaying the Drawable has changed.
802
		 * This could be because the View's bounds have changed, or the user has
803
		 * zoomed.
804
		 * 
805
		 * @param rect
806
		 *            - Rectangle displaying the Drawable's new bounds.
807
		 */
808
		void onMatrixChanged(RectF rect);
809
	}
810
811
	/**
812
	 * Interface definition for a callback to be invoked when the Photo is
813
	 * tapped with a single tap.
814
	 * 
815
	 * @author Chris Banes
816
	 */
817
	public static interface OnPhotoTapListener {
818
819
		/**
820
		 * A callback to receive where the user taps on a photo. You will only
821
		 * receive a callback if the user taps on the actual photo, tapping on
822
		 * 'whitespace' will be ignored.
823
		 * 
824
		 * @param view
825
		 *            - View the user tapped.
826
		 * @param x
827
		 *            - where the user tapped from the of the Drawable, as
828
		 *            percentage of the Drawable width.
829
		 * @param y
830
		 *            - where the user tapped from the top of the Drawable, as
831
		 *            percentage of the Drawable height.
832
		 */
833
		void onPhotoTap(View view, float x, float y);
834
	}
835
836
	/**
837
	 * Interface definition for a callback to be invoked when the ImageView is
838
	 * tapped with a single tap.
839
	 * 
840
	 * @author Chris Banes
841
	 */
842
	public static interface OnViewTapListener {
843
844
		/**
845
		 * A callback to receive where the user taps on a ImageView. You will
846
		 * receive a callback if the user taps anywhere on the view, tapping on
847
		 * 'whitespace' will not be ignored.
848
		 * 
849
		 * @param view
850
		 *            - View the user tapped.
851
		 * @param x
852
		 *            - where the user tapped from the left of the View.
853
		 * @param y
854
		 *            - where the user tapped from the top of the View.
855
		 */
856
		void onViewTap(View view, float x, float y);
857
	}
858
859
	private class AnimatedZoomRunnable implements Runnable {
860
861
		// These are 'postScale' values, means they're compounded each iteration
862
		static final float ANIMATION_SCALE_PER_ITERATION_IN = 1.07f;
863
		static final float ANIMATION_SCALE_PER_ITERATION_OUT = 0.93f;
864
865
		private final float mFocalX, mFocalY;
866
		private final float mTargetZoom;
867
		private final float mDeltaScale;
868
869
		public AnimatedZoomRunnable(final float currentZoom,
870
				final float targetZoom, final float focalX, final float focalY) {
871
			mTargetZoom = targetZoom;
872
			mFocalX = focalX;
873
			mFocalY = focalY;
874
875
			if (currentZoom < targetZoom) {
876
				mDeltaScale = ANIMATION_SCALE_PER_ITERATION_IN;
877
			} else {
878
				mDeltaScale = ANIMATION_SCALE_PER_ITERATION_OUT;
879
			}
880
		}
881
882
		public void run() {
883
			ImageView imageView = getImageView();
884
885
			if (null != imageView) {
886
				mSuppMatrix.postScale(mDeltaScale, mDeltaScale, mFocalX,
887
						mFocalY);
888
				checkAndDisplayMatrix();
889
890
				final float currentScale = getScale();
891
892
				if ((mDeltaScale > 1f && currentScale < mTargetZoom)
893
						|| (mDeltaScale < 1f && mTargetZoom < currentScale)) {
894
					// We haven't hit our target scale yet, so post ourselves
895
					// again
896
					Compat.postOnAnimation(imageView, this);
897
898
				} else {
899
					// We've scaled past our target zoom, so calculate the
900
					// necessary scale so we're back at target zoom
901
					final float delta = mTargetZoom / currentScale;
902
					mSuppMatrix.postScale(delta, delta, mFocalX, mFocalY);
903
					checkAndDisplayMatrix();
904
				}
905
			}
906
		}
907
	}
908
909
	private class FlingRunnable implements Runnable {
910
911
		private final ScrollerProxy mScroller;
912
		private int mCurrentX, mCurrentY;
913
914
		public FlingRunnable(Context context) {
915
			mScroller = ScrollerProxy.getScroller(context);
916
		}
917
918
		public void cancelFling() {
919
			if (DEBUG) {
920
				Log.d(LOG_TAG, "Cancel Fling");
921
			}
922
			mScroller.forceFinished(true);
923
		}
924
925
		public void fling(int viewWidth, int viewHeight, int velocityX,
926
				int velocityY) {
927
			final RectF rect = getDisplayRect();
928
			if (null == rect) {
929
				return;
930
			}
931
932
			final int startX = Math.round(-rect.left);
933
			final int minX, maxX, minY, maxY;
934
935
			if (viewWidth < rect.width()) {
936
				minX = 0;
937
				maxX = Math.round(rect.width() - viewWidth);
938
			} else {
939
				minX = maxX = startX;
940
			}
941
942
			final int startY = Math.round(-rect.top);
943
			if (viewHeight < rect.height()) {
944
				minY = 0;
945
				maxY = Math.round(rect.height() - viewHeight);
946
			} else {
947
				minY = maxY = startY;
948
			}
949
950
			mCurrentX = startX;
951
			mCurrentY = startY;
952
953
			if (DEBUG) {
954
				Log.d(LOG_TAG, "fling. StartX:" + startX + " StartY:" + startY
955
						+ " MaxX:" + maxX + " MaxY:" + maxY);
956
			}
957
958
			// If we actually can move, fling the scroller
959
			if (startX != maxX || startY != maxY) {
960
				mScroller.fling(startX, startY, velocityX, velocityY, minX,
961
						maxX, minY, maxY, 0, 0);
962
			}
963
		}
964
965
		@Override
966
		public void run() {
967
			ImageView imageView = getImageView();
968
			if (null != imageView && mScroller.computeScrollOffset()) {
969
970
				final int newX = mScroller.getCurrX();
971
				final int newY = mScroller.getCurrY();
972
973
				if (DEBUG) {
974
					Log.d(LOG_TAG, "fling run(). CurrentX:" + mCurrentX
975
							+ " CurrentY:" + mCurrentY + " NewX:" + newX
976
							+ " NewY:" + newY);
977
				}
978
979
				mSuppMatrix.postTranslate(mCurrentX - newX, mCurrentY - newY);
980
				setImageViewMatrix(getDisplayMatrix());
981
982
				mCurrentX = newX;
983
				mCurrentY = newY;
984
985
				// Post On animation
986
				Compat.postOnAnimation(imageView, this);
987
			}
988
		}
989
	}
990
}

+ 0 - 13
app/src/main/java/com/electric/chargingpile/zoom/SDK16.java

@ -1,13 +0,0 @@
1
package com.electric.chargingpile.zoom;
2
3
import android.annotation.TargetApi;
4
import android.view.View;
5
6
@TargetApi(16)
7
public class SDK16 {
8
9
	public static void postOnAnimation(View view, Runnable r) {
10
		view.postOnAnimation(r);
11
	}
12
	
13
}

+ 0 - 101
app/src/main/java/com/electric/chargingpile/zoom/ScrollerProxy.java

@ -1,101 +0,0 @@
1
package com.electric.chargingpile.zoom;
2
3
import android.annotation.TargetApi;
4
import android.content.Context;
5
import android.os.Build.VERSION;
6
import android.os.Build.VERSION_CODES;
7
import android.widget.OverScroller;
8
import android.widget.Scroller;
9
10
public abstract class ScrollerProxy {
11
12
	public static ScrollerProxy getScroller(Context context) {
13
		if (VERSION.SDK_INT < VERSION_CODES.GINGERBREAD) {
14
			return new PreGingerScroller(context);
15
		} else {
16
			return new GingerScroller(context);
17
		}
18
	}
19
20
	public abstract boolean computeScrollOffset();
21
22
	public abstract void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY,
23
			int maxY, int overX, int overY);
24
25
	public abstract void forceFinished(boolean finished);
26
27
	public abstract int getCurrX();
28
29
	public abstract int getCurrY();
30
31
	@TargetApi(9)
32
	private static class GingerScroller extends ScrollerProxy {
33
34
		private OverScroller mScroller;
35
36
		public GingerScroller(Context context) {
37
			mScroller = new OverScroller(context);
38
		}
39
40
		@Override
41
		public boolean computeScrollOffset() {
42
			return mScroller.computeScrollOffset();
43
		}
44
45
		@Override
46
		public void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY,
47
				int overX, int overY) {
48
			mScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY, overX, overY);
49
		}
50
51
		@Override
52
		public void forceFinished(boolean finished) {
53
			mScroller.forceFinished(finished);
54
		}
55
56
		@Override
57
		public int getCurrX() {
58
			return mScroller.getCurrX();
59
		}
60
61
		@Override
62
		public int getCurrY() {
63
			return mScroller.getCurrY();
64
		}
65
	}
66
67
	private static class PreGingerScroller extends ScrollerProxy {
68
69
		private Scroller mScroller;
70
71
		public PreGingerScroller(Context context) {
72
			mScroller = new Scroller(context);
73
		}
74
75
		@Override
76
		public boolean computeScrollOffset() {
77
			return mScroller.computeScrollOffset();
78
		}
79
80
		@Override
81
		public void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY,
82
				int overX, int overY) {
83
			mScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY);
84
		}
85
86
		@Override
87
		public void forceFinished(boolean finished) {
88
			mScroller.forceFinished(finished);
89
		}
90
91
		@Override
92
		public int getCurrX() {
93
			return mScroller.getCurrX();
94
		}
95
96
		@Override
97
		public int getCurrY() {
98
			return mScroller.getCurrY();
99
		}
100
	}
101
}

+ 0 - 253
app/src/main/java/com/electric/chargingpile/zoom/VersionedGestureDetector.java

@ -1,253 +0,0 @@
1
package com.electric.chargingpile.zoom;
2
3
import android.annotation.TargetApi;
4
import android.content.Context;
5
import android.os.Build;
6
import android.util.FloatMath;
7
import android.view.MotionEvent;
8
import android.view.ScaleGestureDetector;
9
import android.view.ScaleGestureDetector.OnScaleGestureListener;
10
import android.view.VelocityTracker;
11
import android.view.ViewConfiguration;
12
13
public abstract class VersionedGestureDetector {
14
	static final String LOG_TAG = "VersionedGestureDetector";
15
	OnGestureListener mListener;
16
17
	public static VersionedGestureDetector newInstance(Context context, OnGestureListener listener) {
18
		final int sdkVersion = Build.VERSION.SDK_INT;
19
		VersionedGestureDetector detector = null;
20
21
		if (sdkVersion < Build.VERSION_CODES.ECLAIR) {
22
			detector = new CupcakeDetector(context);
23
		} else if (sdkVersion < Build.VERSION_CODES.FROYO) {
24
			detector = new EclairDetector(context);
25
		} else {
26
			detector = new FroyoDetector(context);
27
		}
28
29
		detector.mListener = listener;
30
31
		return detector;
32
	}
33
34
	public abstract boolean onTouchEvent(MotionEvent ev);
35
36
	public abstract boolean isScaling();
37
38
	public static interface OnGestureListener {
39
		public void onDrag(float dx, float dy);
40
41
		public void onFling(float startX, float startY, float velocityX, float velocityY);
42
43
		public void onScale(float scaleFactor, float focusX, float focusY);
44
	}
45
46
	private static class CupcakeDetector extends VersionedGestureDetector {
47
48
		float mLastTouchX;
49
		float mLastTouchY;
50
		final float mTouchSlop;
51
		final float mMinimumVelocity;
52
53
		public CupcakeDetector(Context context) {
54
			final ViewConfiguration configuration = ViewConfiguration.get(context);
55
			mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
56
			mTouchSlop = configuration.getScaledTouchSlop();
57
		}
58
59
		private VelocityTracker mVelocityTracker;
60
		private boolean mIsDragging;
61
62
		float getActiveX(MotionEvent ev) {
63
			return ev.getX();
64
		}
65
66
		float getActiveY(MotionEvent ev) {
67
			return ev.getY();
68
		}
69
70
		public boolean isScaling() {
71
			return false;
72
		}
73
74
		@Override
75
		public boolean onTouchEvent(MotionEvent ev) {
76
			switch (ev.getAction()) {
77
				case MotionEvent.ACTION_DOWN: {
78
					mVelocityTracker = VelocityTracker.obtain();
79
					mVelocityTracker.addMovement(ev);
80
81
					mLastTouchX = getActiveX(ev);
82
					mLastTouchY = getActiveY(ev);
83
					mIsDragging = false;
84
					break;
85
				}
86
87
				case MotionEvent.ACTION_MOVE: {
88
					final float x = getActiveX(ev);
89
					final float y = getActiveY(ev);
90
					final float dx = x - mLastTouchX, dy = y - mLastTouchY;
91
92
					if (!mIsDragging) {
93
						// Use Pythagoras to see if drag length is larger than
94
						// touch slop
95
						mIsDragging = Math.sqrt((dx * dx) + (dy * dy)) >= mTouchSlop;
96
					}
97
98
					if (mIsDragging) {
99
						mListener.onDrag(dx, dy);
100
						mLastTouchX = x;
101
						mLastTouchY = y;
102
103
						if (null != mVelocityTracker) {
104
							mVelocityTracker.addMovement(ev);
105
						}
106
					}
107
					break;
108
				}
109
110
				case MotionEvent.ACTION_CANCEL: {
111
					// Recycle Velocity Tracker
112
					if (null != mVelocityTracker) {
113
						mVelocityTracker.recycle();
114
						mVelocityTracker = null;
115
					}
116
					break;
117
				}
118
119
				case MotionEvent.ACTION_UP: {
120
					if (mIsDragging) {
121
						if (null != mVelocityTracker) {
122
							mLastTouchX = getActiveX(ev);
123
							mLastTouchY = getActiveY(ev);
124
125
							// Compute velocity within the last 1000ms
126
							mVelocityTracker.addMovement(ev);
127
							mVelocityTracker.computeCurrentVelocity(1000);
128
129
							final float vX = mVelocityTracker.getXVelocity(), vY = mVelocityTracker.getYVelocity();
130
131
							// If the velocity is greater than minVelocity, call
132
							// listener
133
							if (Math.max(Math.abs(vX), Math.abs(vY)) >= mMinimumVelocity) {
134
								mListener.onFling(mLastTouchX, mLastTouchY, -vX, -vY);
135
							}
136
						}
137
					}
138
139
					// Recycle Velocity Tracker
140
					if (null != mVelocityTracker) {
141
						mVelocityTracker.recycle();
142
						mVelocityTracker = null;
143
					}
144
					break;
145
				}
146
			}
147
148
			return true;
149
		}
150
	}
151
152
	@TargetApi(5)
153
	private static class EclairDetector extends CupcakeDetector {
154
		private static final int INVALID_POINTER_ID = -1;
155
		private int mActivePointerId = INVALID_POINTER_ID;
156
		private int mActivePointerIndex = 0;
157
158
		public EclairDetector(Context context) {
159
			super(context);
160
		}
161
162
		@Override
163
		float getActiveX(MotionEvent ev) {
164
			try {
165
				return ev.getX(mActivePointerIndex);
166
			} catch (Exception e) {
167
				return ev.getX();
168
			}
169
		}
170
171
		@Override
172
		float getActiveY(MotionEvent ev) {
173
			try {
174
				return ev.getY(mActivePointerIndex);
175
			} catch (Exception e) {
176
				return ev.getY();
177
			}
178
		}
179
180
		@Override
181
		public boolean onTouchEvent(MotionEvent ev) {
182
			final int action = ev.getAction();
183
			switch (action & MotionEvent.ACTION_MASK) {
184
				case MotionEvent.ACTION_DOWN:
185
					mActivePointerId = ev.getPointerId(0);
186
					break;
187
				case MotionEvent.ACTION_CANCEL:
188
				case MotionEvent.ACTION_UP:
189
					mActivePointerId = INVALID_POINTER_ID;
190
					break;
191
				case MotionEvent.ACTION_POINTER_UP:
192
					final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
193
					final int pointerId = ev.getPointerId(pointerIndex);
194
					if (pointerId == mActivePointerId) {
195
						// This was our active pointer going up. Choose a new
196
						// active pointer and adjust accordingly.
197
						final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
198
						mActivePointerId = ev.getPointerId(newPointerIndex);
199
						mLastTouchX = ev.getX(newPointerIndex);
200
						mLastTouchY = ev.getY(newPointerIndex);
201
					}
202
					break;
203
			}
204
205
			mActivePointerIndex = ev.findPointerIndex(mActivePointerId != INVALID_POINTER_ID ? mActivePointerId : 0);
206
			return super.onTouchEvent(ev);
207
		}
208
	}
209
210
	@TargetApi(8)
211
	private static class FroyoDetector extends EclairDetector {
212
213
		private final ScaleGestureDetector mDetector;
214
215
		// Needs to be an inner class so that we don't hit
216
		// VerifyError's on API 4.
217
		private final OnScaleGestureListener mScaleListener = new OnScaleGestureListener() {
218
219
			@Override
220
			public boolean onScale(ScaleGestureDetector detector) {
221
				mListener.onScale(detector.getScaleFactor(), detector.getFocusX(), detector.getFocusY());
222
				return true;
223
			}
224
225
			@Override
226
			public boolean onScaleBegin(ScaleGestureDetector detector) {
227
				return true;
228
			}
229
230
			@Override
231
			public void onScaleEnd(ScaleGestureDetector detector) {
232
				// NO-OP
233
			}
234
		};
235
236
		public FroyoDetector(Context context) {
237
			super(context);
238
			mDetector = new ScaleGestureDetector(context, mScaleListener);
239
		}
240
241
		@Override
242
		public boolean isScaling() {
243
			return mDetector.isInProgress();
244
		}
245
246
		@Override
247
		public boolean onTouchEvent(MotionEvent ev) {
248
			mDetector.onTouchEvent(ev);
249
			return super.onTouchEvent(ev);
250
		}
251
252
	}
253
}

+ 0 - 36
app/src/main/java/com/electric/chargingpile/zoom/ViewPagerFixed.java

@ -1,36 +0,0 @@
1
package com.electric.chargingpile.zoom;
2

3
import android.content.Context;
4
import android.util.AttributeSet;
5
import android.view.MotionEvent;
6

7
public class ViewPagerFixed extends android.support.v4.view.ViewPager {
8

9
    public ViewPagerFixed(Context context) {
10
        super(context);
11
    }
12

13
    public ViewPagerFixed(Context context, AttributeSet attrs) {
14
        super(context, attrs);
15
    }
16

17
    @Override
18
    public boolean onTouchEvent(MotionEvent ev) {
19
        try {
20
            return super.onTouchEvent(ev);
21
        } catch (IllegalArgumentException ex) {
22
            ex.printStackTrace();
23
        }
24
        return false;
25
    }
26

27
    @Override
28
    public boolean onInterceptTouchEvent(MotionEvent ev) {
29
        try {
30
            return super.onInterceptTouchEvent(ev);
31
        } catch (IllegalArgumentException ex) {
32
            ex.printStackTrace();
33
        }
34
        return false;
35
    }
36
}