tags =new ArrayList<>();
117 |
118 | for (String tag : tags) {
119 | CheckBox checkBox = (CheckBox) LayoutInflater.from(context).inflate(R.layout.tag_pw_checkbox, null);
120 | checkBox.setOnCheckedChangeListener(this);
121 | checkBox.setText(tag);
122 | checkBox.setTag(tag+1);
123 |
124 | int spec = View.MeasureSpec.makeMeasureSpec(w_screen, View.MeasureSpec.AT_MOST);
125 | checkBox.measure(spec, spec);
126 |
127 | GridLayout.LayoutParams params = new GridLayout.LayoutParams();
128 | params.width = GridLayout.LayoutParams.WRAP_CONTENT;
129 | params.height = GridLayout.LayoutParams.WRAP_CONTENT;
130 | params.setMargins(0, 0, marRight, marBottom);
131 | params.rowSpec = GridLayout.spec(row);
132 | params.columnSpec = GridLayout.spec(col++);
133 | width += checkBox.getMeasuredWidth() + marRight;
134 | DebugLog.e("width: " + width);
135 | if (width >= w_screen) {
136 | width = marRight + checkBox.getMeasuredWidth() + marRight;
137 | row++;
138 | col = 0;
139 | params.rowSpec = GridLayout.spec(row);
140 | params.columnSpec = GridLayout.spec(col++);
141 | }
142 | gridLayout.addView(checkBox, params);
143 |
144 | }
145 | }
146 |
147 | private int calModeIndex(int mode) {
148 | int exp = -1;
149 | while (mode != 0) {
150 | mode >>= 1;
151 | exp++;
152 | }
153 | return exp;
154 | }
155 |
156 |
157 | @Override
158 | public void dismiss() {
159 | if (outCbx != null && outCbx.isChecked()) {
160 | outCbx.setTag(null);
161 | outCbx.setChecked(false);
162 | }
163 | super.dismiss();
164 | }
165 |
166 |
167 |
168 | boolean lockCheck = false;
169 |
170 | @Override
171 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
172 | if (isChecked) {
173 | if (buttonView == no_limit_cbx[0]) {
174 | lockCheck = true;
175 | GridLayout gridLayout = tag_pw_grid[0];
176 | for (int i = 1; i < gridLayout.getChildCount(); i++) {
177 | CheckBox checkBox = (CheckBox) gridLayout.getChildAt(i);
178 | checkBox.setChecked(false);
179 | }
180 | lockCheck = false;
181 | } else if (buttonView == no_limit_cbx[1]) {
182 | lockCheck = true;
183 | GridLayout gridLayout = tag_pw_grid[1];
184 | for (int i = 1; i < gridLayout.getChildCount(); i++) {
185 | CheckBox checkBox = (CheckBox) gridLayout.getChildAt(i);
186 | checkBox.setChecked(false);
187 | }
188 | lockCheck = false;
189 | } else {
190 | GridLayout gridLayout = tag_pw_grid[0];
191 | for (int i = 1; i < gridLayout.getChildCount(); i++) {
192 | CheckBox cbx = (CheckBox) gridLayout.getChildAt(i);
193 | if (buttonView == cbx) {
194 | lockCheck = true;
195 | no_limit_cbx[0].setChecked(false);
196 | lockCheck = false;
197 | break;
198 | }
199 | }
200 |
201 | gridLayout = tag_pw_grid[1];
202 | for (int i = 1; i < gridLayout.getChildCount(); i++) {
203 | CheckBox cbx = (CheckBox) gridLayout.getChildAt(i);
204 | if (buttonView == cbx) {
205 | lockCheck = true;
206 | no_limit_cbx[1].setChecked(false);
207 | lockCheck = false;
208 | break;
209 | }
210 | }
211 | }
212 | }
213 | }
214 | }
215 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oceancx/androidlib/popupwindow/FilterLinePw.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.androidlib.popupwindow;
2 |
3 | import android.content.Context;
4 | import android.view.KeyEvent;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.CheckBox;
9 | import android.widget.PopupWindow;
10 | import android.widget.RadioButton;
11 | import android.widget.RadioGroup;
12 |
13 | import com.oceancx.androidlib.R;
14 |
15 |
16 | /**
17 | * 最简单的PopupWindow
18 | * popupwindow的作用是构造出来s007请求
19 | * 然后通知fg更新列表
20 | * Created by oceancx on 15/12/30.
21 | */
22 | public class FilterLinePw extends PopupWindow {
23 |
24 |
25 | RadioGroup radioGroup;
26 | CheckBox outCbx;
27 |
28 | // could be any number,but cant be the same
29 | int[] rbtIds = {0, 1, 2};
30 |
31 | public FilterLinePw(Context context, CheckBox outCbx, String[] items) {
32 | super(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
33 | View contentview = LayoutInflater.from(context).inflate(R.layout.line_popupwindow, null);
34 | setContentView(contentview);
35 | setFocusable(true);
36 | setOutsideTouchable(true);
37 | this.outCbx = outCbx;
38 | contentview.setOnKeyListener(new View.OnKeyListener() {
39 | @Override
40 | public boolean onKey(View v, int keyCode, KeyEvent event) {
41 | if (keyCode == KeyEvent.KEYCODE_BACK) {
42 | dismiss();
43 | return true;
44 | }
45 | return false;
46 | }
47 | });
48 | contentview.setFocusable(true); // 这个很重要
49 | contentview.setFocusableInTouchMode(true);
50 | contentview.setOnClickListener(new View.OnClickListener() {
51 | @Override
52 | public void onClick(View v) {
53 | dismiss();
54 | }
55 | });
56 |
57 | /**
58 | * 用数据初始化ui
59 | */
60 | radioGroup = (RadioGroup) contentview.findViewById(R.id.filter_layout1);
61 | radioGroup.clearCheck();
62 | if (items == null) return;
63 | for (int i = 0; i < items.length; i++) {
64 |
65 | RadioButton radioButton = (RadioButton) LayoutInflater.from(context).inflate(R.layout.line_popupwindow_rbt, null);
66 | radioButton.setId(rbtIds[i]);
67 | radioButton.setText(items[i]);
68 |
69 | radioGroup.addView(radioButton, -1, radioGroup.getLayoutParams());
70 |
71 | if (items[i].equals(outCbx.getText())) {
72 | outCbx.setTag(i);
73 | radioButton.setChecked(true);
74 | }
75 |
76 | }
77 | radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
78 | @Override
79 | public void onCheckedChanged(RadioGroup group, int checkedId) {
80 | dismiss();
81 | }
82 | });
83 |
84 | }
85 |
86 |
87 | @Override
88 | public void dismiss() {
89 | if (outCbx != null && outCbx.isChecked()) {
90 | int id = radioGroup.getCheckedRadioButtonId();
91 | RadioButton rbt = (RadioButton) radioGroup.findViewById(id);
92 | Integer old_tag = (Integer) outCbx.getTag();
93 | if (old_tag == null) {
94 | super.dismiss();
95 | return;
96 | }
97 | if (old_tag != id) {
98 | outCbx.setTag(id);
99 | outCbx.setText(rbt.getText());
100 | } else {
101 | outCbx.setTag(-1);
102 | }
103 | outCbx.setChecked(false);
104 | }
105 | super.dismiss();
106 | }
107 |
108 | }
109 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oceancx/androidlib/popupwindow/PwTemplate.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.androidlib.popupwindow;
2 |
3 | import android.content.Context;
4 | import android.view.KeyEvent;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.CheckBox;
9 | import android.widget.PopupWindow;
10 |
11 | import com.oceancx.androidlib.R;
12 |
13 |
14 | /**
15 | * Created by oceancx on 16/1/27.
16 | */
17 | public class PwTemplate extends PopupWindow {
18 | CheckBox outCbx;
19 |
20 | public PwTemplate(Context context, CheckBox outCbx) {
21 | super(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
22 | View contentview = LayoutInflater.from(context).inflate(R.layout.line_popupwindow, null);
23 | setContentView(contentview);
24 | setTouchable(true);
25 | setFocusable(true);
26 | setOutsideTouchable(true);
27 | this.outCbx = outCbx;
28 | contentview.setOnKeyListener(new View.OnKeyListener() {
29 | @Override
30 | public boolean onKey(View v, int keyCode, KeyEvent event) {
31 | if (keyCode == KeyEvent.KEYCODE_BACK) {
32 | dismiss();
33 | return true;
34 | }
35 | return false;
36 | }
37 | });
38 | contentview.setFocusable(true); // 这个很重要
39 | contentview.setFocusableInTouchMode(true);
40 | contentview.setOnClickListener(new View.OnClickListener() {
41 | @Override
42 | public void onClick(View v) {
43 | dismiss();
44 | }
45 | });
46 | init(context);
47 | }
48 |
49 | private void init(Context context) {
50 |
51 | }
52 |
53 | public void dismiss() {
54 | if (outCbx != null && outCbx.isChecked()) {
55 | outCbx.setTag(null);
56 | outCbx.setChecked(false);
57 | }
58 | super.dismiss();
59 | }
60 |
61 | public void dismiss(Object tag) {
62 | if (outCbx != null && outCbx.isChecked()) {
63 |
64 | // TODO: 15/12/31 warnning: the two statement's postion really matters
65 | outCbx.setTag(tag);
66 | // TODO: 15/12/31
67 | outCbx.setChecked(false);
68 | }
69 | super.dismiss();
70 | }
71 |
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oceancx/androidlib/simpleclass/DumbViewHolder.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.androidlib.simpleclass;
2 |
3 | import android.support.v7.widget.RecyclerView;
4 | import android.view.View;
5 |
6 | /**
7 | * Created by oceancx on 15/12/16.
8 | */
9 | public class DumbViewHolder extends RecyclerView.ViewHolder {
10 | public DumbViewHolder(View itemView) {
11 | super(itemView);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oceancx/androidlib/simpleclass/TextWatcherAdapter.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.androidlib.simpleclass;
2 |
3 | import android.text.Editable;
4 | import android.text.TextWatcher;
5 |
6 | /**
7 | * Created by oceancx on 15/12/23.
8 | */
9 | public class TextWatcherAdapter implements TextWatcher {
10 | @Override
11 | public void beforeTextChanged(CharSequence s, int start, int count, int after) {
12 |
13 | }
14 |
15 | @Override
16 | public void onTextChanged(CharSequence s, int start, int before, int count) {
17 |
18 | }
19 |
20 | @Override
21 | public void afterTextChanged(Editable s) {
22 |
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oceancx/androidlib/utils/CacheHelper.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.androidlib.utils;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 |
6 | /**
7 | * 缓存帮助类
8 | * 1. 缓存什么要知道
9 | * 2. 读取什么要知道
10 | * Created by oceancx on 15/11/9.
11 | */
12 | public class CacheHelper {
13 | private SharedPreferences preferences;
14 | private static CacheHelper CACHE;
15 | public static final String FIRSTE_RECTVIEW="firstRecView";
16 |
17 |
18 |
19 | public CacheHelper(Context context) {
20 | preferences = context.getSharedPreferences("Cache", Context.MODE_PRIVATE);
21 | }
22 |
23 | public static CacheHelper getInstance(Context context) {
24 | if (CACHE == null)
25 | CACHE = new CacheHelper(context);
26 | return CACHE;
27 | }
28 |
29 | public boolean writeCache(String key, String text) {
30 | return preferences.edit().putString(key, text).commit();
31 |
32 | }
33 |
34 | public String readCache(String key) {
35 |
36 | return preferences.getString(key, null);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oceancx/androidlib/utils/DateUtils.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.androidlib.utils;
2 |
3 | import android.text.TextUtils;
4 |
5 | import java.text.ParseException;
6 | import java.text.SimpleDateFormat;
7 | import java.util.Calendar;
8 | import java.util.Date;
9 | import java.util.Locale;
10 |
11 |
12 | public class DateUtils {
13 | //20151028_18:00
14 | private static SimpleDateFormat formatter_yyyyMMdd_HH_mm = new SimpleDateFormat("yyyyMMdd_HH:mm");
15 | private static final int HOURS_OF_A_DAY = 24;
16 | private static final int MINUTES_OF_AN_HOUR = 60;
17 | private static final int SECONDS_OF_A_MINUTE = 60;
18 | private static final int SECONDS_OF_A_HOUR = 60 * 60;
19 | private static final int SECONDS_OF_A_DAY = HOURS_OF_A_DAY * MINUTES_OF_AN_HOUR * SECONDS_OF_A_MINUTE;
20 | private static final int TROUSAND = 1000;
21 |
22 | public static final int YEAR = 0;
23 | public static final int MOUNTH = 1;
24 | public static final int DAY = 2;
25 | public static final int HOUR = 3;
26 | public static final int MINUTE = 4;
27 | public static final int SECOND = 5;
28 | private static SimpleDateFormat formatter_yyyyMMdd = new SimpleDateFormat("yyyyMMdd");
29 |
30 |
31 |
32 |
33 | public static FormatedTime formatTime(String yyyyMMdd_HH_mm) {
34 | try {
35 | Date d = formatter_yyyyMMdd_HH_mm.parse(yyyyMMdd_HH_mm);
36 | Calendar c = Calendar.getInstance();
37 | c.setTime(d);
38 | FormatedTime t = new FormatedTime();
39 | t.year = c.get(Calendar.YEAR);
40 | t.month = c.get(Calendar.MONTH) + 1;
41 | t.day = c.get(Calendar.DAY_OF_MONTH);
42 | t.hour = c.get(Calendar.HOUR_OF_DAY);
43 | t.minute = c.get(Calendar.MINUTE);
44 | t.second = c.get(Calendar.SECOND);
45 | return t;
46 | } catch (ParseException e) {
47 | e.printStackTrace();
48 | }
49 | return null;
50 | }
51 |
52 |
53 | public static FormatedTime formatTime_yyyyMMdd(String yyyyMMdd) {
54 | try {
55 | Date d = formatter_yyyyMMdd.parse(yyyyMMdd);
56 | Calendar c = Calendar.getInstance();
57 | c.setTime(d);
58 | FormatedTime t = new FormatedTime();
59 | t.year = c.get(Calendar.YEAR);
60 | t.month = c.get(Calendar.MONTH) + 1;
61 | t.day = c.get(Calendar.DAY_OF_MONTH);
62 | return t;
63 | } catch (ParseException e) {
64 | e.printStackTrace();
65 | }
66 | return null;
67 | }
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oceancx/androidlib/utils/FileHelper.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.androidlib.utils;
2 |
3 | import android.os.Environment;
4 |
5 | import com.oceancx.androidlib.DebugLog;
6 |
7 | import java.io.ByteArrayOutputStream;
8 | import java.io.File;
9 | import java.io.FileInputStream;
10 | import java.io.FileNotFoundException;
11 | import java.io.FileWriter;
12 | import java.io.IOException;
13 |
14 | /**
15 | * Created by oceancx on 15/10/26.
16 | */
17 | public class FileHelper {
18 | static String env = Environment.getExternalStorageDirectory().getAbsolutePath() + "/";
19 |
20 | public static String load(String path) {
21 | DebugLog.e("load file:" + path);
22 | try {
23 | FileInputStream fis = new FileInputStream(env + path);
24 | byte[] bytes = new byte[1024];
25 | int len = 0;
26 | ByteArrayOutputStream bos = new ByteArrayOutputStream();
27 | while ((len = fis.read(bytes)) > 0) {
28 | bos.write(bytes, 0, len);
29 | }
30 | fis.close();
31 | String route = bos.toString();
32 | return route;
33 |
34 | } catch (FileNotFoundException e) {
35 | e.printStackTrace();
36 | } catch (IOException e) {
37 | e.printStackTrace();
38 | } catch (NumberFormatException e) {
39 | e.printStackTrace();
40 | }
41 | return null;
42 | }
43 |
44 | public static void delete(String path) {
45 |
46 | if (path == null || path.equals(""))
47 | path = env + "1.txt";
48 | else
49 | path = env + path;
50 |
51 | File f = new File(path);
52 | if (!f.exists()) {
53 | return;
54 | } else {
55 | f.delete();
56 | }
57 | }
58 |
59 | public static void save(String path, String text) {
60 |
61 | if (path == null || path.equals(""))
62 | path = env + "1.txt";
63 | else
64 | path = env + path;
65 |
66 | File f = new File(path);
67 | if (!f.exists()) {
68 | try {
69 | f.createNewFile();
70 | } catch (IOException e) {
71 | e.printStackTrace();
72 | }
73 | } else {
74 | f.delete();
75 | try {
76 | f.createNewFile();
77 | } catch (IOException e) {
78 | e.printStackTrace();
79 | }
80 | }
81 |
82 | FileWriter fw = null;
83 | try {
84 | fw = new FileWriter(f);
85 |
86 | fw.write(text + "");
87 | fw.close();
88 | DebugLog.e("FileSave:" + text);
89 | DebugLog.e(path + "-文件保存成功!");
90 | } catch (IOException e) {
91 | e.printStackTrace();
92 | }
93 | }
94 |
95 | public static String hash(String str) {
96 | int val = 0;
97 | for (int i = 0; i < str.length(); i++) {
98 | char c = str.charAt(i);
99 | val += c;
100 | }
101 | return String.valueOf(val);
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oceancx/androidlib/utils/FormatedTime.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.androidlib.utils;
2 |
3 | /**
4 | * Created by oceancx on 15/10/21.
5 | */
6 | public class FormatedTime {
7 | public int year;
8 | public int month;
9 | public int day;
10 | public int hour;
11 | public int minute;
12 | public int second;
13 |
14 |
15 | private String completeTo2digits(int field) {
16 | if (field > 99 || field < 0) throw new IllegalArgumentException("参数不能超过100");
17 | if (field < 10) {
18 | return "0" + field;
19 | } else
20 | return field + "";
21 | }
22 |
23 | public String getYear() {
24 |
25 | return completeTo2digits(year);
26 | }
27 |
28 | public String getMonth() {
29 | return completeTo2digits(month);
30 | }
31 |
32 | public String getDay() {
33 | return completeTo2digits(day);
34 | }
35 |
36 | public String getHour() {
37 | return completeTo2digits(hour);
38 | }
39 |
40 | public String getMinute() {
41 | return completeTo2digits(minute);
42 | }
43 |
44 | public String getSecond() {
45 | return completeTo2digits(second);
46 | }
47 |
48 | @Override
49 | public String toString() {
50 | return "FormatedTime{" +
51 | "year=" + year +
52 | ", month=" + month +
53 | ", day=" + day +
54 | ", hour=" + hour +
55 | ", minute=" + minute +
56 | ", second=" + second +
57 | '}';
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oceancx/androidlib/utils/MeasureUtils.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2014 Wireless Designs, LLC
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining
5 | * a copy of this software and associated documentation files (the
6 | * "Software"), to deal in the Software without restriction, including
7 | * without limitation the rights to use, copy, modify, merge, publish,
8 | * distribute, sublicense, and/or sell copies of the Software, and to
9 | * permit persons to whom the Software is furnished to do so, subject to
10 | * the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be
13 | * included in all copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 | */
23 | package com.oceancx.androidlib.utils;
24 |
25 | import android.view.View;
26 |
27 | public class MeasureUtils {
28 |
29 | /**
30 | * Utility to return a view's standard measurement. Uses the
31 | * supplied size when constraints are given. Attempts to
32 | * hold to the desired size unless it conflicts with provided
33 | * constraints.
34 | *
35 | * @param measureSpec Constraints imposed by the parent
36 | * @param contentSize Desired size for the view
37 | * @return The size the view should be.
38 | */
39 | public static int getMeasurement(int measureSpec, int contentSize) {
40 | int specMode = View.MeasureSpec.getMode(measureSpec);
41 | int specSize = View.MeasureSpec.getSize(measureSpec);
42 | int resultSize = 0;
43 | switch (specMode) {
44 | case View.MeasureSpec.UNSPECIFIED:
45 | //Big as we want to be
46 | resultSize = contentSize;
47 | break;
48 | case View.MeasureSpec.AT_MOST:
49 | //Big as we want to be, up to the spec
50 | resultSize = Math.min(contentSize, specSize);
51 | break;
52 | case View.MeasureSpec.EXACTLY:
53 | //Must be the spec size
54 | resultSize = specSize;
55 | break;
56 | }
57 |
58 | return resultSize;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oceancx/androidlib/widget/AdvancedRadioGroup.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.androidlib.widget;
2 |
3 | import android.content.Context;
4 | import android.os.Build;
5 | import android.support.annotation.IdRes;
6 | import android.util.AttributeSet;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.CompoundButton;
10 | import android.widget.FrameLayout;
11 | import android.widget.RadioButton;
12 |
13 | /**
14 | * 大部分代码是从RadioGroup中复制过来的,可以把这个自定义控件当做一个RadioGroup来使用,
15 | * 只不过它支持孩子节点为ViewGroup,只要孩子里面有RadioButton就可以
16 | * 注意:在RadioGroup中的孩子RadioButton不能设置onCheckedChangeListener
17 | * 只能对RadioGroup设置AdvancedRadioGroupCheckChangedListener
18 | * Created by oceancx on 16/1/7.
19 | */
20 | public class AdvancedRadioGroup extends FrameLayout {
21 |
22 | public AdvancedRadioGroup(Context context) {
23 | super(context);
24 | init();
25 | }
26 |
27 | public AdvancedRadioGroup(Context context, AttributeSet attrs) {
28 | super(context, attrs);
29 |
30 | init();
31 | }
32 |
33 | public interface AdvancedRadioGroupCheckChangedListener {
34 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked);
35 | }
36 |
37 |
38 | // holds the checked id; the selection is empty by default
39 | private int mCheckedId = -1;
40 | // tracks children radio buttons checked state
41 | private CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener;
42 | // when true, mOnCheckedChangeListener discards events
43 | private boolean mProtectFromCheckedChange = false;
44 | private OnCheckedChangeListener mOnCheckedChangeListener;
45 | private PassThroughHierarchyChangeListener mPassThroughListener;
46 |
47 |
48 | private void init() {
49 | mChildOnCheckedChangeListener = new CheckedStateTracker();
50 | mPassThroughListener = new PassThroughHierarchyChangeListener();
51 | super.setOnHierarchyChangeListener(mPassThroughListener);
52 | }
53 |
54 | /**
55 | * {@inheritDoc}
56 | */
57 | @Override
58 | public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {
59 | // the user listener is delegated to our pass-through listener
60 | mPassThroughListener.mOnHierarchyChangeListener = listener;
61 | }
62 |
63 | /**
64 | * {@inheritDoc}
65 | */
66 | @Override
67 | protected void onFinishInflate() {
68 | super.onFinishInflate();
69 |
70 | // checks the appropriate radio button as requested in the XML file
71 | if (mCheckedId != -1) {
72 | mProtectFromCheckedChange = true;
73 | setCheckedStateForView(mCheckedId, true);
74 | mProtectFromCheckedChange = false;
75 | setCheckedId(mCheckedId);
76 | }
77 | }
78 |
79 | @Override
80 | public void addView(View child, int index, ViewGroup.LayoutParams params) {
81 |
82 | if (child instanceof RadioButton) {
83 | final RadioButton button = (RadioButton) child;
84 | if (button.isChecked()) {
85 | mProtectFromCheckedChange = true;
86 | if (mCheckedId != -1) {
87 | setCheckedStateForView(mCheckedId, false);
88 | }
89 | mProtectFromCheckedChange = false;
90 | setCheckedId(button.getId());
91 | }
92 | } else if (child instanceof ViewGroup) {
93 | addViewGroup((ViewGroup) child, index, params);
94 | return;
95 | }
96 | super.addView(child, index, params);
97 | }
98 |
99 |
100 | public void addViewGroup(ViewGroup parent, int index, ViewGroup.LayoutParams params) {
101 |
102 | RadioButton child = lookforRadioButton(parent);
103 |
104 | if (child instanceof RadioButton) {
105 | final RadioButton button = (RadioButton) child;
106 | if (button.isChecked()) {
107 | mProtectFromCheckedChange = true;
108 | if (mCheckedId != -1) {
109 | setCheckedStateForView(mCheckedId, false);
110 | }
111 | mProtectFromCheckedChange = false;
112 | setCheckedId(button.getId());
113 | }
114 | }
115 | super.addView(parent, index, params);
116 | }
117 |
118 |
119 | private RadioButton lookforRadioButton(ViewGroup child) {
120 | if (child instanceof ViewGroup) {
121 | ViewGroup viewGroup = (ViewGroup) child;
122 | for (int i = 0; i < viewGroup.getChildCount(); i++) {
123 | if (viewGroup.getChildAt(i) instanceof RadioButton) {
124 | return (RadioButton) viewGroup.getChildAt(i);
125 | } else {
126 | return lookforRadioButton((ViewGroup) viewGroup.getChildAt(i));
127 | }
128 | }
129 | }
130 | return null;
131 | }
132 |
133 |
134 | /**
135 | * Sets the selection to the radio button whose identifier is passed in
136 | * parameter. Using -1 as the selection identifier clears the selection;
137 | * such an operation is equivalent to invoking {@link #clearCheck()}.
138 | *
139 | * @param id the unique id of the radio button to select in this group
140 | * @see #getCheckedRadioButtonId()
141 | * @see #clearCheck()
142 | */
143 | public void check(@IdRes int id) {
144 | // don't even bother
145 | if (id != -1 && (id == mCheckedId)) {
146 | return;
147 | }
148 |
149 | if (mCheckedId != -1) {
150 | setCheckedStateForView(mCheckedId, false);
151 | }
152 |
153 | if (id != -1) {
154 | setCheckedStateForView(id, true);
155 | }
156 |
157 | setCheckedId(id);
158 | }
159 |
160 | private void setCheckedId(@IdRes int id) {
161 | mCheckedId = id;
162 | if (mOnCheckedChangeListener != null) {
163 | mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
164 | }
165 | }
166 |
167 | private void setCheckedStateForView(int viewId, boolean checked) {
168 | View checkedView = findViewById(viewId);
169 | if (checkedView != null && checkedView instanceof RadioButton) {
170 | ((RadioButton) checkedView).setChecked(checked);
171 | }
172 | }
173 |
174 | /**
175 | * Returns the identifier of the selected radio button in this group.
176 | * Upon empty selection, the returned value is -1.
177 | *
178 | * @return the unique id of the selected radio button in this group
179 | * @attr ref android.R.styleable#RadioGroup_checkedButton
180 | * @see #check(int)
181 | * @see #clearCheck()
182 | */
183 | @IdRes
184 | public int getCheckedRadioButtonId() {
185 | return mCheckedId;
186 | }
187 |
188 | /**
189 | * Clears the selection. When the selection is cleared, no radio button
190 | * in this group is selected and {@link #getCheckedRadioButtonId()} returns
191 | * null.
192 | *
193 | * @see #check(int)
194 | * @see #getCheckedRadioButtonId()
195 | */
196 | public void clearCheck() {
197 | check(-1);
198 | }
199 |
200 | /**
201 | * Register a callback to be invoked when the checked radio button
202 | * changes in this group.
203 | *
204 | * @param listener the callback to call on checked state change
205 | */
206 | public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
207 | mOnCheckedChangeListener = listener;
208 | }
209 |
210 | /**
211 | * {@inheritDoc}
212 | */
213 | @Override
214 | public LayoutParams generateLayoutParams(AttributeSet attrs) {
215 | return new LayoutParams(getContext(), attrs);
216 | }
217 |
218 | /**
219 | * {@inheritDoc}
220 | */
221 | @Override
222 | protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
223 | return p instanceof LayoutParams;
224 | }
225 |
226 | @Override
227 | protected LayoutParams generateDefaultLayoutParams() {
228 | return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
229 | }
230 |
231 | @Override
232 | public CharSequence getAccessibilityClassName() {
233 | return AdvancedRadioGroup.class.getName();
234 | }
235 |
236 |
237 | /**
238 | * Interface definition for a callback to be invoked when the checked
239 | * radio button changed in this group.
240 | */
241 | public interface OnCheckedChangeListener {
242 | /**
243 | * Called when the checked radio button has changed. When the
244 | * selection is cleared, checkedId is -1.
245 | *
246 | * @param group the group in which the checked radio button has changed
247 | * @param checkedId the unique identifier of the newly checked radio button
248 | */
249 | public void onCheckedChanged(AdvancedRadioGroup group, @IdRes int checkedId);
250 | }
251 |
252 | private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener {
253 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
254 | // prevents from infinite recursion
255 | if (mProtectFromCheckedChange) {
256 | return;
257 | }
258 |
259 | mProtectFromCheckedChange = true;
260 | if (mCheckedId != -1) {
261 | setCheckedStateForView(mCheckedId, false);
262 | }
263 |
264 | mProtectFromCheckedChange = false;
265 |
266 | int id = buttonView.getId();
267 | setCheckedId(id);
268 | }
269 | }
270 |
271 | /**
272 | * A pass-through listener acts upon the events and dispatches them
273 | * to another listener. This allows the table layout to set its own internal
274 | * hierarchy change listener without preventing the user to setup his.
275 | */
276 | public static int id_sand = 12345;
277 |
278 | private class PassThroughHierarchyChangeListener implements
279 | OnHierarchyChangeListener {
280 | private OnHierarchyChangeListener mOnHierarchyChangeListener;
281 |
282 | /**
283 | * {@inheritDoc}
284 | */
285 | public void onChildViewAdded(View parent, View child) {
286 | if (parent == AdvancedRadioGroup.this && child instanceof RadioButton) {
287 | int id = child.getId();
288 | // generates an id if it's missing
289 | if (id == View.NO_ID) {
290 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
291 | id = View.generateViewId();
292 | }
293 | child.setId(id);
294 | }
295 | ((RadioButton) child).setOnCheckedChangeListener(
296 | mChildOnCheckedChangeListener);
297 | } else if (parent == AdvancedRadioGroup.this && child instanceof ViewGroup) {
298 | ViewGroup p = (ViewGroup) child;
299 | RadioButton radioButton = lookforRadioButton(p);
300 | if (radioButton != null) {
301 | int id = radioButton.getId();
302 | if (id == View.NO_ID) {
303 | id = id_sand++;
304 | }
305 | radioButton.setId(id);
306 | radioButton.setOnCheckedChangeListener(mChildOnCheckedChangeListener);
307 | }
308 | }
309 |
310 | if (mOnHierarchyChangeListener != null) {
311 | mOnHierarchyChangeListener.onChildViewAdded(parent, child);
312 | }
313 | }
314 |
315 | /**
316 | * {@inheritDoc}
317 | */
318 | public void onChildViewRemoved(View parent, View child) {
319 | if (parent == AdvancedRadioGroup.this && child instanceof RadioButton) {
320 | ((RadioButton) child).setOnCheckedChangeListener(null);
321 | } else if (parent == AdvancedRadioGroup.this && child instanceof ViewGroup) {
322 | RadioButton radioButton = lookforRadioButton((ViewGroup) child);
323 | if (radioButton != null) radioButton.setOnCheckedChangeListener(null);
324 | }
325 |
326 | if (mOnHierarchyChangeListener != null) {
327 | mOnHierarchyChangeListener.onChildViewRemoved(parent, child);
328 | }
329 | }
330 | }
331 | }
332 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oceancx/androidlib/widget/DashedLine.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.androidlib.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.DashPathEffect;
7 | import android.graphics.Paint;
8 | import android.graphics.Path;
9 | import android.util.AttributeSet;
10 | import android.view.View;
11 |
12 | import com.oceancx.androidlib.R;
13 |
14 |
15 | /**
16 | * 虚线自定义视图
17 | * Created by oceancx on 15/12/25.
18 | */
19 | public class DashedLine extends View {
20 | Paint paint;
21 | Path path;
22 | DashPathEffect pathEffect;
23 |
24 | public DashedLine(Context context) {
25 | this(context, null);
26 | }
27 |
28 | public DashedLine(Context context, AttributeSet attrs) {
29 | this(context, attrs, 0);
30 |
31 |
32 | }
33 |
34 | public DashedLine(Context context, AttributeSet attrs, int defStyleAttr) {
35 | super(context, attrs, defStyleAttr);
36 | pathEffect = new DashPathEffect(new float[]{context.getResources().getDimensionPixelSize(R.dimen._2dp),
37 | context.getResources().getDimensionPixelSize(R.dimen._5dp)}, 0);
38 | paint = new Paint();
39 | path = new Path();
40 | }
41 |
42 |
43 | @Override
44 | protected void onDraw(Canvas canvas) {
45 |
46 | paint.reset();
47 | paint.setStyle(Paint.Style.STROKE);
48 | paint.setStrokeWidth(getMeasuredHeight());
49 | paint.setColor(Color.rgb(0xbf, 0xc4, 0xd3));
50 | paint.setAntiAlias(true);
51 | paint.setPathEffect(pathEffect);
52 | path.moveTo(0, 0);
53 | path.lineTo(getMeasuredWidth(), 0);
54 | canvas.drawPath(path, paint);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oceancx/androidlib/widget/DashedOval.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.androidlib.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.DashPathEffect;
7 | import android.graphics.Paint;
8 | import android.graphics.Path;
9 | import android.util.AttributeSet;
10 | import android.view.View;
11 |
12 | import com.oceancx.androidlib.R;
13 |
14 |
15 | /**
16 | * Created by oceancx on 15/12/25.
17 | */
18 | public class DashedOval extends View {
19 | Paint paint;
20 | Path path;
21 | DashPathEffect pathEffect;
22 |
23 | public DashedOval(Context context) {
24 | super(context);
25 | }
26 |
27 | public DashedOval(Context context, AttributeSet attrs) {
28 | super(context, attrs);
29 |
30 | pathEffect = new DashPathEffect(new float[]{context.getResources().getDimensionPixelSize(R.dimen._2dp),
31 | context.getResources().getDimensionPixelSize(R.dimen._5dp)}, 0);
32 | paint = new Paint();
33 | path = new Path();
34 |
35 | }
36 |
37 | public DashedOval(Context context, AttributeSet attrs, int defStyleAttr) {
38 | super(context, attrs, defStyleAttr);
39 | }
40 |
41 |
42 | @Override
43 | protected void onDraw(Canvas canvas) {
44 |
45 | paint.reset();
46 | paint.setStyle(Paint.Style.STROKE);
47 | paint.setStrokeWidth(getMeasuredHeight());
48 | paint.setColor(Color.rgb(0xbf, 0xc4, 0xd3));
49 | paint.setAntiAlias(true);
50 | paint.setPathEffect(pathEffect);
51 | path.moveTo(0, 0);
52 | canvas.drawPath(path, paint);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oceancx/androidlib/widget/ExpandableListViewForScrollView.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.androidlib.widget;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.widget.ExpandableListView;
6 |
7 | /**
8 | * 可以放在NestedScrollView中,这样就可以在CoordinatorLayout中联动了
9 | * Created by oceancx on 15/12/26.
10 | */
11 | public class ExpandableListViewForScrollView extends ExpandableListView {
12 |
13 |
14 | public ExpandableListViewForScrollView(Context context) {
15 | super(context);
16 | }
17 |
18 | public ExpandableListViewForScrollView(Context context, AttributeSet attrs) {
19 | super(context, attrs);
20 | }
21 |
22 | public ExpandableListViewForScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
23 | super(context, attrs, defStyleAttr);
24 | }
25 |
26 | @Override
27 | /**
28 | * 重写该方法,达到使ListView适应ScrollView的效果
29 | */
30 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
31 | int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
32 | MeasureSpec.AT_MOST);
33 | super.onMeasure(widthMeasureSpec, expandSpec);
34 | }
35 |
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oceancx/androidlib/widget/FrameLayoutCheckBox.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.androidlib.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.Rect;
5 | import android.util.AttributeSet;
6 | import android.view.TouchDelegate;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.CheckBox;
10 | import android.widget.CompoundButton;
11 | import android.widget.FrameLayout;
12 |
13 | import java.util.ArrayList;
14 |
15 | /**
16 | * 对里面的CompoundButton(RadioButton/CheckBox)设置了TouchDelegate,用来扩大(RadioButton/CheckBox)的点击区域
17 | * Created by oceancx on 15/12/26.
18 | */
19 | public class FrameLayoutCheckBox extends FrameLayout {
20 | CompoundButton cbx;
21 |
22 | public FrameLayoutCheckBox(Context context) {
23 | super(context);
24 | }
25 |
26 | public FrameLayoutCheckBox(Context context, AttributeSet attrs) {
27 | super(context, attrs);
28 | }
29 |
30 | public FrameLayoutCheckBox(Context context, AttributeSet attrs, int defStyleAttr) {
31 | super(context, attrs, defStyleAttr);
32 | }
33 |
34 | private CheckBox findCheckBox(View view) {
35 | //无递归广度优先遍历寻找CheckBox - -!我只是想重温一下C
36 | ArrayList views = new ArrayList<>();
37 | views.add(view);
38 | while (!views.isEmpty()) {
39 | View c = views.remove(0);
40 | if (c instanceof CheckBox) {
41 | return (CheckBox) c;
42 | } else if (c instanceof ViewGroup) {
43 | ViewGroup fa = (ViewGroup) c;
44 | for (int i = 0; i < fa.getChildCount(); i++) {
45 | views.add(fa.getChildAt(i));
46 | }
47 | }
48 | }
49 | return null;
50 | }
51 |
52 | @Override
53 | protected void onFinishInflate() {
54 | super.onFinishInflate();
55 | if (getChildCount() > 0) {
56 | View child = findCheckBox(this);
57 | if (child instanceof CompoundButton) cbx = (CompoundButton) child;
58 | }
59 | }
60 |
61 | @Override
62 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
63 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
64 | if (cbx != null) {
65 | Rect bounds = new Rect(getPaddingLeft(), getPaddingTop(), getPaddingLeft() + getMeasuredWidth() + getPaddingRight(), getPaddingTop() + getMeasuredHeight() + getPaddingBottom());
66 | TouchDelegate delegate = new TouchDelegate(bounds, cbx);
67 | setTouchDelegate(delegate);
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oceancx/androidlib/widget/PullToRefreshRecyclerView.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.androidlib.widget;
2 |
3 | /**
4 | * 依赖于PullToRefreshLibrary
5 | * 让RecyclerView支持下拉刷新和上拉加载更多
6 | * Created by oceancx on 16/1/21.
7 | */
8 | public class PullToRefreshRecyclerView{
9 | //extends PullToRefreshBase {
10 | //
11 | // @Override
12 | // public Orientation getPullToRefreshScrollDirection() {
13 | // return Orientation.VERTICAL;
14 | // }
15 |
16 | // @Override
17 | // protected RecyclerView createRefreshableView(Context context, AttributeSet attrs) {
18 | //
19 | // RecyclerView recyclerView = new RecyclerView(context, attrs);
20 | // recyclerView.setId(R.id.ryc_views);
21 | // return recyclerView;
22 | // }
23 |
24 | // protected boolean isReadyForPullEnd() {
25 | // try {
26 | // RecyclerView mRefreshableView = getRefreshableView();
27 | // int checkPos = mRefreshableView.getAdapter().getItemCount() - 1;
28 | //
29 | // View mLastChild = mRefreshableView.getChildAt(mRefreshableView.getChildCount() - 1);
30 | // int rvPos = mRefreshableView.getChildAdapterPosition(mLastChild);
31 | // // 当且仅当第一个可视节点==0 切其top==0的时候 此时rv到达顶部
32 | // if (rvPos == checkPos && mLastChild.getBottom() - mLastChild.getTop() == mLastChild.getMeasuredHeight() && mLastChild.getBottom() == mRefreshableView.getBottom()) {
33 | // return true;
34 | // }
35 | // } catch (NullPointerException e) {
36 | // e.printStackTrace();
37 | // }
38 | // return false;
39 | // }
40 | //
41 | // protected boolean isReadyForPullStart() {
42 | // try {
43 | // int checkPos = 0;
44 | // RecyclerView mRefreshableView = getRefreshableView();
45 | // View mFirstChild = mRefreshableView.getChildAt(0);
46 | // int rvPos = mRefreshableView.getChildLayoutPosition(mFirstChild);
47 | // // 当且仅当第一个可视节点==0 切其top==0的时候 此时rv到达顶部
48 | // if (rvPos == checkPos && mFirstChild.getTop() == mRefreshableView.getPaddingTop()) {
49 | // return true;
50 | // }
51 | // } catch (NullPointerException e) {
52 | // e.printStackTrace();
53 | // }
54 | // return false;
55 | // }
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oceancx/androidlib/widget/TranslusantView.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.androidlib.widget;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.MotionEvent;
6 | import android.widget.FrameLayout;
7 |
8 | /**
9 | * 用来做遮罩,看似简单,却很实用
10 | * Created by oceancx on 15/12/11.
11 | */
12 | public class TranslusantView extends FrameLayout {
13 |
14 | public TranslusantView(Context context) {
15 | super(context);
16 | }
17 |
18 | public TranslusantView(Context context, AttributeSet attrs) {
19 | super(context, attrs);
20 | }
21 |
22 | public TranslusantView(Context context, AttributeSet attrs, int defStyleAttr) {
23 | super(context, attrs, defStyleAttr);
24 | }
25 |
26 | @Override
27 | public boolean onTouchEvent(MotionEvent event) {
28 |
29 | return super.onTouchEvent(event);
30 | }
31 |
32 |
33 | @Override
34 | public boolean onInterceptTouchEvent(MotionEvent ev) {
35 | return true;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/loading_50x50_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/app/src/main/res/drawable-mdpi/loading_50x50_1.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/loading_50x50_10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/app/src/main/res/drawable-mdpi/loading_50x50_10.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/loading_50x50_11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/app/src/main/res/drawable-mdpi/loading_50x50_11.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/loading_50x50_12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/app/src/main/res/drawable-mdpi/loading_50x50_12.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/loading_50x50_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/app/src/main/res/drawable-mdpi/loading_50x50_2.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/loading_50x50_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/app/src/main/res/drawable-mdpi/loading_50x50_3.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/loading_50x50_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/app/src/main/res/drawable-mdpi/loading_50x50_4.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/loading_50x50_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/app/src/main/res/drawable-mdpi/loading_50x50_5.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/loading_50x50_6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/app/src/main/res/drawable-mdpi/loading_50x50_6.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/loading_50x50_7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/app/src/main/res/drawable-mdpi/loading_50x50_7.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/loading_50x50_8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/app/src/main/res/drawable-mdpi/loading_50x50_8.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/loading_50x50_9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/app/src/main/res/drawable-mdpi/loading_50x50_9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/cbx_filter_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/cbx_tag_text_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/dis_ripple.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/filter_txt_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/music_pgb_drawable.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 | -
9 |
10 |
11 |
12 |
13 |
14 |
15 | -
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/pgb_circle.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
10 |
11 |
14 |
15 |
18 |
19 |
22 |
23 |
26 |
27 |
30 |
31 |
34 |
35 |
38 |
39 |
42 |
43 |
46 |
47 |
50 |
51 |
54 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_rect_2dp_grey_border.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_rect_2dp_main_blue.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_white_rect.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/shape_circle_white.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tag_tv_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/checkbox_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
22 |
23 |
32 |
33 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_template.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/divider_grey_e6e7ea.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/line_popupwindow.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
16 |
17 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/line_popupwindow_cbx.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/line_popupwindow_rbt.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/media_player_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
17 |
18 |
22 |
23 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/pull_to_fresh_and_loadmore_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
21 |
22 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/pull_to_refresh_body.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/range_seekbar_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
17 |
18 |
29 |
30 |
35 |
36 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/tag_popupwindow.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
11 |
12 |
17 |
18 |
21 |
22 |
28 |
29 |
39 |
40 |
53 |
54 |
55 |
65 |
66 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
96 |
97 |
98 |
99 |
100 |
105 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/tag_pw_checkbox.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_open_time_pw.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
16 |
17 |
27 |
28 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_open_time_pw_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
13 |
22 |
23 |
30 |
31 |
35 |
36 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 | #486cdc
7 | #ffffff
8 | #41444E
9 | #8d919c
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 2dp
6 | 5dp
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | AndroidLib
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/test/java/com/oceancx/androidlib/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.androidlib;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 |
9 | classpath 'com.android.tools.build:gradle:2.1.0-alpha3'
10 |
11 |
12 | // NOTE: Do not place your application dependencies here; they belong
13 | // in the individual module build.gradle files
14 | }
15 | }
16 |
17 | allprojects {
18 | repositories {
19 | jcenter()
20 | }
21 | }
22 |
23 | task clean(type: Delete) {
24 | delete rootProject.buildDir
25 | }
26 |
--------------------------------------------------------------------------------
/gif/range_seekbar.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/gif/range_seekbar.gif
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 28 10:00:20 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | minSdkVersion 14
9 | targetSdkVersion 23
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | compile 'com.android.support:appcompat-v7:23.1.1'
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | testCompile 'junit:junit:4.12'
25 | compile 'com.android.support:recyclerview-v7:23.1.1'
26 | }
27 |
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/oceancx/Development/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/androidTest/java/com/oceancx/pulltorefreshandloadmore/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.pulltorefreshandloadmore;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/java/com/oceancx/pulltorefreshandloadmore/DebugLog.java:
--------------------------------------------------------------------------------
1 | /***
2 | This is free and unencumbered software released into the public domain.
3 |
4 | Anyone is free to copy, modify, publish, use, compile, sell, or
5 | distribute this software, either in source code form or as a compiled
6 | binary, for any purpose, commercial or non-commercial, and by any
7 | means.
8 |
9 | For more information, please refer to
10 | */
11 |
12 | package com.oceancx.pulltorefreshandloadmore;
13 |
14 | import android.util.Log;
15 |
16 |
17 | /**
18 | * @date 21.06.2012
19 | * @author Mustafa Ferhan Akman
20 | *
21 | * Create a simple and more understandable Android logs.
22 | * */
23 |
24 | public class DebugLog {
25 |
26 | static String className;
27 | static String methodName;
28 | static int lineNumber;
29 |
30 | private DebugLog(){
31 | /* Protect from instantiations */
32 | }
33 |
34 | public static boolean isDebuggable() {
35 | return true;
36 | }
37 |
38 | private static String createLog( String log ) {
39 |
40 | StringBuffer buffer = new StringBuffer();
41 | buffer.append("[");
42 | buffer.append(methodName);
43 | buffer.append(":");
44 | buffer.append(lineNumber);
45 | buffer.append("]");
46 | buffer.append(log);
47 |
48 | return buffer.toString();
49 | }
50 |
51 | private static void getMethodNames(StackTraceElement[] sElements){
52 | className = sElements[1].getFileName();
53 | methodName = sElements[1].getMethodName();
54 | lineNumber = sElements[1].getLineNumber();
55 | }
56 |
57 | public static void e(String message){
58 | if (!isDebuggable())
59 | return;
60 |
61 | // Throwable instance must be created before any methods
62 | getMethodNames(new Throwable().getStackTrace());
63 | Log.e(className, createLog(message));
64 | }
65 |
66 | public static void i(String message){
67 | if (!isDebuggable())
68 | return;
69 |
70 | getMethodNames(new Throwable().getStackTrace());
71 | Log.i(className, createLog(message));
72 | }
73 |
74 | public static void d(String message){
75 | if (!isDebuggable())
76 | return;
77 |
78 | getMethodNames(new Throwable().getStackTrace());
79 | Log.d(className, createLog(message));
80 | }
81 |
82 | public static void v(String message){
83 | if (!isDebuggable())
84 | return;
85 |
86 | getMethodNames(new Throwable().getStackTrace());
87 | Log.v(className, createLog(message));
88 | }
89 |
90 | public static void w(String message){
91 | if (!isDebuggable())
92 | return;
93 |
94 | getMethodNames(new Throwable().getStackTrace());
95 | Log.w(className, createLog(message));
96 | }
97 |
98 | public static void wtf(String message){
99 | if (!isDebuggable())
100 | return;
101 |
102 | getMethodNames(new Throwable().getStackTrace());
103 | Log.wtf(className, createLog(message));
104 | }
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/java/com/oceancx/pulltorefreshandloadmore/PullToFreshAndLordMoreLayout.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.pulltorefreshandloadmore;
2 |
3 | import android.content.Context;
4 | import android.support.v4.view.ViewCompat;
5 | import android.support.v4.widget.ViewDragHelper;
6 | import android.support.v7.widget.RecyclerView;
7 | import android.util.AttributeSet;
8 | import android.view.LayoutInflater;
9 | import android.view.MotionEvent;
10 | import android.view.View;
11 | import android.view.ViewConfiguration;
12 | import android.view.ViewGroup;
13 | import android.widget.FrameLayout;
14 | import android.widget.ImageView;
15 | import android.widget.ProgressBar;
16 | import android.widget.TextView;
17 |
18 |
19 | /**
20 | * 实现RecyclerView的下拉刷新上拉加载更多
21 | * 今天最低目标:
22 | * 实现下拉悬停
23 | * Created by oceancx on 15/11/12.
24 | */
25 | public class PullToFreshAndLordMoreLayout extends FrameLayout {
26 |
27 | float initDownY, initDownX, lastDownX, lastDownY;
28 | boolean shouldIntercept = false;
29 | boolean mRvReachTopWhenDown = false;
30 | boolean mRvReachBottomWhenDown = false;
31 | /**
32 | * child == 0 , 代表的是linearlayout
33 | */
34 | boolean setOnce = false;
35 | boolean setOnce1 = false;
36 | private int mTouchSlop;
37 | private ViewDragHelper mViewDragHelper;
38 | private RecyclerView mRecyclerView;
39 | private View header;
40 | private View footer;
41 | private View body;
42 | private RefreshAndLoadMoreListener mRLListener;
43 | private ProgressBar header_pgb;
44 | private TextView header_tv;
45 | private View header_hanging_layout;
46 | private ImageView header_down_arrow;
47 | private int offset_top = 0;
48 |
49 | public PullToFreshAndLordMoreLayout(Context context) {
50 | this(context, null);
51 | }
52 |
53 |
54 | public PullToFreshAndLordMoreLayout(Context context, AttributeSet attrs) {
55 | this(context, attrs, 0);
56 | }
57 |
58 | public PullToFreshAndLordMoreLayout(Context context, AttributeSet attrs, int defStyleAttr) {
59 | super(context, attrs, defStyleAttr);
60 | mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
61 | mViewDragHelper = ViewDragHelper.create(this, new DragHelperCallback());
62 | /**
63 | * 这里的话 要自己对孩子进行添加Header 和 footer
64 | */
65 |
66 | }
67 |
68 | public void setRefreshAndLoadMoreListener(RefreshAndLoadMoreListener mRLListener) {
69 | this.mRLListener = mRLListener;
70 | }
71 |
72 | @Override
73 | protected void onFinishInflate() {
74 | super.onFinishInflate();
75 | // initData();
76 |
77 | ViewGroup ll_parent = (ViewGroup) getChildAt(0);
78 | body = ll_parent.getChildAt(0);
79 | mRecyclerView = (RecyclerView) ((ViewGroup) body).getChildAt(0);
80 | header = LayoutInflater.from(getContext()).inflate(R.layout.pull_to_refresh_header, ll_parent, false);
81 | footer = LayoutInflater.from(getContext()).inflate(R.layout.pull_to_refresh_footer, ll_parent, false);
82 | ll_parent.addView(header, 0);
83 | ll_parent.addView(footer);
84 |
85 | header_hanging_layout = header.findViewById(R.id.header_hanging_layout);
86 | header_pgb = (ProgressBar) header.findViewById(R.id.header_pgb);
87 | header_down_arrow = (ImageView) header.findViewById(R.id.header_down_arrow_img);
88 | header_tv = (TextView) header.findViewById(R.id.pull_to_refresh_tv);
89 | DebugLog.e("header:" + header + " body:" + body + " footer:" + footer);
90 |
91 |
92 | }
93 |
94 | /**
95 | * 测量两次 确定最终长度
96 | *
97 | * @param widthMeasureSpec
98 | * @param heightMeasureSpec
99 | */
100 | @Override
101 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
102 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
103 | int heightSize = header.getMeasuredHeight() + footer.getMeasuredHeight() + getMeasuredHeight();
104 | int heightMode = MeasureSpec.EXACTLY;
105 | super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(heightSize, heightMode));
106 | }
107 |
108 | @Override
109 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
110 | //onlyChild.layout(left, top, right, bottom);
111 | super.onLayout(changed, left, top, right, bottom);
112 | DebugLog.e("header height: " + header.getMeasuredHeight() + " scale:" + getResources().getDisplayMetrics().scaledDensity);
113 | offsetTopAndBottom(-header.getMeasuredHeight());
114 | }
115 |
116 | /**
117 | * 判断RcyclerView是否在顶点
118 | *
119 | * @return
120 | */
121 | private boolean isRvReachTop() {
122 | int checkPos = 0;
123 |
124 | View mFirstChild = mRecyclerView.getChildAt(0);
125 | int rvPos = mRecyclerView.getChildLayoutPosition(mFirstChild);
126 | // 当且仅当第一个可视节点==0 切其top==0的时候 此时rv到达顶部
127 | DebugLog.e("child top : " + mFirstChild.getTop());
128 | if (rvPos == checkPos && mFirstChild.getTop() == 0) {
129 | return true;
130 | }
131 | return false;
132 | }
133 |
134 | /**
135 | * 判断RcyclerView是否在底部
136 | *
137 | * @return
138 | */
139 | private boolean isRvReachBottom() {
140 | int checkPos = mRecyclerView.getAdapter().getItemCount() - 1;
141 |
142 | View mLastChild = mRecyclerView.getChildAt(mRecyclerView.getChildCount() - 1);
143 | int rvPos = mRecyclerView.getChildAdapterPosition(mLastChild);
144 | // 当且仅当第一个可视节点==0 切其top==0的时候 此时rv到达顶部
145 | DebugLog.e("rvPos:" + rvPos + " child bottom: " + mLastChild.getBottom() + "rv B: " + mRecyclerView.getBottom() + " meight:" + getMeasuredHeight() + " body heifghtg:" + body.getMeasuredHeight());
146 | if (rvPos == checkPos && mLastChild.getBottom() - mLastChild.getTop() == mLastChild.getMeasuredHeight()) {
147 | DebugLog.e("reach bootom");
148 | return true;
149 | }
150 | return false;
151 | }
152 |
153 | /**
154 | * 刚开始的时候 Intercept == false
155 | * RecyclerView可以进行滑动
156 | *
157 | * @param ev
158 | * @return
159 | */
160 | @Override
161 | public boolean onInterceptTouchEvent(MotionEvent ev) {
162 | shouldIntercept = false;
163 |
164 | switch (ev.getAction()) {
165 | case MotionEvent.ACTION_DOWN: {
166 | initDownY = ev.getY();
167 | initDownX = ev.getX();
168 | lastDownX = initDownX;
169 | lastDownY = initDownY;
170 | mViewDragHelper.processTouchEvent(ev);
171 | mRvReachTopWhenDown = isRvReachTop();
172 | mRvReachBottomWhenDown = isRvReachBottom();
173 |
174 | }
175 | break;
176 | case MotionEvent.ACTION_MOVE: {
177 | float my = ev.getY();
178 | float mx = ev.getX();
179 | float dx = mx - initDownX;
180 | float dy = my - initDownY;
181 |
182 | /**
183 | * 判断是否为下移,如果是下移,切在down的时候RvReachTop,那么就要开始Intercept
184 | * 下移的条件是 dy > touchSlop && checkDegree >45
185 | */
186 | DebugLog.e("check Degree :" + checkDegree(dx, dy) + " dy : " + dy + " mRcouTop:" + mRvReachTopWhenDown);
187 | if (!shouldIntercept && mRvReachTopWhenDown && dy > mTouchSlop && (checkDegree(dx, dy) > 45 || checkDegree(dx, dy) < -45)) {
188 | DebugLog.e("reach touch true" + " dd : " + checkDegree(dx, dy));
189 | shouldIntercept = true;
190 | mViewDragHelper.processTouchEvent(ev);
191 | } else if (!shouldIntercept && mRvReachBottomWhenDown && -dy > mTouchSlop && (checkDegree(dx, dy) > 45 || checkDegree(dx, dy) < -45)) {
192 | shouldIntercept = true;
193 | mViewDragHelper.processTouchEvent(ev);
194 | }
195 | }
196 | break;
197 | case MotionEvent.ACTION_UP:
198 | case MotionEvent.ACTION_CANCEL: {
199 | shouldIntercept = false;
200 | }
201 | break;
202 | }
203 | return shouldIntercept && mViewDragHelper.shouldInterceptTouchEvent(ev);
204 | }
205 |
206 | private int checkDegree(float dx, float dy) {
207 | return (int) (Math.atan(dy / dx) * 180 / Math.PI);
208 | }
209 |
210 | @Override
211 | public void computeScroll() {
212 | if (mViewDragHelper.continueSettling(true)) {
213 | ViewCompat.postInvalidateOnAnimation(this);
214 | }
215 | }
216 |
217 | @Override
218 | public boolean onTouchEvent(MotionEvent event) {
219 | mViewDragHelper.processTouchEvent(event);
220 | switch (event.getAction()) {
221 | case MotionEvent.ACTION_UP:
222 | if (mRvReachTopWhenDown) {
223 | /**
224 | * down事件的时候,Rv处于顶部,因此此处是下拉刷新
225 | * 要做的事情:
226 | * 1. 判断拉下来的高度是否超过hanging layout 的高度
227 | * 如果超过了,那么就可以将hanging layout给hang了
228 | * 如果没有超过,那么就直接把rv推上去
229 | * 2. 在当次动画没有完结之前,对后来的Up事件不响应
230 | * 3. 如果超过了hanging layout 的高度, 那么就等通知,等到rv通知后,将rv顶到顶部即可
231 | */
232 | int hanging_h = header_hanging_layout.getMeasuredHeight();
233 | DebugLog.e("offset_top:" + offset_top + " hanging_h:" + hanging_h + " header height:" + header.getMeasuredHeight());
234 |
235 | if (offset_top >= hanging_h) {
236 |
237 | /**
238 | * 不将rv上滑
239 | */
240 | if (offset_top == header.getMeasuredHeight() || mViewDragHelper.smoothSlideViewTo(getChildAt(0), 0, header.getMeasuredHeight())) {
241 | ViewCompat.postInvalidateOnAnimation(this);
242 | if (mRLListener != null) {
243 | header_pgb.setVisibility(VISIBLE);
244 | header_down_arrow.setVisibility(INVISIBLE);
245 | mRLListener.onRefresh();
246 | }
247 | }
248 |
249 | } else {
250 | if (mViewDragHelper.smoothSlideViewTo(getChildAt(0), 0, 0)) {
251 | mRvReachTopWhenDown = false;
252 | offset_top = 0;
253 | ViewCompat.postInvalidateOnAnimation(this);
254 | }
255 | }
256 |
257 | // if (mViewDragHelper.smoothSlideViewTo(getChildAt(0), 0, 0)) {
258 | // mRvReachTopWhenDown = false;
259 | // ViewCompat.postInvalidateOnAnimation(this);
260 | // mRLListener.onRefreshComplete();
261 | // }
262 | } else if (mRvReachBottomWhenDown) {
263 | if (mRLListener != null) {
264 | mRLListener.onLoadMore();
265 | }
266 | if (mViewDragHelper.smoothSlideViewTo(getChildAt(0), 0, 0)) {
267 | mRvReachBottomWhenDown = false;
268 | ViewCompat.postInvalidateOnAnimation(this);
269 | mRLListener.onLoadMoreComplete();
270 | }
271 | }
272 | return true;
273 | }
274 | return true;
275 | }
276 |
277 | public void onFinishRefresh() {
278 | /**
279 | * 这里才把hanginglayout的高度给顶回去
280 | */
281 | if (mViewDragHelper.smoothSlideViewTo(getChildAt(0), 0, 0)) {
282 | mRvReachTopWhenDown = false;
283 | ViewCompat.postInvalidateOnAnimation(this);
284 | header_pgb.setVisibility(INVISIBLE);
285 | header_down_arrow.setRotation(0);
286 | header_down_arrow.setVisibility(VISIBLE);
287 | //header_tv.setText("下拉刷新");
288 | setOnce = false;
289 | setOnce1 = false;
290 | }
291 |
292 | }
293 |
294 | public interface RefreshAndLoadMoreListener {
295 | public void onLoadMore();
296 |
297 | public void onRefresh();
298 |
299 | public void onLoadMoreComplete();
300 |
301 | public void onRefreshComplete();
302 | }
303 |
304 | private class DragHelperCallback extends ViewDragHelper.Callback {
305 |
306 | @Override
307 | public boolean tryCaptureView(View child, int pointerId) {
308 | return child == getChildAt(0);
309 | }
310 |
311 | @Override
312 | public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
313 | super.onViewPositionChanged(changedView, left, top, dx, dy);
314 | offset_top = top;
315 | int hanging_h = header_hanging_layout.getMeasuredHeight();
316 | if (offset_top > hanging_h && dy > 0 && !setOnce) {
317 | /**
318 | * 下拉
319 | */
320 | // header_tv.setText("释放刷新");
321 | header_down_arrow.setRotation(180);
322 | setOnce = true;
323 | setOnce1 = false;
324 |
325 | } else if (offset_top < hanging_h && dy <= 0 && !setOnce1) {
326 | /**
327 | * 上滚
328 | */
329 | header_down_arrow.setRotation(0);
330 | setOnce1 = true;
331 | setOnce = false;
332 | // header_tv.setText("下拉刷新");
333 | }
334 | }
335 |
336 | @Override
337 | public int clampViewPositionVertical(View child, int top, int dy) {
338 | DebugLog.e("header : height:" + header.getMeasuredHeight() + " footer height:" + footer.getMeasuredHeight() + " top:" + top);
339 | if (top > header.getMeasuredHeight()) {
340 | top = header.getMeasuredHeight();
341 | }
342 | return top;
343 | }
344 | }
345 | }
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/drawable-hdpi/ic_arrow_downward_black_18dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/drawable-hdpi/ic_arrow_downward_black_18dp.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/drawable-mdpi/ic_arrow_downward_black_18dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/drawable-mdpi/ic_arrow_downward_black_18dp.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_1.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_10.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_11.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_12.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_2.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_3.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_4.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_5.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_6.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_7.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_8.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/drawable-mdpi/loading_50x50_9.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/drawable-xhdpi/ic_arrow_downward_black_18dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/drawable-xhdpi/ic_arrow_downward_black_18dp.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/drawable-xxhdpi/ic_arrow_downward_black_18dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/drawable-xxhdpi/ic_arrow_downward_black_18dp.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/drawable-xxxhdpi/ic_arrow_downward_black_18dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/drawable-xxxhdpi/ic_arrow_downward_black_18dp.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/drawable/pgb_circle.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
10 |
11 |
14 |
15 |
18 |
19 |
22 |
23 |
26 |
27 |
30 |
31 |
34 |
35 |
38 |
39 |
42 |
43 |
46 |
47 |
50 |
51 |
54 |
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/layout/pull_to_refresh_footer.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
16 |
17 |
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/layout/pull_to_refresh_header.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
21 |
22 |
23 |
31 |
32 |
40 |
41 |
42 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goceancx/AndroidLib/21bb547a08426a8a3743c5cabaf2ff391b5d90cb/pulltorefreshandloadmore/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | PullToRefreshAndLoadMore
3 |
4 |
--------------------------------------------------------------------------------
/pulltorefreshandloadmore/src/test/java/com/oceancx/pulltorefreshandloadmore/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.pulltorefreshandloadmore;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/rangeseekbar/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/rangeseekbar/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | minSdkVersion 14
9 | targetSdkVersion 23
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | compile fileTree(dir: 'libs', include: ['*.jar'])
23 | testCompile 'junit:junit:4.12'
24 | compile 'com.android.support:appcompat-v7:23.1.1'
25 | }
26 |
--------------------------------------------------------------------------------
/rangeseekbar/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/oceancx/Development/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/rangeseekbar/src/androidTest/java/com/oceancx/rangeseekbar/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.rangeseekbar;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/rangeseekbar/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/rangeseekbar/src/main/java/com/oceancx/rangeseekbar/RangeSeekBar.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.rangeseekbar;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Canvas;
6 | import android.graphics.Color;
7 | import android.graphics.Paint;
8 | import android.graphics.Path;
9 | import android.graphics.RectF;
10 | import android.graphics.Typeface;
11 | import android.support.v4.widget.NestedScrollView;
12 | import android.support.v4.widget.ViewDragHelper;
13 | import android.util.AttributeSet;
14 | import android.view.MotionEvent;
15 | import android.view.View;
16 | import android.view.ViewGroup;
17 | import android.widget.FrameLayout;
18 | import android.widget.ImageView;
19 |
20 |
21 | /**
22 | * 上面的消息框的spec
23 | * 带改进成支持多指触控的.
24 | * Created by oceancx on 16/1/8.
25 | */
26 | public class RangeSeekBar extends FrameLayout {
27 |
28 | public static final int MODE_TIME = 0;
29 | public static final int MODE_MAX_MIN_VALUE = 1;
30 | View left_img;
31 | View right_img;
32 | ImageView line_img;
33 | Paint paint;
34 | int maxValue, minValue;
35 | int initMinValue, initMaxValue;
36 | ViewDragHelper helper;
37 | boolean firstLayout = true;
38 | int color_red = 0xffFF4081;
39 | double field_min, field_max, field_len;
40 | int mode = MODE_TIME;
41 |
42 |
43 | int lastDx = 0;
44 |
45 | ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
46 | boolean hit_sec = true;
47 | boolean hit_first = true;
48 |
49 |
50 | @Override
51 | public void onViewReleased(View releasedChild, float xvel, float yvel) {
52 | super.onViewReleased(releasedChild, xvel, yvel);
53 | if (mode == MODE_TIME) {
54 | /**
55 | * 将minValue和maxValue规定到半小时的刻度
56 | */
57 | int half_h = 60 * 30;
58 | initMinValue = initMinValue / half_h * half_h;
59 | initMaxValue = initMaxValue / half_h * half_h;
60 | firstLayout = true;
61 |
62 | requestLayout();
63 | invalidate();
64 | }
65 | }
66 |
67 | @Override
68 | public boolean tryCaptureView(View child, int pointerId) {
69 | return child == left_img || child == right_img;
70 | }
71 |
72 | @Override
73 | public int clampViewPositionVertical(View child, int top, int dy) {
74 | return getPaddingTop();
75 | }
76 |
77 | @Override
78 | public int clampViewPositionHorizontal(View child, int left, int dx) {
79 | if (child == left_img) {
80 | if (left < getPaddingLeft()) left = getPaddingLeft();
81 | if (left > getMeasuredWidth() - right_img.getMeasuredWidth() - left_img.getMeasuredWidth() - getPaddingRight())
82 | left = getMeasuredWidth() - right_img.getMeasuredWidth() - left_img.getMeasuredWidth() - getPaddingRight();
83 |
84 | initMinValue = (int) ((left_img.getRight() - field_min) * (maxValue - minValue) / field_len) + minValue;
85 | if (hit_sec && dx > 0)
86 | initMaxValue = (int) ((right_img.getLeft() - field_min) * (maxValue - minValue) / field_len) + minValue;
87 |
88 | } else if (child == right_img) {
89 | if (left < left_img.getMeasuredWidth() + getPaddingLeft()) {
90 | left = left_img.getMeasuredWidth() + getPaddingLeft();
91 | }
92 | if (left > getMeasuredWidth() - right_img.getMeasuredWidth() - getPaddingRight()) {
93 | left = getMeasuredWidth() - right_img.getMeasuredWidth() - getPaddingRight();
94 | }
95 | if (hit_first && dx < 0)
96 | initMinValue = (int) ((left_img.getRight() - field_min) * (maxValue - minValue) / field_len) + minValue;
97 | initMaxValue = (int) ((right_img.getLeft() - field_min) * (maxValue - minValue) / field_len) + minValue;
98 |
99 | }
100 |
101 |
102 | invalidate();
103 | return left;
104 | }
105 |
106 | @Override
107 | public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
108 | // DebugLog.e("changedView :" + changedView.getLeft() + " left:" + left + " top:" + top + " dx:" + dx + " dy:" + dy);
109 | if (changedView == left_img) {
110 | //left_img右滑撞到right_img
111 | if (left + left_img.getMeasuredWidth() - dx == right_img.getLeft() && dx > 0) {
112 | if (hit_sec) {
113 | right_img.offsetLeftAndRight(dx);
114 | return;
115 | }
116 | }
117 | if (-(left + left_img.getMeasuredWidth() - right_img.getLeft()) <= helper.getTouchSlop() / 3 && dx > 0) {
118 | left_img.offsetLeftAndRight(-(left + left_img.getMeasuredWidth() - right_img.getLeft()));
119 | initMinValue = (int) ((left_img.getRight() - field_min) * (maxValue - minValue) / field_len) + minValue;
120 | hit_sec = true;
121 | } else {
122 | hit_sec = false;
123 | }
124 | } else if (changedView == right_img) {
125 | //right_img左滑撞到左边img
126 | if (left - dx == left_img.getRight() && dx < 0) {
127 | if (hit_first) {
128 | left_img.offsetLeftAndRight(dx);
129 | return;
130 | }
131 | }
132 | if ((left - left_img.getRight()) <= helper.getTouchSlop() / 3 && dx < 0) {
133 | right_img.offsetLeftAndRight(-(left - left_img.getRight()));
134 | initMaxValue = (int) ((right_img.getLeft() - field_min) * (maxValue - minValue) / field_len) + minValue;
135 | hit_first = true;
136 | } else {
137 | hit_first = false;
138 | }
139 |
140 | }
141 |
142 | }
143 |
144 | };
145 |
146 | int rect_w = 42, rect_h = 20, rect_radius = 8;
147 | int triangle_b = 8, triangle_h = 4;
148 | int font_size = 14;
149 |
150 |
151 | public RangeSeekBar(Context context) {
152 | this(context, null);
153 | }
154 |
155 | public RangeSeekBar(Context context, AttributeSet attrs) {
156 | this(context, attrs, 0);
157 | }
158 |
159 |
160 | public RangeSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
161 | super(context, attrs, defStyleAttr);
162 | final TypedArray a = context.obtainStyledAttributes(
163 | attrs, R.styleable.RangeSeekBar, defStyleAttr, defStyleAttr);
164 | mode = a.getInteger(R.styleable.RangeSeekBar_range_mode, -1);
165 | if (mode == -1) mode = MODE_TIME;
166 | if (mode == MODE_TIME) {
167 | minValue = 0;
168 | maxValue = 60 * 60 * 24;
169 | } else {
170 | minValue = a.getInteger(R.styleable.RangeSeekBar_min_value, -1);
171 | if (minValue == -1) minValue = 0;
172 |
173 | maxValue = a.getInteger(R.styleable.RangeSeekBar_max_value, -1);
174 | if (maxValue == -1) maxValue = Integer.MAX_VALUE;
175 | }
176 | initMinValue = a.getInteger(R.styleable.RangeSeekBar_init_min_value, minValue);
177 | initMaxValue = a.getInteger(R.styleable.RangeSeekBar_init_max_value, maxValue);
178 |
179 | a.recycle();
180 |
181 |
182 | helper = ViewDragHelper.create(this, callback);
183 | paint = new Paint(Paint.ANTI_ALIAS_FLAG);
184 | setWillNotDraw(false);
185 |
186 | }
187 |
188 | @Override
189 | protected void onFinishInflate() {
190 | super.onFinishInflate();
191 | if (getChildCount() < 2) throw new IllegalArgumentException("孩子节点要超过2个");
192 | left_img = getChildAt(1);
193 | right_img = getChildAt(2);
194 | line_img = (ImageView) getChildAt(0);
195 |
196 | }
197 |
198 | @Override
199 | public boolean onInterceptTouchEvent(MotionEvent ev) {
200 | return helper.shouldInterceptTouchEvent(ev);
201 | }
202 |
203 | @Override
204 | public boolean onTouchEvent(MotionEvent event) {
205 |
206 | helper.processTouchEvent(event);
207 | if (helper.isCapturedViewUnder((int) event.getX(), (int) event.getY())) {
208 | View view = findScrollView(this);
209 | if (view != null) {
210 | ((ViewGroup) view).requestDisallowInterceptTouchEvent(true);
211 | }
212 | }
213 | return true;
214 | }
215 |
216 | /**
217 | * 防止引起父scrollView垂直方向抖动
218 | *
219 | * @param view
220 | * @return
221 | */
222 | public ViewGroup findScrollView(View view) {
223 | if (view instanceof NestedScrollView) {
224 | return (ViewGroup) view;
225 | } else if (view == null) return null;
226 | else if (view.getParent() instanceof ViewGroup)
227 | return findScrollView((View) view.getParent());
228 | else return null;
229 | }
230 |
231 | int last_dx = 0;
232 |
233 | @Override
234 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
235 | super.onLayout(changed, left, top, right, bottom);
236 |
237 | if (firstLayout) {
238 | firstLayout = false;
239 | field_min = getPaddingLeft() + left_img.getMeasuredWidth();
240 | field_max = getMeasuredWidth() - getPaddingRight() - right_img.getMeasuredWidth();
241 | field_len = field_max - field_min;
242 | }
243 | last_dx = (int) ((initMinValue - minValue) * field_len * 1.0f / (maxValue - minValue));
244 | left_img.offsetLeftAndRight(last_dx);
245 |
246 | last_dx = (int) ((initMaxValue - minValue) * field_len * 1.0f / (maxValue - minValue));
247 | right_img.offsetLeftAndRight(last_dx + left_img.getMeasuredWidth());
248 |
249 |
250 | }
251 |
252 | @Override
253 | protected void onDetachedFromWindow() {
254 | super.onDetachedFromWindow();
255 | helper = null;
256 | }
257 |
258 | @Override
259 | protected void dispatchDraw(Canvas canvas) {
260 | super.dispatchDraw(canvas);
261 |
262 | paint.reset();
263 | //红色
264 | paint.setColor(0xffFF4081);
265 | paint.setStyle(Paint.Style.STROKE);
266 | paint.setStrokeWidth(line_img.getMeasuredHeight());
267 |
268 | int left, right, top, bottom;
269 | int half_line_img_h = line_img.getMeasuredHeight() / 2;
270 |
271 | left = left_img.getRight();
272 | top = line_img.getTop() + half_line_img_h;
273 | right = right_img.getLeft();
274 | bottom = line_img.getTop() + half_line_img_h;
275 | //画遮盖线
276 | canvas.drawLine(left, top, right, bottom, paint);
277 |
278 | int half_left_img_w = left_img.getMeasuredWidth() / 2;
279 | left = (int) (left_img.getLeft() + half_left_img_w - pxToDp(rect_w) / 2);
280 | top = (int) (left_img.getTop() - pxToDp(rect_h + triangle_h));
281 | drawBlueRoundRectWithDownTriangleWithText(canvas, left, top, initMinValue);
282 |
283 |
284 | int half_right_img_w = right_img.getMeasuredWidth() / 2;
285 | left = (int) (right_img.getLeft() + half_right_img_w - pxToDp(rect_w) / 2);
286 | top = (int) (right_img.getBottom() + pxToDp(triangle_h));
287 | drawBlueRoundRectWithUpTriangleWithText(canvas, left, top, initMaxValue);
288 | }
289 |
290 |
291 | private String secToHHMM(int sec) {
292 |
293 | int hour, min;
294 | hour = sec / (60 * 60);
295 | min = (sec - hour * 60 * 60) / 60;
296 |
297 | return (hour < 10 ? "0" + hour : "" + hour) + ":" +
298 | (min < 10 ? "0" + min : "" + min);
299 | }
300 |
301 | private void drawBlueRoundRectWithDownTriangleWithText(Canvas canvas, float x, float y, int value) {
302 | /**
303 | * 画圆角矩形 还有 下面的三角形
304 | * spec rect : w : 100 h : 40 radius : 8
305 | * spec triangle : b:10 h:5 5√2 5√2
306 | * number: font-size : 28px line-height : 40px
307 | * Canvas画图形参考: http://blog.csdn.net/rhljiayou/article/details/7212620
308 | */
309 | if (paint == null) paint = new Paint(Paint.ANTI_ALIAS_FLAG);
310 | paint.reset();
311 | paint.setStyle(Paint.Style.FILL);
312 | paint.setColor(color_red);
313 | // canvas.clipRect(x, y, x + pxToDp(rect_w), y + pxToDp(rect_h + triangle_h));
314 | RectF roundRect = new RectF(x, y, x + pxToDp(rect_w), y + pxToDp(rect_h));// 设置个新的长方形
315 | canvas.drawRoundRect(roundRect, rect_radius, rect_radius, paint);
316 | Path path = new Path();
317 | path.moveTo(x + pxToDp(rect_w / 2 - triangle_b / 2), y + pxToDp(rect_h));
318 | path.lineTo(x + pxToDp(rect_w / 2), y + pxToDp(rect_h + triangle_h));
319 | path.lineTo(x + pxToDp(rect_w / 2 + triangle_b / 2), y + pxToDp(rect_h));
320 | path.close();
321 | canvas.drawPath(path, paint);
322 |
323 | paint.reset();
324 | paint.setAntiAlias(true);
325 | paint.setTextSize(pxToDp(font_size));
326 | paint.setColor(Color.WHITE);
327 | paint.setTypeface(Typeface.DEFAULT_BOLD);
328 |
329 | Paint.FontMetricsInt fontMetrics = paint.getFontMetricsInt();
330 | // 转载请注明出处:http://blog.csdn.net/hursing
331 | int baseline = (int) ((roundRect.bottom + roundRect.top - fontMetrics.bottom - fontMetrics.top) / 2);
332 | // 下面这行是实现水平居中,drawText对应改为传入targetRect.centerX()
333 | paint.setTextAlign(Paint.Align.CENTER);
334 | if (mode == MODE_TIME)
335 | canvas.drawText(secToHHMM(value), roundRect.centerX(), baseline, paint);
336 | else if (MODE_MAX_MIN_VALUE == mode)
337 | canvas.drawText(String.valueOf(value), roundRect.centerX(), baseline, paint);
338 |
339 | }
340 |
341 | private void drawBlueRoundRectWithUpTriangleWithText(Canvas canvas, int x, int y, int value) {
342 | if (paint == null) paint = new Paint(Paint.ANTI_ALIAS_FLAG);
343 | paint.reset();
344 | paint.setStyle(Paint.Style.FILL);
345 | paint.setColor(color_red);
346 |
347 | // canvas.clipRect(x, y - triangle_h, x + pxToDp(rect_w), y + pxToDp(rect_h));
348 | RectF roundRect = new RectF(x, y, x + pxToDp(rect_w), y + pxToDp(rect_h));// 设置个新的长方形
349 | canvas.drawRoundRect(roundRect, rect_radius, rect_radius, paint);
350 |
351 | Path path = new Path();
352 | path.moveTo(x + pxToDp(rect_w / 2 - triangle_b / 2), y);
353 | path.lineTo(x + pxToDp(rect_w / 2), y - pxToDp(triangle_h));
354 | path.lineTo(x + pxToDp(rect_w / 2 + triangle_b / 2), y);
355 | path.close();
356 | canvas.drawPath(path, paint);
357 |
358 | paint.reset();
359 | paint.setAntiAlias(true);
360 | paint.setTextSize(pxToDp(font_size));
361 | paint.setColor(Color.WHITE);
362 | paint.setTypeface(Typeface.DEFAULT_BOLD);
363 |
364 | Paint.FontMetricsInt fontMetrics = paint.getFontMetricsInt();
365 | // 转载请注明出处:http://blog.csdn.net/hursing
366 | int baseline = (int) ((roundRect.bottom + roundRect.top - fontMetrics.bottom - fontMetrics.top) / 2);
367 | // 下面这行是实现水平居中,drawText对应改为传入targetRect.centerX()
368 | paint.setTextAlign(Paint.Align.CENTER);
369 | if (mode == MODE_TIME)
370 | canvas.drawText(secToHHMM(value), roundRect.centerX(), baseline, paint);
371 | else if (MODE_MAX_MIN_VALUE == mode)
372 | canvas.drawText(String.valueOf(value), roundRect.centerX(), baseline, paint);
373 | }
374 |
375 |
376 | private float pxToDp(int pix) {
377 | final float scale = getResources().getDisplayMetrics().density;
378 | return pix * scale;
379 | }
380 |
381 |
382 | public void setMode(int mode) {
383 | if (mode > 1) return;
384 | this.mode = mode;
385 | firstLayout = true;
386 | requestLayout();
387 | }
388 |
389 | public void setSeekRange(int mode, int min, int max) {
390 | setSeekRange(mode, min, max, min, max);
391 | }
392 |
393 | public void setSeekRange(int mode, int min, int max, int initMin, int initMax) {
394 | if (mode > 1) return;
395 | this.mode = mode;
396 | this.minValue = min;
397 | this.maxValue = max;
398 | this.initMinValue = initMin;
399 | this.initMaxValue = initMax;
400 | firstLayout = true;
401 | //这句话 位置比较关键
402 | invalidate();
403 | requestLayout();
404 | }
405 |
406 | public int getInitMinValue() {
407 | return initMinValue;
408 | }
409 |
410 | public int getInitMaxValue() {
411 | return initMaxValue;
412 | }
413 | }
--------------------------------------------------------------------------------
/rangeseekbar/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/rangeseekbar/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | RangeSeekBar
3 |
4 |
--------------------------------------------------------------------------------
/rangeseekbar/src/test/java/com/oceancx/rangeseekbar/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.rangeseekbar;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | 个人android开源库,先来一个appetizer
2 |
3 |
4 |
5 | RangeSeekBar => 涉及源码文件:RangeSeekBar.java,RangeSeekActivity.java.
6 |
7 | 简介:主要使用了ViewDragHelper来简化处理.练手之作,见笑了,UI部分基本完成,筛选范围等数据逻辑方面还没有加.
8 |
9 | 2016-02-19-更新:
10 |
11 | 1. 添加两种模式 时间范围选择 整数范围选择
12 | 2. 添加setSeekRange方法 可以重新设置控件
13 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':uilib', ':rangeseekbar', ':pulltorefreshandloadmore'
2 |
--------------------------------------------------------------------------------
/uilib/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/uilib/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | minSdkVersion 14
9 | targetSdkVersion 23
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | compile 'com.android.support:appcompat-v7:23.+'
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | testCompile 'junit:junit:4.12'
25 | }
26 |
--------------------------------------------------------------------------------
/uilib/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/oceancx/Development/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/uilib/src/androidTest/java/com/oceancx/uilib/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.uilib;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/uilib/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/uilib/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | UILib
3 |
4 |
--------------------------------------------------------------------------------
/uilib/src/test/java/com/oceancx/uilib/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.oceancx.uilib;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------