├── .gitignore ├── LICENSE ├── README.md ├── app ├── build.gradle ├── libs │ ├── ZHConverter.jar │ └── pinyin4j-2.5.0.jar ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── licenses.html │ ├── java │ └── info │ │ └── papdt │ │ └── express │ │ └── helper │ │ ├── api │ │ └── KuaiDi100Helper.java │ │ ├── dao │ │ └── ExpressDatabase.java │ │ ├── support │ │ ├── AddTrackReceiver.java │ │ ├── ConnectivityReceiver.java │ │ ├── CrashHandler.java │ │ ├── Express.java │ │ ├── ExpressResult.java │ │ ├── HttpUtils.java │ │ ├── ReminderService.java │ │ ├── Settings.java │ │ └── Utility.java │ │ ├── ui │ │ ├── AbsActivity.java │ │ ├── AddActivity.java │ │ ├── CompanySelectActivity.java │ │ ├── DetailsActivity.java │ │ ├── MainActivity.java │ │ ├── SettingsActivity.java │ │ ├── TestActivity.java │ │ ├── adapter │ │ │ ├── CompanyListRecyclerAdapter.java │ │ │ ├── HomeCardRecyclerAdapter.java │ │ │ └── HomePagerAdapter.java │ │ ├── common │ │ │ └── MyRecyclerViewAdapter.java │ │ └── fragment │ │ │ ├── BaseHomeFragment.java │ │ │ ├── HomeFragment.java │ │ │ ├── ReceivedListFragment.java │ │ │ ├── UnreceivedListFragment.java │ │ │ └── settings │ │ │ ├── SettingsLicense.java │ │ │ └── SettingsMain.java │ │ └── view │ │ ├── SlidingTabLayout.java │ │ └── SlidingTabStrip.java │ └── res │ ├── anim │ ├── card_slide_in.xml │ └── state_raise.xml │ ├── drawable-hdpi │ ├── ic_add_white_24dp.png │ ├── ic_assignment_black_24dp.png │ ├── ic_assignment_returned_white_24dp.png │ ├── ic_assignment_turned_in_white_24dp.png │ ├── ic_done_white_24dp.png │ ├── ic_event_note_black_24dp.png │ ├── ic_home_white_24dp.png │ ├── ic_launcher_webp.webp │ ├── ic_local_phone_white_24dp.png │ ├── ic_local_shipping_black_24dp.png │ ├── ic_local_shipping_white_24dp.png │ ├── ic_mode_edit_white_24dp.png │ ├── ic_more_horiz_black_24dp.png │ ├── ic_settings_white_24dp.png │ ├── ic_visibility_off_white_24dp.png │ └── ic_visibility_white_24dp.png │ ├── drawable-mdpi │ ├── ic_add_white_24dp.png │ ├── ic_assignment_black_24dp.png │ ├── ic_assignment_returned_white_24dp.png │ ├── ic_assignment_turned_in_white_24dp.png │ ├── ic_done_white_24dp.png │ ├── ic_event_note_black_24dp.png │ ├── ic_home_white_24dp.png │ ├── ic_launcher_webp.webp │ ├── ic_local_phone_white_24dp.png │ ├── ic_local_shipping_black_24dp.png │ ├── ic_local_shipping_white_24dp.png │ ├── ic_mode_edit_white_24dp.png │ ├── ic_more_horiz_black_24dp.png │ ├── ic_settings_white_24dp.png │ ├── ic_visibility_off_white_24dp.png │ └── ic_visibility_white_24dp.png │ ├── drawable-xhdpi │ ├── ic_add_white_24dp.png │ ├── ic_assignment_black_24dp.png │ ├── ic_assignment_returned_white_24dp.png │ ├── ic_assignment_turned_in_white_24dp.png │ ├── ic_done_white_24dp.png │ ├── ic_event_note_black_24dp.png │ ├── ic_home_white_24dp.png │ ├── ic_launcher_webp.webp │ ├── ic_local_phone_white_24dp.png │ ├── ic_local_shipping_black_24dp.png │ ├── ic_local_shipping_white_24dp.png │ ├── ic_mode_edit_white_24dp.png │ ├── ic_more_horiz_black_24dp.png │ ├── ic_settings_white_24dp.png │ ├── ic_visibility_off_white_24dp.png │ └── ic_visibility_white_24dp.png │ ├── drawable-xxhdpi │ ├── background_title_webp.webp │ ├── ic_add_white_24dp.png │ ├── ic_assignment_black_24dp.png │ ├── ic_assignment_returned_white_24dp.png │ ├── ic_assignment_turned_in_white_24dp.png │ ├── ic_done_white_24dp.png │ ├── ic_event_note_black_24dp.png │ ├── ic_home_white_24dp.png │ ├── ic_launcher_webp.webp │ ├── ic_local_phone_white_24dp.png │ ├── ic_local_shipping_black_24dp.png │ ├── ic_local_shipping_white_24dp.png │ ├── ic_mode_edit_white_24dp.png │ ├── ic_more_horiz_black_24dp.png │ ├── ic_settings_white_24dp.png │ ├── ic_visibility_off_white_24dp.png │ └── ic_visibility_white_24dp.png │ ├── drawable │ └── alipay.webp │ ├── layout-land │ ├── activity_add.xml │ └── activity_details.xml │ ├── layout-v21 │ └── card_express_item.xml │ ├── layout │ ├── activity_add.xml │ ├── activity_details.xml │ ├── activity_main.xml │ ├── activity_select_company.xml │ ├── activity_settings.xml │ ├── activity_test.xml │ ├── card_express_item.xml │ ├── dialog_custom_token.xml │ ├── dialog_donate.xml │ ├── drawer_list_item.xml │ ├── fragment_drawer.xml │ ├── fragment_home.xml │ ├── fragment_license.xml │ ├── fragment_placeholder.xml │ ├── list_item_company.xml │ ├── padding.xml │ ├── simple_list_item.xml │ └── tab_indicator.xml │ ├── menu │ ├── details_menu.xml │ ├── details_menu_editing.xml │ ├── main_menu.xml │ └── select_company_menu.xml │ ├── values-v19 │ └── styles.xml │ ├── values-v21 │ ├── color.xml │ └── styles.xml │ ├── values-w820dp │ └── dimens.xml │ ├── values-zh-rCN │ └── strings.xml │ ├── values-zh-rTW │ └── strings.xml │ ├── values │ ├── color.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml │ └── xml │ └── pref_main.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── libraries ├── PersistentSearch │ ├── .gitattributes │ ├── .gitignore │ ├── AndroidManifest.xml │ ├── README.md │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── project.properties │ ├── res │ │ ├── anim │ │ │ └── anim_down.xml │ │ ├── drawable-hdpi │ │ │ ├── ic_action_mic.png │ │ │ ├── ic_clear.png │ │ │ ├── ic_up.png │ │ │ └── search_bg.9.png │ │ ├── drawable-mdpi │ │ │ ├── ic_action_mic.png │ │ │ ├── ic_clear.png │ │ │ ├── ic_up.png │ │ │ └── search_bg.9.png │ │ ├── drawable-xhdpi │ │ │ ├── ic_action_mic.png │ │ │ ├── ic_clear.png │ │ │ ├── ic_up.png │ │ │ └── search_bg.9.png │ │ ├── drawable-xxhdpi │ │ │ ├── ic_action_mic.png │ │ │ ├── ic_clear.png │ │ │ ├── ic_up.png │ │ │ ├── search_bg.9.png │ │ │ ├── search_bg_shadow.9.png │ │ │ ├── search_bg_transparent.9.png │ │ │ └── search_frame.9.png │ │ ├── layout │ │ │ ├── search_option.xml │ │ │ └── searchbox.xml │ │ └── values │ │ │ └── strings.xml │ └── src │ │ ├── com │ │ └── quinny898 │ │ │ └── library │ │ │ └── persistentsearch │ │ │ ├── SearchBox.java │ │ │ └── SearchResult.java │ │ └── io │ │ └── codetail │ │ ├── animation │ │ ├── RevealAnimator.java │ │ ├── ReverseInterpolator.java │ │ ├── SupportAnimator.java │ │ ├── SupportAnimatorLollipop.java │ │ ├── SupportAnimatorPreL.java │ │ └── ViewAnimationUtils.java │ │ └── widget │ │ ├── RevealFrameLayout.java │ │ └── RevealLinearLayout.java └── SwipeBackLayout │ ├── build.gradle │ └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── me │ │ └── imid │ │ └── swipebacklayout │ │ └── lib │ │ ├── SwipeBackLayout.java │ │ ├── Utils.java │ │ ├── ViewDragHelper.java │ │ └── app │ │ ├── SwipeBackActivity.java │ │ ├── SwipeBackActivityBase.java │ │ └── SwipeBackActivityHelper.java │ └── res │ ├── drawable-xhdpi │ ├── shadow_bottom.png │ ├── shadow_left.png │ └── shadow_right.png │ └── values │ ├── attrs.xml │ └── styles.xml ├── port ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── info │ │ └── papdt │ │ └── express │ │ └── helper │ │ └── port │ │ ├── ExpressHelper.java │ │ └── support │ │ ├── Express.java │ │ └── ExpressResult.java │ └── res │ ├── drawable-xxhdpi │ └── ic_launcher.webp │ └── values │ └── strings.xml ├── settings.gradle └── wearable ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src └── main ├── AndroidManifest.xml ├── java └── info │ └── papdt │ └── express │ └── helper │ └── wearable │ └── MainActivity.java └── res ├── drawable-xhdpi └── ic_launcher_webp.webp ├── layout ├── activity_main.xml ├── rect_activity_main.xml └── round_activity_main.xml └── values └── strings.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | class_files.txt 3 | seeds.txt 4 | unused.txt 5 | /app/build 6 | /build 7 | /bin 8 | /gen 9 | /obj 10 | /buck-out 11 | /out 12 | /.settings 13 | /.buckd 14 | /.directory 15 | /lint.xml 16 | /libs/*/*.so 17 | /libs/*/bin 18 | /libs/*/gen 19 | /libs/*/obj 20 | /libs/*/.settings 21 | /libs/*/.directory 22 | /libs/*/libs/*/bin 23 | /libs/*/libs/*/gen 24 | /libs/*/libs/*/obj 25 | /libs/*/libs/*/.settings 26 | /keystore/publish.keystore 27 | /keystore/publish.keystore.properties 28 | /PagerSlidingTabStrip/bin 29 | /PagerSlidingTabStrip/gen 30 | /.gradle 31 | /.idea/libraries 32 | local.properties 33 | *.iml 34 | .idea/ 35 | .gradle/ 36 | 37 | # Secret Files 38 | /app/src/main/java/info/papdt/express/helper/api/secret 39 | 40 | # Build Files 41 | /libraries/*/build -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ExpressHelper 2 | ## 快递助手(别称:水表助手) 3 | 4 | A Material Design App which can help you check the latest status of express package. 5 | 6 | 一枚帮助你查询最新物流状态的 Material Design 应用。 7 | 8 | ## Deprecated! 9 | 10 | 现在已由重构后的 [Package Tracker](https://github.com/fython/PackageTracker) 取代!请移步到新的 Repo。 11 | 12 | ### License 13 | 14 | ``` 15 | GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 16 | 17 | Copyright (C) 2015 Fython 18 | 19 | This program comes with ABSOLUTELY NO WARRANTY. 20 | This is free software, and you are welcome to redistribute it under certain conditions. 21 | ``` 22 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 21 5 | buildToolsVersion "21.1.2" 6 | defaultConfig { 7 | applicationId "info.papdt.express.helper" 8 | minSdkVersion 15 9 | targetSdkVersion 21 10 | versionCode 14 11 | versionName "1.1.2" 12 | } 13 | compileOptions { 14 | sourceCompatibility JavaVersion.VERSION_1_7 15 | targetCompatibility JavaVersion.VERSION_1_7 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | productFlavors { 24 | } 25 | } 26 | 27 | dependencies { 28 | compile fileTree(dir: 'libs', include: ['*.jar']) 29 | compile project(':libraries:SwipeBackLayout') 30 | compile project(':libraries:PersistentSearch') 31 | compile project(':port') 32 | compile 'com.android.support:appcompat-v7:22.+' 33 | compile 'com.android.support:cardview-v7:22.+' 34 | compile 'com.android.support:support-v13:22.+' 35 | compile 'com.melnykov:floatingactionbutton:1.1.+' 36 | compile 'com.rengwuxian.materialedittext:library:1.8.+' 37 | compile 'de.hdodenhof:circleimageview:1.2.+' 38 | compile 'com.afollestad:material-dialogs:0.6.3.2' 39 | compile 'com.github.ksoichiro:android-observablescrollview:1.5.0' 40 | } 41 | -------------------------------------------------------------------------------- /app/libs/ZHConverter.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/libs/ZHConverter.jar -------------------------------------------------------------------------------- /app/libs/pinyin4j-2.5.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/libs/pinyin4j-2.5.0.jar -------------------------------------------------------------------------------- /app/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 C:\tools\adt-bundle-windows-x86_64-20131030\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 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 16 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 30 | 31 | 32 | 33 | 34 | 38 | 39 | 40 | 41 | 42 | 46 | 47 | 48 | 49 | 50 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/support/AddTrackReceiver.java: -------------------------------------------------------------------------------- 1 | package info.papdt.express.helper.support; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.util.Log; 7 | 8 | import org.json.JSONException; 9 | import org.json.JSONObject; 10 | 11 | import java.io.IOException; 12 | 13 | import info.papdt.express.helper.dao.ExpressDatabase; 14 | 15 | public class AddTrackReceiver extends BroadcastReceiver { 16 | 17 | public static final String EXTRA_ADD_EXPRESS_DATA = "data"; 18 | 19 | private String tempData; 20 | private ExpressDatabase edb; 21 | 22 | @Override 23 | public void onReceive(Context context, Intent intent) { 24 | Log.i("AddTrackReceiver", "onReceived!"); 25 | if (intent.hasExtra(EXTRA_ADD_EXPRESS_DATA)) { 26 | tempData = intent.getStringExtra(EXTRA_ADD_EXPRESS_DATA); 27 | Log.i("AddTrackReceiver", tempData); 28 | edb = ExpressDatabase.getInstance(context); 29 | new Thread() { 30 | @Override 31 | public void run() { 32 | try { 33 | edb.addExpress(Express.buildFromJSONObject(new JSONObject(tempData)).getDataStr(), null); 34 | } catch (JSONException e) { 35 | e.printStackTrace(); 36 | } 37 | try { 38 | edb.save(); 39 | Log.i("AddTrackReceiver", "Succeed!"); 40 | } catch (IOException e) { 41 | e.printStackTrace(); 42 | } catch (JSONException e) { 43 | e.printStackTrace(); 44 | } 45 | } 46 | }.start(); 47 | } 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/support/ConnectivityReceiver.java: -------------------------------------------------------------------------------- 1 | package info.papdt.express.helper.support; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.net.ConnectivityManager; 7 | import android.util.Log; 8 | 9 | /** 10 | * 11 | * @author PeterCxy 12 | * 13 | */ 14 | 15 | public class ConnectivityReceiver extends BroadcastReceiver { 16 | 17 | public static boolean isWIFI = true; 18 | 19 | @Override 20 | public void onReceive(Context context, Intent intent) { 21 | if (readNetworkState(context)) { 22 | Log.i("ConnectivityReceiver", "Start ReminderService."); 23 | Utility.startServices(context); 24 | } else { 25 | Log.i("ConnectivityReceiver", "Stop ReminderService."); 26 | Utility.stopServices(context); 27 | } 28 | } 29 | 30 | public static boolean readNetworkState(Context context) { 31 | if (context == null) return false; 32 | 33 | ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 34 | 35 | if (cm != null && cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnected()) { 36 | isWIFI = (cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI); 37 | return true; 38 | } else { 39 | return false; 40 | } 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/support/CrashHandler.java: -------------------------------------------------------------------------------- 1 | package info.papdt.express.helper.support; 2 | 3 | import android.content.Context; 4 | import android.content.pm.PackageInfo; 5 | import android.os.Build; 6 | import android.os.Environment; 7 | 8 | import java.io.File; 9 | import java.io.PrintWriter; 10 | 11 | public class CrashHandler implements Thread.UncaughtExceptionHandler 12 | { 13 | public static String CRASH_DIR = Environment.getExternalStorageDirectory().getPath() + "/"; 14 | public static String CRASH_LOG = CRASH_DIR + "ExpressHelper_CrashLog_%s.log"; 15 | public static String CRASH_TAG = CRASH_DIR + ".crashed"; 16 | 17 | private static String ANDROID = Build.VERSION.RELEASE; 18 | private static String MODEL = Build.MODEL; 19 | private static String MANUFACTURER = Build.MANUFACTURER; 20 | 21 | public static String VERSION = "Unknown"; 22 | 23 | private Thread.UncaughtExceptionHandler mPrevious; 24 | 25 | public static void init(Context context) { 26 | try { 27 | PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); 28 | VERSION = info.versionName + info.versionCode; 29 | } catch (Exception e) { 30 | throw new RuntimeException(e); 31 | } 32 | } 33 | 34 | public static void register() { 35 | new CrashHandler(); 36 | } 37 | 38 | private CrashHandler() { 39 | mPrevious = Thread.currentThread().getUncaughtExceptionHandler(); 40 | Thread.currentThread().setUncaughtExceptionHandler(this); 41 | } 42 | 43 | @Override 44 | public void uncaughtException(Thread thread, Throwable throwable) { 45 | File f = new File(String.format(CRASH_LOG, System.currentTimeMillis())); 46 | if (f.exists()) { 47 | f.delete(); 48 | } else { 49 | try { 50 | new File(CRASH_DIR).mkdirs(); 51 | f.createNewFile(); 52 | } catch (Exception e) { 53 | return; 54 | } 55 | } 56 | 57 | PrintWriter p; 58 | try { 59 | p = new PrintWriter(f); 60 | } catch (Exception e) { 61 | return; 62 | } 63 | 64 | p.write("Android Version: " + ANDROID + "\n"); 65 | p.write("Device Model: " + MODEL + "\n"); 66 | p.write("Device Manufacturer: " + MANUFACTURER + "\n"); 67 | p.write("App Version: " + VERSION + "\n"); 68 | p.write("*********************\n"); 69 | throwable.printStackTrace(p); 70 | 71 | p.close(); 72 | 73 | try { 74 | new File(CRASH_TAG).createNewFile(); 75 | } catch (Exception e) { 76 | return; 77 | } 78 | 79 | if (mPrevious != null) { 80 | mPrevious.uncaughtException(thread, throwable); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/support/Express.java: -------------------------------------------------------------------------------- 1 | package info.papdt.express.helper.support; 2 | 3 | import android.text.TextUtils; 4 | 5 | import org.json.JSONException; 6 | import org.json.JSONObject; 7 | 8 | public class Express { 9 | 10 | private String companyCode, mailNumber, name; 11 | private String jsonData = null, lastJsonData = null; 12 | private int lastStatus = ExpressResult.STATUS_OTHER; 13 | public boolean shouldPush = true, needPush = true; 14 | 15 | public Express(String companyCode, String mailNumber){ 16 | this(companyCode, mailNumber, mailNumber); 17 | } 18 | 19 | public Express(String companyCode, String mailNumber, String name){ 20 | this.companyCode = companyCode; 21 | this.mailNumber = mailNumber; 22 | this.name = name; 23 | } 24 | 25 | public String getDataStr() { 26 | return jsonData; 27 | } 28 | 29 | public void setData(String jsonStr) { 30 | this.jsonData = jsonStr; 31 | } 32 | 33 | public String getLastDataStr() { 34 | return lastJsonData; 35 | } 36 | 37 | public void setLastData(String lastJsonStr) { 38 | this.lastJsonData = lastJsonStr; 39 | if (this.lastJsonData != null) { 40 | this.lastStatus = getLastData().getTrueStatus(); 41 | } 42 | } 43 | 44 | public int getLastStatus() { 45 | return lastStatus; 46 | } 47 | 48 | public ExpressResult getData() { 49 | return ExpressResult.buildFromJSON(jsonData); 50 | } 51 | 52 | public ExpressResult getLastData() { 53 | return ExpressResult.buildFromJSON(lastJsonData); 54 | } 55 | 56 | public String getCompanyCode(){ 57 | return companyCode; 58 | } 59 | 60 | public String getMailNumber(){ 61 | return mailNumber; 62 | } 63 | 64 | public void setCompanyCode(String companyCode){ 65 | this.companyCode = companyCode; 66 | } 67 | 68 | public void setMailNumber(String mailNumber){ 69 | this.mailNumber = mailNumber; 70 | } 71 | 72 | public JSONObject toJSONObject() { 73 | JSONObject obj0 = new JSONObject(); 74 | try { 75 | obj0.put("name", getName()); 76 | obj0.put("companyCode", getCompanyCode()); 77 | obj0.put("mailNumber", getMailNumber()); 78 | obj0.put("cache", getDataStr()); 79 | obj0.put("lastCache", getLastDataStr()); 80 | obj0.put("lastStatus", getLastStatus()); 81 | obj0.put("needPush", needPush); 82 | obj0.put("shouldPush", shouldPush); 83 | } catch (JSONException e) { 84 | e.printStackTrace(); 85 | } 86 | return obj0; 87 | } 88 | 89 | public static Express buildFromJSONObject(JSONObject obj) throws JSONException { 90 | Express newExpress = new Express(obj.getString("companyCode"), obj.getString("mailNumber")); 91 | String name; 92 | try { 93 | name = obj.getString("name"); 94 | } catch (Exception e) { 95 | name = newExpress.getMailNumber(); 96 | } 97 | newExpress.setName(name); 98 | try { 99 | newExpress.setData(obj.getString("cache")); 100 | } catch (Exception e) { 101 | newExpress.setData(null); 102 | } 103 | 104 | try { 105 | newExpress.setLastData(obj.getString("lastCache")); 106 | } catch (Exception e) { 107 | newExpress.setLastData(null); 108 | } 109 | 110 | try { 111 | newExpress.shouldPush = obj.getBoolean("shouldPush"); 112 | newExpress.needPush = obj.getBoolean("needPush"); 113 | } catch (Exception e) { 114 | 115 | } 116 | return newExpress; 117 | } 118 | 119 | public String getName() { 120 | return name; 121 | } 122 | 123 | public void setName(String name) { 124 | if (name == null) { 125 | this.name = mailNumber; 126 | return; 127 | } else if (TextUtils.isEmpty(name)) { 128 | this.name = mailNumber; 129 | return; 130 | } 131 | this.name = name; 132 | } 133 | 134 | } 135 | -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/support/ExpressResult.java: -------------------------------------------------------------------------------- 1 | package info.papdt.express.helper.support; 2 | 3 | import android.util.Log; 4 | 5 | import java.util.*; 6 | 7 | import info.papdt.express.helper.api.KuaiDi100Helper; 8 | 9 | public class ExpressResult { 10 | 11 | public int status, errCode, update, cache; 12 | public String message, html, mailNo, expSpellName, expTextName, ord; 13 | public ArrayList> data; 14 | 15 | public static final int STATUS_FAILED = 0, STATUS_NORMAL = 1, STATUS_ON_THE_WAY = 2, 16 | STATUS_DELIVERED = 3, STATUS_RETURNED = 4, STATUS_OTHER = 5; 17 | 18 | public ExpressResult() { 19 | data = new ArrayList<>(); 20 | } 21 | 22 | public static ExpressResult buildFromJSON(String jsonStr) { 23 | return KuaiDi100Helper.buildDataFromResultStr(jsonStr); 24 | } 25 | 26 | /** 为了解决奇葩的API把顺丰快递准备签收的状态当成已签收而设 F**k */ 27 | public int getTrueStatus() { 28 | try { 29 | if (expSpellName.equals("shunfeng")) { 30 | if (data.get(data.size() - 1).get("context").contains("准备")) { 31 | return STATUS_ON_THE_WAY; 32 | } else { 33 | return status; 34 | } 35 | } else { 36 | if (data.get(data.size() - 1).get("context").contains("妥投") && 37 | !data.get(data.size() - 1).get("context").contains("未")) { 38 | return STATUS_DELIVERED; 39 | } else { 40 | return status; 41 | } 42 | } 43 | } catch (Exception e) { 44 | return status; 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/support/HttpUtils.java: -------------------------------------------------------------------------------- 1 | package info.papdt.express.helper.support; 2 | 3 | import android.util.Log; 4 | 5 | import org.apache.http.HttpResponse; 6 | import org.apache.http.client.ClientProtocolException; 7 | import org.apache.http.client.methods.HttpGet; 8 | import org.apache.http.impl.client.DefaultHttpClient; 9 | import org.apache.http.util.EntityUtils; 10 | 11 | import java.io.IOException; 12 | 13 | public class HttpUtils { 14 | 15 | public static final String TAG = "HttpUtils"; 16 | public static final int CODE_OKAY = 0, CODE_NETWORK_ERROR = -1, CODE_CLIENT_ERROR = -2, 17 | CODE_NONE_200 = 1; 18 | 19 | public static int get(String url, String[] result) { 20 | HttpResponse httpResponse; 21 | try { 22 | Log.v(TAG, "HTTP请求:" + url); 23 | HttpGet httpGet = new HttpGet(url); 24 | httpResponse = new DefaultHttpClient().execute(httpGet); 25 | if (httpResponse.getStatusLine().getStatusCode() == 200) { 26 | result[0] = EntityUtils.toString(httpResponse.getEntity()); 27 | Log.v(TAG, "返回结果为" + result[0]); 28 | return CODE_OKAY; 29 | } else { 30 | return CODE_NONE_200; 31 | } 32 | } catch (ClientProtocolException e) { 33 | e.printStackTrace(); 34 | return CODE_CLIENT_ERROR; 35 | } catch (IOException e) { 36 | e.printStackTrace(); 37 | return CODE_NETWORK_ERROR; 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/support/ReminderService.java: -------------------------------------------------------------------------------- 1 | package info.papdt.express.helper.support; 2 | 3 | import android.app.IntentService; 4 | import android.app.Notification; 5 | import android.app.NotificationManager; 6 | import android.app.PendingIntent; 7 | import android.content.Context; 8 | import android.content.Intent; 9 | import android.graphics.drawable.BitmapDrawable; 10 | import android.os.Build; 11 | import android.os.IBinder; 12 | import android.util.Log; 13 | 14 | import org.json.JSONException; 15 | 16 | import java.io.IOException; 17 | import java.util.Calendar; 18 | 19 | import info.papdt.express.helper.R; 20 | import info.papdt.express.helper.dao.ExpressDatabase; 21 | import info.papdt.express.helper.ui.DetailsActivity; 22 | 23 | @SuppressWarnings("ALL") 24 | public class ReminderService extends IntentService { 25 | 26 | private static final String TAG = ReminderService.class.getSimpleName(); 27 | 28 | private static final int ID = 100000; 29 | 30 | private Notification produceNotifications(int position, Express exp) { 31 | if (exp != null) { 32 | int defaults = parseDefaults(getApplicationContext()); 33 | 34 | PendingIntent pi; 35 | 36 | Intent i = new Intent(getApplicationContext(), DetailsActivity.class); 37 | i.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 38 | i.putExtra("id", position); 39 | i.putExtra("data", exp.toJSONObject().toString()); 40 | 41 | pi = PendingIntent.getActivity(getApplicationContext(), position, i, PendingIntent.FLAG_UPDATE_CURRENT); 42 | 43 | String title = exp.getName(); 44 | if (exp.getData().getTrueStatus() == ExpressResult.STATUS_DELIVERED) { 45 | title += getString(R.string.notification_delivered); 46 | } else { 47 | if (exp.getData().getTrueStatus() == ExpressResult.STATUS_ON_THE_WAY) { 48 | title += getString(R.string.notification_on_the_way); 49 | } else { 50 | title += getString(R.string.notification_new_message); 51 | } 52 | } 53 | 54 | int smallIcon; 55 | switch (exp.getData().getTrueStatus()) { 56 | case ExpressResult.STATUS_DELIVERED: 57 | smallIcon = R.drawable.ic_done_white_24dp; 58 | break; 59 | case ExpressResult.STATUS_ON_THE_WAY: 60 | smallIcon = R.drawable.ic_assignment_turned_in_white_24dp; 61 | break; 62 | default: 63 | smallIcon = R.drawable.ic_assignment_returned_white_24dp; 64 | } 65 | 66 | Notification n = buildNotification(getApplicationContext(), 67 | title, 68 | exp.getData().data.get(exp.getData().data.size() - 1).get("context"), 69 | Build.VERSION.SDK_INT < 20 ? R.drawable.ic_local_shipping_white_24dp 70 | : R.drawable.ic_local_shipping_black_24dp, 71 | smallIcon, 72 | getResources().getIntArray(R.array.statusColor) [exp.getData().getTrueStatus()], 73 | defaults, 74 | pi, 75 | null); 76 | 77 | n.tickerText = title; 78 | 79 | return n; 80 | } 81 | return null; 82 | } 83 | 84 | public ReminderService() { 85 | super(TAG); 86 | } 87 | 88 | @Override 89 | public IBinder onBind(Intent intent) { 90 | return null; 91 | } 92 | 93 | @Override 94 | public void onHandleIntent(Intent intent) { 95 | boolean isEnabledDontDisturbMode = Settings.getInstance(getApplicationContext()) 96 | .getBoolean(Settings.KEY_NOTIFICATION_DO_NOT_DISTURB, true); 97 | if (isEnabledDontDisturbMode && Utility.isDisturbTime(Calendar.getInstance())) { 98 | Log.i(TAG, "现在是勿扰时间段,跳过检查。"); 99 | return; 100 | } 101 | 102 | NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 103 | 104 | ExpressDatabase db = ExpressDatabase.getInstance(getApplicationContext()); 105 | 106 | db.pullNewDataFromNetwork(false); 107 | try { 108 | db.save(); 109 | } catch (IOException e) { 110 | e.printStackTrace(); 111 | } catch (JSONException e) { 112 | e.printStackTrace(); 113 | } 114 | 115 | for (int i = 0; i < db.size(); i++) { 116 | Express exp = db.getExpress(i); 117 | if (exp.getData().getTrueStatus() != ExpressResult.STATUS_FAILED && exp.needPush && exp.shouldPush) { 118 | if (exp.getLastStatus() == ExpressResult.STATUS_DELIVERED) continue; 119 | Notification n = produceNotifications(i, exp); 120 | if (exp != null) { 121 | nm.notify(i + 20000, n); 122 | exp.needPush = false; 123 | } 124 | } 125 | } 126 | 127 | try { 128 | db.save(); 129 | } catch (IOException e) { 130 | e.printStackTrace(); 131 | } catch (JSONException e) { 132 | e.printStackTrace(); 133 | } 134 | } 135 | 136 | private static int parseDefaults(Context context) { 137 | Settings settings = Settings.getInstance(context); 138 | 139 | return (settings.getBoolean(Settings.KEY_NOTIFICATION_SOUND, true) ? Notification.DEFAULT_SOUND : 0) | 140 | (settings.getBoolean(Settings.KEY_NOTIFICATION_VIBRATE, true) ? Notification.DEFAULT_VIBRATE : 0) | 141 | Notification.DEFAULT_LIGHTS; 142 | } 143 | 144 | @SuppressWarnings("getNotification") 145 | private static Notification buildNotification(Context context, String title, String text, int icon0, int icon1, int color, 146 | int defaults, PendingIntent contentIntent, PendingIntent deleteIntent) { 147 | Notification n; 148 | Notification.Builder builder = new Notification.Builder(context) 149 | .setContentTitle(title) 150 | .setContentText(text) 151 | .setSmallIcon(icon1) 152 | .setLargeIcon(((BitmapDrawable) context.getResources().getDrawable(icon0)).getBitmap()) 153 | .setDefaults(defaults) 154 | .setAutoCancel(true) 155 | .setContentIntent(contentIntent); 156 | 157 | if (Build.VERSION.SDK_INT >= 16) { 158 | if (Build.VERSION.SDK_INT >= 21) { 159 | builder.setColor(color); 160 | } 161 | n = builder.build(); 162 | } else { 163 | n = builder.getNotification(); 164 | } 165 | 166 | return n; 167 | } 168 | 169 | } -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/support/Settings.java: -------------------------------------------------------------------------------- 1 | package info.papdt.express.helper.support; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | 6 | public class Settings { 7 | 8 | public static final String XML_NAME = "settings"; 9 | public static final String KEY_TOKEN_CHOOSE = "token_choose", 10 | KEY_CUSTOM_SECRET = "token_secret", KEY_CUSTOM_ID = "token_custom_id", 11 | KEY_SWIPE_BACK = "swipe_back", 12 | KEY_NOTIFICATION_SOUND = "noti_sound", 13 | KEY_NOTIFICATION_VIBRATE = "noti_vibrate", 14 | KEY_NOTIFICATION_INTERVAL = "noti_interval", 15 | KEY_NOTIFICATION_DO_NOT_DISTURB = "noti_do_not_disturb", 16 | KEY_DISABLE_ANIMATION = "disable_animation", 17 | KEY_NAVIGATION_TINT = "navigation_tint"; 18 | public static final String STATE_SELECTED_TAB = "selected_tab"; 19 | 20 | private static Settings sInstance; 21 | 22 | private SharedPreferences mPrefs; 23 | 24 | public static Settings getInstance(Context context) { 25 | if (sInstance == null) { 26 | sInstance = new Settings(context); 27 | } 28 | return sInstance; 29 | } 30 | 31 | private Settings(Context context) { 32 | mPrefs = context.getSharedPreferences(XML_NAME, Context.MODE_PRIVATE); 33 | } 34 | 35 | public Settings putBoolean(String key, boolean value) { 36 | mPrefs.edit().putBoolean(key, value).commit(); 37 | return this; 38 | } 39 | 40 | public boolean getBoolean(String key, boolean def) { 41 | return mPrefs.getBoolean(key, def); 42 | } 43 | 44 | public Settings putInt(String key, int value) { 45 | mPrefs.edit().putInt(key, value).commit(); 46 | return this; 47 | } 48 | 49 | public int getInt(String key, int defValue) { 50 | return mPrefs.getInt(key, defValue); 51 | } 52 | 53 | 54 | public Settings putString(String key, String value) { 55 | mPrefs.edit().putString(key, value).commit(); 56 | return this; 57 | } 58 | 59 | public String getString(String key, String defValue) { 60 | return mPrefs.getString(key, defValue); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/ui/AbsActivity.java: -------------------------------------------------------------------------------- 1 | package info.papdt.express.helper.ui; 2 | 3 | import android.graphics.Color; 4 | import android.os.Build; 5 | import android.os.Bundle; 6 | import android.support.annotation.LayoutRes; 7 | import android.support.v7.app.ActionBar; 8 | import android.support.v7.widget.Toolbar; 9 | import android.view.MenuItem; 10 | import android.view.View; 11 | 12 | import info.papdt.express.helper.R; 13 | import info.papdt.express.helper.support.Settings; 14 | import info.papdt.express.helper.support.Utility; 15 | import me.imid.swipebacklayout.lib.SwipeBackLayout; 16 | import me.imid.swipebacklayout.lib.app.SwipeBackActivity; 17 | 18 | public abstract class AbsActivity extends SwipeBackActivity { 19 | 20 | protected Toolbar mToolbar; 21 | protected ActionBar mActionBar; 22 | protected Settings mSets; 23 | private SwipeBackLayout mSwipeBackLayout; 24 | 25 | protected int statusBarHeight = 0; 26 | 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState) { 29 | /** Initialize Settings */ 30 | mSets = Settings.getInstance(getApplicationContext()); 31 | 32 | /** Set up translucent status bar */ 33 | if (Build.VERSION.SDK_INT >= 19 && !Utility.isChrome()) { 34 | getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); 35 | statusBarHeight = Utility.getStatusBarHeight(getApplicationContext()); 36 | } 37 | 38 | if (Build.VERSION.SDK_INT >= 21) { 39 | getWindow().setStatusBarColor(Color.TRANSPARENT); 40 | if (mSets.getBoolean(Settings.KEY_NAVIGATION_TINT, true)) { 41 | getWindow().setNavigationBarColor(getResources().getColor(R.color.pink_800)); 42 | } 43 | } 44 | 45 | super.onCreate(savedInstanceState); 46 | } 47 | 48 | protected abstract void setUpViews(); 49 | 50 | @Override 51 | public void setContentView(@LayoutRes int layoutResId) { 52 | super.setContentView(layoutResId); 53 | 54 | try { 55 | View statusHeaderView = findViewById(R.id.statusHeaderView); 56 | statusHeaderView.getLayoutParams().height = statusBarHeight; 57 | } catch (NullPointerException e) { 58 | 59 | } 60 | 61 | try { 62 | mToolbar = (Toolbar) findViewById(R.id.toolbar); 63 | setSupportActionBar(mToolbar); 64 | } catch (Exception e) { 65 | 66 | } 67 | mActionBar = getSupportActionBar(); 68 | 69 | try { 70 | mSwipeBackLayout = getSwipeBackLayout(); 71 | 72 | mSwipeBackLayout.setEdgeTrackingEnabled(SwipeBackLayout.EDGE_LEFT | SwipeBackLayout.EDGE_RIGHT); 73 | mSwipeBackLayout.setEnableGesture(mSets.getBoolean(Settings.KEY_SWIPE_BACK, true)); 74 | } catch (Exception e) { 75 | 76 | } 77 | 78 | setUpViews(); 79 | } 80 | 81 | @Override 82 | public boolean onOptionsItemSelected(MenuItem item) { 83 | if (item.getItemId() == android.R.id.home) { 84 | this.onBackPressed(); 85 | return true; 86 | } 87 | 88 | return super.onOptionsItemSelected(item); 89 | } 90 | 91 | @Override 92 | public void onBackPressed() { 93 | if (mSwipeBackLayout != null && mSwipeBackLayout.isGestureEnabled()) { 94 | scrollToFinishActivity(); 95 | } else { 96 | super.onBackPressed(); 97 | } 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/ui/CompanySelectActivity.java: -------------------------------------------------------------------------------- 1 | package info.papdt.express.helper.ui; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.AsyncTask; 7 | import android.os.Bundle; 8 | import android.os.Handler; 9 | import android.support.v7.widget.LinearLayoutManager; 10 | import android.view.Menu; 11 | import android.view.View; 12 | import android.view.inputmethod.InputMethodManager; 13 | import android.widget.Toast; 14 | 15 | import com.github.ksoichiro.android.observablescrollview.ObservableRecyclerView; 16 | import com.quinny898.library.persistentsearch.SearchBox; 17 | 18 | import java.util.ArrayList; 19 | 20 | import info.papdt.express.helper.R; 21 | import info.papdt.express.helper.api.KuaiDi100Helper; 22 | import info.papdt.express.helper.support.Utility; 23 | import info.papdt.express.helper.ui.adapter.CompanyListRecyclerAdapter; 24 | import info.papdt.express.helper.ui.common.MyRecyclerViewAdapter; 25 | 26 | public class CompanySelectActivity extends AbsActivity { 27 | 28 | private SearchBox mSearchBox; 29 | private ObservableRecyclerView mRecyclerView; 30 | private CompanyListRecyclerAdapter mCompanyListAdapter; 31 | 32 | public static final int REQUEST_CODE_SELECT = 0x100, RESULT_SELECTED = 0x100; 33 | 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | setContentView(R.layout.activity_select_company); 38 | 39 | setSwipeBackEnable(false); 40 | 41 | mToolbar.setTitle(""); 42 | 43 | new Handler().postDelayed(new Runnable() { 44 | @Override 45 | public void run() { 46 | runOnUiThread(new Runnable() { 47 | @Override 48 | public void run() { 49 | openSearchBox(); 50 | } 51 | }); 52 | } 53 | }, 100); 54 | } 55 | 56 | public void openSearchBox() { 57 | mSearchBox.revealFromMenuItem(R.id.action_select_company, this); 58 | mSearchBox.setSearchListener(new SearchBox.SearchListener() { 59 | @Override 60 | public void onSearchOpened() { 61 | new SearchCompanyTask().execute(); 62 | } 63 | 64 | @Override 65 | public void onSearchCleared() { 66 | } 67 | 68 | @Override 69 | public void onSearchClosed() { 70 | close(); 71 | } 72 | 73 | @Override 74 | public void onSearchTermChanged() { 75 | new SearchCompanyTask().execute(mSearchBox.getSearchText()); 76 | } 77 | 78 | @Override 79 | public void onSearch(String result) { 80 | } 81 | 82 | }); 83 | } 84 | 85 | public void close() { 86 | mSearchBox.hideCircularly(this); 87 | hideSoftKeyboard(); 88 | finish(); 89 | } 90 | 91 | private void hideSoftKeyboard() { 92 | InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 93 | imm.hideSoftInputFromWindow(mSearchBox.getEditTextWindowToken(), 0); 94 | } 95 | 96 | @Override 97 | protected void setUpViews() { 98 | mRecyclerView = (ObservableRecyclerView) findViewById(R.id.company_list); 99 | mSearchBox = (SearchBox) findViewById(R.id.searchBox); 100 | 101 | mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); 102 | mRecyclerView.setHasFixedSize(true); 103 | mSearchBox.setHintText(getString(R.string.search_hint_company)); 104 | mSearchBox.setLogoText(""); 105 | } 106 | 107 | @Override 108 | public boolean onCreateOptionsMenu(Menu menu) { 109 | getMenuInflater().inflate(R.menu.select_company_menu, menu); 110 | return super.onCreateOptionsMenu(menu); 111 | } 112 | 113 | public static void launchActivity(Activity mActivity) { 114 | Intent intent = new Intent(mActivity, CompanySelectActivity.class); 115 | intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); 116 | mActivity.startActivityForResult(intent, REQUEST_CODE_SELECT); 117 | } 118 | 119 | public class SearchCompanyTask extends AsyncTask> { 120 | 121 | @Override 122 | protected ArrayList doInBackground(String... params) { 123 | if (params.length > 0) { 124 | return KuaiDi100Helper.searchCompany(params [0]); 125 | } else { 126 | return KuaiDi100Helper.CompanyInfo.info; 127 | } 128 | } 129 | 130 | @Override 131 | protected void onPostExecute(ArrayList result) { 132 | if (result != null) { 133 | mCompanyListAdapter = new CompanyListRecyclerAdapter(result); 134 | mRecyclerView.setAdapter(mCompanyListAdapter); 135 | mCompanyListAdapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() { 136 | @Override 137 | public void onItemClicked(int position) { 138 | Intent intent = new Intent(); 139 | intent.putExtra("company_code", mCompanyListAdapter.getItem(position).code); 140 | setResult(RESULT_SELECTED, intent); 141 | close(); 142 | } 143 | }); 144 | } 145 | } 146 | 147 | } 148 | 149 | public void mic(View v) { 150 | if (Utility.isApplicationAvailable(getApplicationContext(), "com.mokee.assist")) { 151 | Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage("com.mokee.assist"); 152 | startActivity(LaunchIntent); 153 | } else { 154 | Toast.makeText( 155 | getApplicationContext(), 156 | R.string.toast_mic_unsupported, 157 | Toast.LENGTH_SHORT 158 | ).show(); 159 | } 160 | } 161 | 162 | } 163 | -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/ui/SettingsActivity.java: -------------------------------------------------------------------------------- 1 | package info.papdt.express.helper.ui; 2 | 3 | import android.app.Activity; 4 | import android.app.Fragment; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.support.v4.view.ViewCompat; 8 | 9 | import info.papdt.express.helper.R; 10 | import info.papdt.express.helper.ui.fragment.settings.SettingsLicense; 11 | import info.papdt.express.helper.ui.fragment.settings.SettingsMain; 12 | 13 | public class SettingsActivity extends AbsActivity { 14 | 15 | private Fragment mFragment; 16 | private int flag = 0; 17 | 18 | public static final String EXTRA_FLAG = "flag"; 19 | public static final int FLAG_MAIN = 0, FLAG_LICENSE = 1; 20 | 21 | @Override 22 | public void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | 25 | /** 获取传入参数 */ 26 | Intent intent = getIntent(); 27 | flag = intent.getIntExtra(EXTRA_FLAG, FLAG_MAIN); 28 | 29 | setContentView(R.layout.activity_settings); 30 | 31 | mActionBar.setDisplayHomeAsUpEnabled(true); 32 | } 33 | 34 | @Override 35 | public void setUpViews() { 36 | ViewCompat.setElevation(mToolbar, getResources().getDimension(R.dimen.toolbar_elevation)); 37 | 38 | switch (flag) { 39 | case FLAG_MAIN: 40 | mFragment = SettingsMain.newInstance(); 41 | break; 42 | case FLAG_LICENSE: 43 | mFragment = new SettingsLicense(); 44 | break; 45 | } 46 | getFragmentManager().beginTransaction() 47 | .replace(R.id.container, mFragment) 48 | .commit(); 49 | } 50 | 51 | 52 | public static void launchActivity(Activity mActivity, int flag) { 53 | Intent intent = new Intent(mActivity, SettingsActivity.class); 54 | intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); 55 | intent.putExtra(EXTRA_FLAG, flag); 56 | mActivity.startActivity(intent); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/ui/TestActivity.java: -------------------------------------------------------------------------------- 1 | package info.papdt.express.helper.ui; 2 | 3 | import android.os.Bundle; 4 | import android.view.View; 5 | import android.widget.TextView; 6 | 7 | import info.papdt.express.helper.R; 8 | import info.papdt.express.helper.port.ExpressHelper; 9 | import info.papdt.express.helper.port.support.Express; 10 | 11 | public class TestActivity extends AbsActivity { 12 | 13 | private TextView mTextView; 14 | 15 | private Express mExpress; 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity_test); 21 | } 22 | 23 | @Override 24 | protected void setUpViews() { 25 | mTextView = (TextView) findViewById(R.id.tv_test); 26 | findViewById(R.id.btn_check).setOnClickListener(new View.OnClickListener() { 27 | @Override 28 | public void onClick(View v) { 29 | new Thread() { 30 | @Override 31 | public void run() { 32 | mExpress = ExpressHelper.getExpressInfo("顺丰", "233333333333"); 33 | runOnUiThread(new Runnable() { 34 | @Override 35 | public void run() { 36 | mTextView.setText(mExpress.toJSONObject().toString()); 37 | } 38 | }); 39 | } 40 | }.start(); 41 | } 42 | }); 43 | findViewById(R.id.btn_add).setOnClickListener(new View.OnClickListener() { 44 | @Override 45 | public void onClick(View v) { 46 | if (ExpressHelper.addExpressTrackToApp(getApplicationContext(), mExpress)) { 47 | mTextView.setText("添加成功\n" + mTextView.getText().toString()); 48 | } else { 49 | mTextView.setText("添加失败,可能水表助手未安装\n" + mTextView.getText().toString()); 50 | } 51 | } 52 | }); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/ui/adapter/CompanyListRecyclerAdapter.java: -------------------------------------------------------------------------------- 1 | package info.papdt.express.helper.ui.adapter; 2 | 3 | import android.view.LayoutInflater; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | import android.widget.TextView; 7 | 8 | import java.util.ArrayList; 9 | 10 | import de.hdodenhof.circleimageview.CircleImageView; 11 | import info.papdt.express.helper.R; 12 | import info.papdt.express.helper.api.KuaiDi100Helper; 13 | import info.papdt.express.helper.ui.common.MyRecyclerViewAdapter; 14 | 15 | public class CompanyListRecyclerAdapter extends MyRecyclerViewAdapter { 16 | 17 | private ArrayList data; 18 | 19 | public CompanyListRecyclerAdapter(ArrayList data) { 20 | super(false); 21 | this.data = data; 22 | } 23 | 24 | @Override 25 | public ClickableViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 26 | bindContext(parent.getContext()); 27 | View v = LayoutInflater.from(getContext()) 28 | .inflate(R.layout.list_item_company, parent, false); 29 | ViewHolder holder = new ViewHolder(v); 30 | return holder; 31 | } 32 | 33 | @Override 34 | public void onBindViewHolder(ClickableViewHolder holder, int position) { 35 | if (!(holder instanceof ViewHolder)) return; 36 | 37 | super.onBindViewHolder(holder, position); 38 | 39 | ViewHolder h = (ViewHolder) holder; 40 | 41 | h.setTitle(data.get(position).name); 42 | if (data.get(position).phone != null) { 43 | h.tv_info.setVisibility(View.VISIBLE); 44 | h.tv_info.setText(data.get(position).phone); 45 | } else { 46 | if (data.get(position).website != null) { 47 | h.tv_info.setVisibility(View.VISIBLE); 48 | h.tv_info.setText(data.get(position).website); 49 | } else { 50 | h.tv_info.setVisibility(View.GONE); 51 | } 52 | } 53 | } 54 | 55 | @Override 56 | public int getItemCount() { 57 | return data.size(); 58 | } 59 | 60 | public KuaiDi100Helper.CompanyInfo.Company getItem(int pos) { 61 | return data.get(pos); 62 | } 63 | 64 | public class ViewHolder extends ClickableViewHolder { 65 | 66 | public CircleImageView iv_round; 67 | public TextView tv_name, tv_info, tv_center; 68 | 69 | public ViewHolder(View itemView) { 70 | super(itemView); 71 | iv_round = (CircleImageView) itemView.findViewById(R.id.iv_round); 72 | tv_name = (TextView) itemView.findViewById(R.id.tv_title); 73 | tv_info = (TextView) itemView.findViewById(R.id.tv_info); 74 | tv_center = (TextView) itemView.findViewById(R.id.center_text); 75 | } 76 | 77 | public void setTitle(String text) { 78 | tv_name.setText(text); 79 | tv_center.setText(text.substring(0, 1)); 80 | } 81 | 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/ui/adapter/HomeCardRecyclerAdapter.java: -------------------------------------------------------------------------------- 1 | package info.papdt.express.helper.ui.adapter; 2 | 3 | import android.content.Context; 4 | import android.graphics.drawable.ColorDrawable; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.TextView; 9 | 10 | import java.util.Map; 11 | 12 | import de.hdodenhof.circleimageview.CircleImageView; 13 | import info.papdt.express.helper.R; 14 | import info.papdt.express.helper.dao.ExpressDatabase; 15 | import info.papdt.express.helper.support.Express; 16 | import info.papdt.express.helper.support.ExpressResult; 17 | import info.papdt.express.helper.support.Settings; 18 | import info.papdt.express.helper.ui.common.MyRecyclerViewAdapter; 19 | 20 | public class HomeCardRecyclerAdapter extends MyRecyclerViewAdapter { 21 | 22 | private static final int VIEW_TYPE_HEADER = 0; 23 | private static final int VIEW_TYPE_ITEM = 1; 24 | 25 | private ExpressDatabase db; 26 | private int type; 27 | private View headerView; 28 | 29 | private int[] defaultColors; 30 | 31 | public static final int TYPE_ALL = 0, TYPE_UNRECEIVED = 1, TYPE_RECEIVED = 2; 32 | 33 | public HomeCardRecyclerAdapter(Context context, ExpressDatabase db, View headerView) { 34 | this(context, db, TYPE_ALL, headerView); 35 | } 36 | 37 | public HomeCardRecyclerAdapter(Context context, ExpressDatabase db, int type, View headerView) { 38 | super(!Settings.getInstance(context).getBoolean(Settings.KEY_DISABLE_ANIMATION, false)); 39 | this.db = db; 40 | this.defaultColors = context.getResources().getIntArray(R.array.statusColor); 41 | this.type = type; 42 | this.headerView = headerView; 43 | } 44 | 45 | @Override 46 | public ClickableViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 47 | switch (viewType) { 48 | case VIEW_TYPE_HEADER: 49 | return new HeaderViewHolder(headerView); 50 | case VIEW_TYPE_ITEM: 51 | bindContext(parent.getContext()); 52 | View v = LayoutInflater.from(getContext()) 53 | .inflate(R.layout.card_express_item, parent, false); 54 | return new ViewHolder(v); 55 | default: 56 | return null; 57 | } 58 | } 59 | 60 | @Override 61 | public void onBindViewHolder(ClickableViewHolder viewHolder, final int position) { 62 | if (!(viewHolder instanceof ViewHolder)) return; 63 | 64 | super.onBindViewHolder(viewHolder, position); 65 | 66 | Express item = getItem(position + (headerView != null ? -1 : 0)); 67 | 68 | ExpressResult cache = item.getData(); 69 | 70 | ViewHolder holder = (ViewHolder) viewHolder; 71 | 72 | ColorDrawable drawable = new ColorDrawable(defaultColors[cache.getTrueStatus()]); 73 | holder.iv_round.setImageDrawable(drawable); 74 | 75 | holder.tv_title.setText(item.getName()); 76 | 77 | String desp, time; 78 | try { 79 | Map lastData = cache.data.get(cache.data.size() - 1); 80 | holder.tv_center_round.setText(cache.expTextName.substring(0, 1)); 81 | desp = lastData.get("context"); 82 | time = lastData.get("time"); 83 | } catch (Exception e) { 84 | desp = "failed"; 85 | time = "1970/01/01"; 86 | } 87 | holder.tv_desp.setText(desp); 88 | holder.tv_time.setText(time); 89 | } 90 | 91 | public int getExpressCount() { 92 | if (type == TYPE_ALL) { 93 | return db.size(); 94 | } else if (type == TYPE_UNRECEIVED) { 95 | return db.urSize(); 96 | } else if (type == TYPE_RECEIVED) { 97 | return db.okSize(); 98 | } 99 | return -1; 100 | } 101 | 102 | @Override 103 | public int getItemCount() { 104 | int result = getExpressCount(); 105 | if (headerView != null) result++; 106 | return result; 107 | } 108 | 109 | @Override 110 | public int getItemViewType(int position) { 111 | return (position == 0 && headerView != null) ? VIEW_TYPE_HEADER : VIEW_TYPE_ITEM; 112 | } 113 | 114 | public Express getItem(int i) { 115 | if (type == TYPE_ALL) { 116 | return db.getExpress(getExpressCount() - i - 1); 117 | } else if (type == TYPE_UNRECEIVED) { 118 | return db.getUnreceivedArray().get(getExpressCount() - i - 1); 119 | } else if (type == TYPE_RECEIVED) { 120 | return db.getReceivedArray().get(getExpressCount() - i - 1); 121 | } 122 | return null; 123 | } 124 | 125 | public class ViewHolder extends ClickableViewHolder { 126 | 127 | public CircleImageView iv_round; 128 | public TextView tv_title, tv_desp, tv_time, tv_center_round; 129 | 130 | public ViewHolder(View itemView) { 131 | super(itemView); 132 | this.iv_round = (CircleImageView) itemView.findViewById(R.id.iv_round); 133 | this.tv_title = (TextView) itemView.findViewById(R.id.tv_title); 134 | this.tv_desp = (TextView) itemView.findViewById(R.id.tv_desp); 135 | this.tv_time = (TextView) itemView.findViewById(R.id.tv_time); 136 | this.tv_center_round = (TextView) itemView.findViewById(R.id.center_text); 137 | } 138 | 139 | } 140 | 141 | public class HeaderViewHolder extends ClickableViewHolder { 142 | 143 | public HeaderViewHolder(View view) { 144 | super(view); 145 | } 146 | 147 | } 148 | 149 | } -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/ui/adapter/HomePagerAdapter.java: -------------------------------------------------------------------------------- 1 | package info.papdt.express.helper.ui.adapter; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.v4.app.Fragment; 6 | import android.support.v4.app.FragmentManager; 7 | 8 | import com.github.ksoichiro.android.observablescrollview.CacheFragmentStatePagerAdapter; 9 | 10 | import info.papdt.express.helper.R; 11 | import info.papdt.express.helper.ui.fragment.BaseHomeFragment; 12 | import info.papdt.express.helper.ui.fragment.HomeFragment; 13 | import info.papdt.express.helper.ui.fragment.ReceivedListFragment; 14 | import info.papdt.express.helper.ui.fragment.UnreceivedListFragment; 15 | 16 | public class HomePagerAdapter extends CacheFragmentStatePagerAdapter { 17 | 18 | private static String[] TITLES; 19 | 20 | private int mScrollY; 21 | 22 | public HomePagerAdapter(Context context, FragmentManager fm) { 23 | super(fm); 24 | TITLES = context.getResources().getStringArray(R.array.title_sections); 25 | } 26 | 27 | public void setScrollY(int scrollY) { 28 | mScrollY = scrollY; 29 | } 30 | 31 | @Override 32 | protected android.support.v4.app.Fragment createItem(int position) { 33 | Fragment f = null; 34 | switch (position) { 35 | case 0: 36 | f = HomeFragment.newInstance(); 37 | if (0 < mScrollY) { 38 | Bundle args = new Bundle(); 39 | args.putInt(BaseHomeFragment.ARG_INITIAL_POSITION, 1); 40 | f.setArguments(args); 41 | } 42 | break; 43 | case 1: 44 | f = UnreceivedListFragment.newInstance(); 45 | if (0 < mScrollY) { 46 | Bundle args = new Bundle(); 47 | args.putInt(BaseHomeFragment.ARG_INITIAL_POSITION, 1); 48 | f.setArguments(args); 49 | } 50 | break; 51 | case 2: 52 | f = ReceivedListFragment.newInstance(); 53 | if (0 < mScrollY) { 54 | Bundle args = new Bundle(); 55 | args.putInt(BaseHomeFragment.ARG_INITIAL_POSITION, 1); 56 | f.setArguments(args); 57 | } 58 | break; 59 | } 60 | return f; 61 | } 62 | 63 | public void notifyDataSetChanged() { 64 | for (int i = 0; i < 3; i++) { 65 | try { 66 | BaseHomeFragment fragment = (BaseHomeFragment) this.getItemAt(i); 67 | fragment.mHandler.sendEmptyMessage(BaseHomeFragment.FLAG_REFRESH_ADAPTER_ONLY); 68 | } catch (Exception e) { 69 | 70 | } 71 | } 72 | } 73 | 74 | @Override 75 | public int getCount() { 76 | return 3; 77 | } 78 | 79 | @Override 80 | public CharSequence getPageTitle(int position) { 81 | return TITLES[position]; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/ui/common/MyRecyclerViewAdapter.java: -------------------------------------------------------------------------------- 1 | package info.papdt.express.helper.ui.common; 2 | 3 | import android.content.Context; 4 | import android.os.Handler; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.view.View; 7 | import android.view.animation.Animation; 8 | import android.view.animation.AnimationUtils; 9 | 10 | import info.papdt.express.helper.R; 11 | 12 | public abstract class MyRecyclerViewAdapter extends RecyclerView.Adapter { 13 | 14 | private int lastPosition = -1; 15 | private boolean firstLoad = true; 16 | private Context context; 17 | 18 | private boolean useAnimation; 19 | 20 | public MyRecyclerViewAdapter(boolean useAnimation) { 21 | this.useAnimation = useAnimation; 22 | } 23 | 24 | public interface OnItemClickListener { 25 | public void onItemClicked(int position); 26 | } 27 | 28 | public interface OnItemLongClickListener { 29 | public boolean onItemLongClicked(int position); 30 | } 31 | 32 | private OnItemClickListener itemClickListener; 33 | private OnItemLongClickListener itemLongClickListener; 34 | 35 | public void setOnItemClickListener(OnItemClickListener listener) { 36 | this.itemClickListener = listener; 37 | } 38 | 39 | public void setOnItemLongClickListener(OnItemLongClickListener listener) { 40 | this.itemLongClickListener = listener; 41 | } 42 | 43 | public void bindContext(Context context) { 44 | this.context = context; 45 | } 46 | 47 | public Context getContext() { 48 | return this.context; 49 | } 50 | 51 | @Override 52 | public void onBindViewHolder(ClickableViewHolder holder, final int position) { 53 | holder.getParentView().setOnClickListener(new View.OnClickListener() { 54 | @Override 55 | public void onClick(View v) { 56 | if (itemClickListener != null) { 57 | itemClickListener.onItemClicked(position); 58 | } 59 | } 60 | }); 61 | holder.getParentView().setOnLongClickListener(new View.OnLongClickListener() { 62 | @Override 63 | public boolean onLongClick(View v) { 64 | if (itemLongClickListener != null) { 65 | return itemLongClickListener.onItemLongClicked(position); 66 | } else { 67 | return false; 68 | } 69 | } 70 | }); 71 | if (useAnimation) setAnimation(holder.parentView, position); 72 | } 73 | 74 | private void setAnimation(final View viewToAnimate, final int position) { 75 | // If the bound view wasn't previously displayed on screen, it's animated 76 | if (position > lastPosition) { 77 | if (firstLoad) { 78 | viewToAnimate.setAlpha(0f); 79 | new Handler().postDelayed( 80 | new Runnable() { 81 | @Override 82 | public void run() { 83 | Animation animation = AnimationUtils.loadAnimation( 84 | context, 85 | R.anim.card_slide_in 86 | ); 87 | animation.setAnimationListener(new Animation.AnimationListener() { 88 | @Override 89 | public void onAnimationStart(Animation animation) { 90 | viewToAnimate.setAlpha(1f); 91 | firstLoad = true; 92 | } 93 | 94 | @Override 95 | public void onAnimationEnd(Animation animation) { 96 | firstLoad = false; 97 | } 98 | 99 | @Override 100 | public void onAnimationRepeat(Animation animation) { 101 | 102 | } 103 | }); 104 | animation.setFillAfter(true); 105 | viewToAnimate.startAnimation(animation); 106 | } 107 | } 108 | , position * 180); 109 | } else { 110 | Animation animation = AnimationUtils.loadAnimation(context, R.anim.card_slide_in); 111 | viewToAnimate.startAnimation(animation); 112 | } 113 | lastPosition = position; 114 | } 115 | } 116 | 117 | public class ClickableViewHolder extends RecyclerView.ViewHolder { 118 | 119 | private View parentView; 120 | 121 | public ClickableViewHolder(View itemView) { 122 | super(itemView); 123 | this.parentView = itemView; 124 | } 125 | 126 | public View getParentView() { 127 | return parentView; 128 | } 129 | 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/ui/fragment/HomeFragment.java: -------------------------------------------------------------------------------- 1 | package info.papdt.express.helper.ui.fragment; 2 | 3 | import info.papdt.express.helper.ui.adapter.HomeCardRecyclerAdapter; 4 | 5 | public class HomeFragment extends BaseHomeFragment { 6 | 7 | private HomeCardRecyclerAdapter mAdapter; 8 | 9 | public static HomeFragment newInstance() { 10 | HomeFragment fragment = new HomeFragment(); 11 | return fragment; 12 | } 13 | 14 | public HomeFragment() { 15 | } 16 | 17 | @Override 18 | public void setUpAdapter() { 19 | mAdapter = new HomeCardRecyclerAdapter(getActivity().getApplicationContext(), mDB, headerView); 20 | mRecyclerView.setAdapter(mAdapter); 21 | setUpAdapterListener(); 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/ui/fragment/ReceivedListFragment.java: -------------------------------------------------------------------------------- 1 | package info.papdt.express.helper.ui.fragment; 2 | 3 | import info.papdt.express.helper.ui.adapter.HomeCardRecyclerAdapter; 4 | 5 | public class ReceivedListFragment extends BaseHomeFragment { 6 | 7 | private HomeCardRecyclerAdapter mAdapter; 8 | public static ReceivedListFragment newInstance() { 9 | ReceivedListFragment fragment = new ReceivedListFragment(); 10 | return fragment; 11 | } 12 | 13 | public ReceivedListFragment() { 14 | } 15 | 16 | @Override 17 | public void setUpAdapter() { 18 | mAdapter = new HomeCardRecyclerAdapter(getActivity().getApplicationContext(), mDB, HomeCardRecyclerAdapter.TYPE_RECEIVED, headerView); 19 | mRecyclerView.setAdapter(mAdapter); 20 | setUpAdapterListener(); 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/ui/fragment/UnreceivedListFragment.java: -------------------------------------------------------------------------------- 1 | package info.papdt.express.helper.ui.fragment; 2 | 3 | import info.papdt.express.helper.ui.adapter.HomeCardRecyclerAdapter; 4 | 5 | public class UnreceivedListFragment extends BaseHomeFragment { 6 | 7 | private HomeCardRecyclerAdapter mAdapter; 8 | 9 | public static UnreceivedListFragment newInstance() { 10 | UnreceivedListFragment fragment = new UnreceivedListFragment(); 11 | return fragment; 12 | } 13 | 14 | public UnreceivedListFragment() { 15 | } 16 | 17 | @Override 18 | public void setUpAdapter() { 19 | mAdapter = new HomeCardRecyclerAdapter(getActivity().getApplicationContext(), mDB, HomeCardRecyclerAdapter.TYPE_UNRECEIVED, headerView); 20 | mRecyclerView.setAdapter(mAdapter); 21 | setUpAdapterListener(); 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/ui/fragment/settings/SettingsLicense.java: -------------------------------------------------------------------------------- 1 | package info.papdt.express.helper.ui.fragment.settings; 2 | 3 | import android.app.Fragment; 4 | import android.os.Bundle; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.webkit.WebView; 9 | 10 | import info.papdt.express.helper.R; 11 | 12 | public class SettingsLicense extends Fragment { 13 | 14 | @Override 15 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 16 | Bundle savedInstanceState) { 17 | View v = inflater.inflate(R.layout.fragment_license, container, false); 18 | 19 | WebView webView = (WebView) v.findViewById(R.id.webView); 20 | webView.loadUrl("file:///android_asset/licenses.html"); 21 | 22 | getActivity().setTitle(R.string.item_open_source_license); 23 | 24 | return v; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/info/papdt/express/helper/view/SlidingTabStrip.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Google Inc. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package info.papdt.express.helper.view; 18 | 19 | import android.R; 20 | import android.content.Context; 21 | import android.graphics.Canvas; 22 | import android.graphics.Color; 23 | import android.graphics.Paint; 24 | import android.util.AttributeSet; 25 | import android.util.TypedValue; 26 | import android.view.View; 27 | import android.widget.LinearLayout; 28 | 29 | class SlidingTabStrip extends LinearLayout { 30 | 31 | private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 0; 32 | private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26; 33 | private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 1; 34 | private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFF33B5E5; 35 | 36 | private final int mBottomBorderThickness; 37 | private final Paint mBottomBorderPaint; 38 | 39 | private final int mSelectedIndicatorThickness; 40 | private final Paint mSelectedIndicatorPaint; 41 | 42 | private final int mDefaultBottomBorderColor; 43 | 44 | private int mSelectedPosition; 45 | private float mSelectionOffset; 46 | 47 | private SlidingTabLayout.TabColorizer mCustomTabColorizer; 48 | private final SimpleTabColorizer mDefaultTabColorizer; 49 | 50 | SlidingTabStrip(Context context) { 51 | this(context, null); 52 | } 53 | 54 | SlidingTabStrip(Context context, AttributeSet attrs) { 55 | super(context, attrs); 56 | setWillNotDraw(false); 57 | 58 | final float density = getResources().getDisplayMetrics().density; 59 | 60 | TypedValue outValue = new TypedValue(); 61 | context.getTheme().resolveAttribute(R.attr.colorForeground, outValue, true); 62 | final int themeForegroundColor = outValue.data; 63 | 64 | mDefaultBottomBorderColor = setColorAlpha(themeForegroundColor, 65 | DEFAULT_BOTTOM_BORDER_COLOR_ALPHA); 66 | 67 | mDefaultTabColorizer = new SimpleTabColorizer(); 68 | mDefaultTabColorizer.setIndicatorColors(DEFAULT_SELECTED_INDICATOR_COLOR); 69 | 70 | mBottomBorderThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density); 71 | mBottomBorderPaint = new Paint(); 72 | mBottomBorderPaint.setColor(mDefaultBottomBorderColor); 73 | 74 | mSelectedIndicatorThickness = (int) (SELECTED_INDICATOR_THICKNESS_DIPS * density); 75 | mSelectedIndicatorPaint = new Paint(); 76 | } 77 | 78 | void setCustomTabColorizer(SlidingTabLayout.TabColorizer customTabColorizer) { 79 | mCustomTabColorizer = customTabColorizer; 80 | invalidate(); 81 | } 82 | 83 | void setSelectedIndicatorColors(int... colors) { 84 | // Make sure that the custom colorizer is removed 85 | mCustomTabColorizer = null; 86 | mDefaultTabColorizer.setIndicatorColors(colors); 87 | invalidate(); 88 | } 89 | 90 | void onViewPagerPageChanged(int position, float positionOffset) { 91 | mSelectedPosition = position; 92 | mSelectionOffset = positionOffset; 93 | invalidate(); 94 | } 95 | 96 | @Override 97 | protected void onDraw(Canvas canvas) { 98 | final int height = getHeight(); 99 | final int childCount = getChildCount(); 100 | final SlidingTabLayout.TabColorizer tabColorizer = mCustomTabColorizer != null 101 | ? mCustomTabColorizer 102 | : mDefaultTabColorizer; 103 | 104 | // Thick colored underline below the current selection 105 | if (childCount > 0) { 106 | View selectedTitle = getChildAt(mSelectedPosition); 107 | int left = selectedTitle.getLeft(); 108 | int right = selectedTitle.getRight(); 109 | int color = tabColorizer.getIndicatorColor(mSelectedPosition); 110 | 111 | if (mSelectionOffset > 0f && mSelectedPosition < (getChildCount() - 1)) { 112 | int nextColor = tabColorizer.getIndicatorColor(mSelectedPosition + 1); 113 | if (color != nextColor) { 114 | color = blendColors(nextColor, color, mSelectionOffset); 115 | } 116 | 117 | // Draw the selection partway between the tabs 118 | View nextTitle = getChildAt(mSelectedPosition + 1); 119 | left = (int) (mSelectionOffset * nextTitle.getLeft() + 120 | (1.0f - mSelectionOffset) * left); 121 | right = (int) (mSelectionOffset * nextTitle.getRight() + 122 | (1.0f - mSelectionOffset) * right); 123 | } 124 | 125 | mSelectedIndicatorPaint.setColor(color); 126 | 127 | canvas.drawRect(left, height - mSelectedIndicatorThickness, right, 128 | height, mSelectedIndicatorPaint); 129 | } 130 | 131 | // Thin underline along the entire bottom edge 132 | canvas.drawRect(0, height - mBottomBorderThickness, getWidth(), height, mBottomBorderPaint); 133 | } 134 | 135 | /** 136 | * Set the alpha value of the {@code color} to be the given {@code alpha} value. 137 | */ 138 | private static int setColorAlpha(int color, byte alpha) { 139 | return Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color)); 140 | } 141 | 142 | /** 143 | * Blend {@code color1} and {@code color2} using the given ratio. 144 | * 145 | * @param ratio of which to blend. 1.0 will return {@code color1}, 0.5 will give an even blend, 146 | * 0.0 will return {@code color2}. 147 | */ 148 | private static int blendColors(int color1, int color2, float ratio) { 149 | final float inverseRation = 1f - ratio; 150 | float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation); 151 | float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation); 152 | float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation); 153 | return Color.rgb((int) r, (int) g, (int) b); 154 | } 155 | 156 | private static class SimpleTabColorizer implements SlidingTabLayout.TabColorizer { 157 | private int[] mIndicatorColors; 158 | 159 | @Override 160 | public final int getIndicatorColor(int position) { 161 | return mIndicatorColors[position % mIndicatorColors.length]; 162 | } 163 | 164 | void setIndicatorColors(int... colors) { 165 | mIndicatorColors = colors; 166 | } 167 | } 168 | } -------------------------------------------------------------------------------- /app/src/main/res/anim/card_slide_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 9 | 11 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/anim/state_raise.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-hdpi/ic_add_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_assignment_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-hdpi/ic_assignment_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_assignment_returned_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-hdpi/ic_assignment_returned_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_assignment_turned_in_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-hdpi/ic_assignment_turned_in_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_done_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-hdpi/ic_done_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_event_note_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-hdpi/ic_event_note_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_home_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-hdpi/ic_home_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_launcher_webp.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-hdpi/ic_launcher_webp.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_local_phone_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-hdpi/ic_local_phone_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_local_shipping_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-hdpi/ic_local_shipping_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_local_shipping_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-hdpi/ic_local_shipping_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_mode_edit_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-hdpi/ic_mode_edit_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_more_horiz_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-hdpi/ic_more_horiz_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_settings_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-hdpi/ic_settings_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_visibility_off_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-hdpi/ic_visibility_off_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_visibility_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-hdpi/ic_visibility_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-mdpi/ic_add_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_assignment_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-mdpi/ic_assignment_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_assignment_returned_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-mdpi/ic_assignment_returned_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_assignment_turned_in_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-mdpi/ic_assignment_turned_in_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_done_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-mdpi/ic_done_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_event_note_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-mdpi/ic_event_note_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_home_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-mdpi/ic_home_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_launcher_webp.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-mdpi/ic_launcher_webp.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_local_phone_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-mdpi/ic_local_phone_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_local_shipping_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-mdpi/ic_local_shipping_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_local_shipping_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-mdpi/ic_local_shipping_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_mode_edit_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-mdpi/ic_mode_edit_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_more_horiz_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-mdpi/ic_more_horiz_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_settings_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-mdpi/ic_settings_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_visibility_off_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-mdpi/ic_visibility_off_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_visibility_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-mdpi/ic_visibility_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xhdpi/ic_add_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_assignment_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xhdpi/ic_assignment_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_assignment_returned_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xhdpi/ic_assignment_returned_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_assignment_turned_in_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xhdpi/ic_assignment_turned_in_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_done_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xhdpi/ic_done_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_event_note_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xhdpi/ic_event_note_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_home_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xhdpi/ic_home_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_launcher_webp.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xhdpi/ic_launcher_webp.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_local_phone_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xhdpi/ic_local_phone_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_local_shipping_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xhdpi/ic_local_shipping_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_local_shipping_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xhdpi/ic_local_shipping_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_mode_edit_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xhdpi/ic_mode_edit_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_more_horiz_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xhdpi/ic_more_horiz_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_settings_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xhdpi/ic_settings_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_visibility_off_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xhdpi/ic_visibility_off_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_visibility_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xhdpi/ic_visibility_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/background_title_webp.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xxhdpi/background_title_webp.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xxhdpi/ic_add_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_assignment_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xxhdpi/ic_assignment_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_assignment_returned_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xxhdpi/ic_assignment_returned_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_assignment_turned_in_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xxhdpi/ic_assignment_turned_in_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_done_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xxhdpi/ic_done_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_event_note_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xxhdpi/ic_event_note_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_home_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xxhdpi/ic_home_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_launcher_webp.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xxhdpi/ic_launcher_webp.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_local_phone_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xxhdpi/ic_local_phone_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_local_shipping_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xxhdpi/ic_local_shipping_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_local_shipping_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xxhdpi/ic_local_shipping_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_mode_edit_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xxhdpi/ic_mode_edit_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_more_horiz_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xxhdpi/ic_more_horiz_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_settings_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xxhdpi/ic_settings_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_visibility_off_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xxhdpi/ic_visibility_off_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_visibility_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable-xxhdpi/ic_visibility_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/alipay.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fython/ExpressHelper/a0cb853df60e3e1c9cc076ac457e2918c5f9177c/app/src/main/res/drawable/alipay.webp -------------------------------------------------------------------------------- /app/src/main/res/layout-land/activity_details.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 18 | 19 | 20 | 23 | 24 | 31 | 32 | 39 | 40 | 50 | 51 | 54 | 55 | 67 | 68 | 75 | 76 | 77 | 78 | 84 | 85 | 92 | 93 | 102 | 103 | 112 | 113 | 114 | 115 | 122 | 123 | 124 | 125 | 133 | 134 | 144 | 145 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /app/src/main/res/layout-v21/card_express_item.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 22 | 23 | 27 | 28 | 34 | 35 | 42 | 43 | 44 | 45 | 50 | 51 | 58 | 59 | 68 | 69 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_details.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 21 | 22 | 28 | 29 | 34 | 35 | 38 | 39 | 51 | 52 | 59 | 60 | 61 | 62 | 68 | 69 | 76 | 77 | 86 | 87 | 96 | 97 | 98 | 99 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 117 | 118 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 14 | 15 | 20 | 21 | 24 | 25 | 29 | 30 | 34 | 35 | 36 | 37 | 43 | 44 | 52 | 53 | 59 | 60 | 61 | 62 | 72 | 73 | 74 | 75 | 76 | 77 | 82 | 83 | 88 | 89 | 93 | 94 | 99 | 100 | 105 | 106 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_select_company.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 18 | 19 | 27 | 28 | 33 | 34 | 35 | 36 | 40 | 41 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | 23 | 24 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_test.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | 16 | 24 | 25 |