Ver código fonte

1.修改Android Apex Mobile Result,完成界面。

Pen Li 7 anos atrás
pai
commit
395c8b4e35
35 arquivos alterados com 2231 adições e 91 exclusões
  1. 3 2
      Apex Mobile/app/build.gradle
  2. 80 79
      Apex Mobile/app/src/main/AndroidManifest.xml
  3. 9 4
      Apex Mobile/app/src/main/java/com/usai/apex/SearchListActivity.java
  4. 133 0
      Apex Mobile/app/src/main/java/com/usai/apex/actionSheet/ActionSheet.java
  5. 200 0
      Apex Mobile/app/src/main/java/com/usai/apex/apexResult/ApexResultActivity.java
  6. 173 0
      Apex Mobile/app/src/main/java/com/usai/apex/apexResult/ApexResultAdapter.java
  7. 229 0
      Apex Mobile/app/src/main/java/com/usai/apex/apexResult/ApexResultPresenter.java
  8. 53 0
      Apex Mobile/app/src/main/java/com/usai/apex/apexResult/cell/ApexResultAdditionView.java
  9. 70 0
      Apex Mobile/app/src/main/java/com/usai/apex/apexResult/cell/ApexResultDocumentCell.java
  10. 165 0
      Apex Mobile/app/src/main/java/com/usai/apex/apexResult/cell/ApexResultShipCell.java
  11. 16 0
      Apex Mobile/app/src/main/java/com/usai/apex/apexResult/model/ApexResultBaseModel.java
  12. 8 0
      Apex Mobile/app/src/main/java/com/usai/apex/apexResult/model/ApexResultDocumentModel.java
  13. 61 0
      Apex Mobile/app/src/main/java/com/usai/apex/apexResult/model/ApexResultShipModel.java
  14. 318 0
      Apex Mobile/app/src/main/java/com/usai/apex/base/BaseObject.java
  15. 176 0
      Apex Mobile/app/src/main/java/com/usai/apex/button/RAButton.java
  16. 1 1
      Apex Mobile/app/src/main/java/com/usai/apex/mainframe/RecentFragment.java
  17. 1 2
      Apex Mobile/app/src/main/java/com/usai/apex/mainframe/TrackingImageView.java
  18. 92 0
      Apex Mobile/app/src/main/java/com/usai/apex/operationQueue/OperationQueue.java
  19. 27 0
      Apex Mobile/app/src/main/java/com/usai/util/Network.java
  20. 5 0
      Apex Mobile/app/src/main/res/anim/dialog_in.xml
  21. 5 0
      Apex Mobile/app/src/main/res/anim/dialog_out.xml
  22. 13 0
      Apex Mobile/app/src/main/res/drawable/actionsheet_round_corner_highlight_bg.xml
  23. 13 0
      Apex Mobile/app/src/main/res/drawable/actionsheet_round_corner_normal_bg.xml
  24. 13 0
      Apex Mobile/app/src/main/res/drawable/actionsheet_round_corner_selected_bg.xml
  25. 46 0
      Apex Mobile/app/src/main/res/drawable/apex_result_cell_bg.xml
  26. 9 0
      Apex Mobile/app/src/main/res/layout/action_sheet.xml
  27. 18 0
      Apex Mobile/app/src/main/res/layout/activity_apex_result.xml
  28. 29 0
      Apex Mobile/app/src/main/res/layout/apex_result_addition_view.xml
  29. 69 0
      Apex Mobile/app/src/main/res/layout/apex_result_document_cell.xml
  30. 149 0
      Apex Mobile/app/src/main/res/layout/apex_result_ship_cell.xml
  31. 12 0
      Apex Mobile/app/src/main/res/menu/apex_result_menu.xml
  32. 22 0
      Apex Mobile/app/src/main/res/values/actionsheet_styles.xml
  33. 10 0
      Apex Mobile/app/src/main/res/values/animation.xml
  34. 1 1
      Apex Mobile/build.gradle
  35. 2 2
      Apex Mobile/gradle/wrapper/gradle-wrapper.properties

+ 3 - 2
Apex Mobile/app/build.gradle

@@ -4,7 +4,7 @@ android {
     signingConfigs {
     }
     compileSdkVersion 27
-    buildToolsVersion '27.0.3'
+    buildToolsVersion '28.0.3'
     defaultConfig {
         applicationId "com.usai.apex"
         minSdkVersion 16
@@ -19,7 +19,8 @@ android {
         release {
 
             ndk {
-                abiFilters  "armeabi-v7a"  // 指定要ndk需要兼容的架构(这样其他依赖包里mips,x86,armeabi,arm-v8之类的so会被过滤掉)
+                abiFilters "armeabi-v7a"
+                // 指定要ndk需要兼容的架构(这样其他依赖包里mips,x86,armeabi,arm-v8之类的so会被过滤掉)
             }
 
             minifyEnabled true

+ 80 - 79
Apex Mobile/app/src/main/AndroidManifest.xml

@@ -1,42 +1,40 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.usai.apex"
-    android:versionCode="17"
-    android:versionName="A180723"> <!-- Copied from Google Maps Library/AndroidManifest.xml. -->
-    <uses-sdk
-        android:minSdkVersion="14"
-        android:targetSdkVersion="18" />
+          package="com.usai.apex"
+          android:versionCode="17"
+          android:versionName="A180723"> <!-- Copied from Google Maps Library/AndroidManifest.xml. -->
+    <uses-sdk android:targetSdkVersion="18"/>
 
     <!-- 写联系人权限 -->
-    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
-    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
-    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
+    <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
     <!--
          <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
     <uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" />
     -->
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
-    <uses-permission android:name="android.permission.INTERNET" />
-    <uses-permission android:name="android.permission.READ_CONTACTS" />
-    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+    <uses-permission android:name="android.permission.INTERNET"/>
+    <uses-permission android:name="android.permission.READ_CONTACTS"/>
+    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
     <!-- External storage for caching. -->
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     <!-- My Location -->
-    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
-    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
     <!-- Maps API needs OpenGL ES 2.0. -->
     <uses-feature
         android:glEsVersion="0x00020000"
-        android:required="true" />
+        android:required="true"/>
     <!-- End of copy. -->
 
 
     <!-- Baidu Map API -->
 
-    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
-    <!--<uses-permission android:name="android.permission.WRITE_SETTINGS" />-->
-    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+    <!-- <uses-permission android:name="android.permission.WRITE_SETTINGS" /> -->
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
 
     <!--
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
@@ -108,32 +106,32 @@
             android:grantUriPermissions="true">
             <meta-data
                 android:name="android.support.FILE_PROVIDER_PATHS"
-                android:resource="@xml/download_dir" />
+                android:resource="@xml/download_dir"/>
         </provider>
 
         <!-- release key -->
         <meta-data
             android:name="com.google.android.maps.v2.API_KEY"
-            android:value="AIzaSyDdbk58Lx6QzaXcB_hNpSHVp3l_CJeNpoo" />
+            android:value="AIzaSyDdbk58Lx6QzaXcB_hNpSHVp3l_CJeNpoo"/>
         <meta-data
             android:name="com.baidu.lbsapi.API_KEY"
-            android:value="nqBQoSDbxrslhuzW91uViQX7" />
+            android:value="nqBQoSDbxrslhuzW91uViQX7"/>
         <meta-data
             android:name="com.google.android.gms.version"
-            android:value="@integer/google_play_services_version" />
+            android:value="@integer/google_play_services_version"/>
 
         <!-- debug key -->
 
 
-         <!--<meta-data-->
-         <!--android:name="com.google.android.maps.v2.API_KEY"-->
-         <!--android:value="AIzaSyD6Snyg2SDUGtkC3sOAr979__IDCZnGGuU" />-->
-         <!--<meta-data-->
-         <!--android:name="com.baidu.lbsapi.API_KEY"-->
-         <!--android:value="tznWFxd3RvSoul1TGQp6GSzo" />-->
-         <!--<meta-data-->
-         <!--android:name="com.google.android.gms.version"-->
-         <!--android:value="@integer/google_play_services_version" />-->
+        <!-- <meta-data -->
+        <!-- android:name="com.google.android.maps.v2.API_KEY" -->
+        <!-- android:value="AIzaSyD6Snyg2SDUGtkC3sOAr979__IDCZnGGuU" /> -->
+        <!-- <meta-data -->
+        <!-- android:name="com.baidu.lbsapi.API_KEY" -->
+        <!-- android:value="tznWFxd3RvSoul1TGQp6GSzo" /> -->
+        <!-- <meta-data -->
+        <!-- android:name="com.google.android.gms.version" -->
+        <!-- android:value="@integer/google_play_services_version" /> -->
 
         <activity
             android:name=".DetailActivity"
@@ -159,7 +157,7 @@
             android:label="@string/title_activity_apex"
             android:logo="@drawable/apexlogo_2"
             android:screenOrientation="portrait"
-            android:windowSoftInputMode="adjustPan" />
+            android:windowSoftInputMode="adjustPan"/>
         <!--
              <activity
             android:name="com.usai.apex.LoginFragment"
@@ -179,9 +177,9 @@
             android:screenOrientation="portrait"
             android:theme="@style/ToolbarTheme">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-
-                <category android:name="android.intent.category.LAUNCHER" />
+                <action android:name="android.intent.action.MAIN"/>
+                <action android:name="android.intent.action.VIEW"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
         <activity
@@ -201,116 +199,114 @@
         <activity
             android:name=".SearchActivity"
             android:label="@string/title_activity_search"
-            android:screenOrientation="portrait" />
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".AnnouncementActivity"
             android:label="@string/title_activity_announcements"
-            android:screenOrientation="portrait" />
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".CustomizeFieldsActivity"
             android:label="@string/title_activity_customize_fields"
-            android:screenOrientation="portrait" />
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".ResultActivity"
             android:label="@string/title_activity_result"
-            android:screenOrientation="portrait" />
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".LocationDetailActivity"
             android:label="@string/title_activity_location_detail"
-            android:screenOrientation="portrait" />
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".InnerMapActivity"
             android:label="@string/title_activity_inner_map"
-            android:screenOrientation="portrait" />
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".HelpActivity"
             android:label="@string/title_activity_help"
             android:screenOrientation="portrait"
-            android:theme="@android:style/Theme.Holo.NoActionBar" />
+            android:theme="@android:style/Theme.Holo.NoActionBar"/>
         <activity
             android:name=".SearchListActivity"
             android:label="@string/title_activity_search_list"
             android:screenOrientation="portrait"
             android:theme="@style/SearchActionbarTheme"
-            android:windowSoftInputMode="adjustUnspecified|stateHidden" />
+            android:windowSoftInputMode="adjustUnspecified|stateHidden"/>
         <activity
             android:name=".RetrievePasswordActivity"
             android:label="@string/title_activity_retrieve_password"
-            android:screenOrientation="portrait" />
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".MessageActivity"
             android:label="@string/title_activity_message"
-            android:screenOrientation="portrait" />
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".SearchHistoryActivity"
             android:label="@string/title_activity_search_history"
-            android:screenOrientation="portrait" />
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".ChangePasswordActivity"
             android:label="Change Password"
             android:screenOrientation="portrait"
-            android:windowSoftInputMode="adjustResize|stateVisible" />
+            android:windowSoftInputMode="adjustResize|stateVisible"/>
         <activity
             android:name=".AboutActivity"
             android:label="@string/title_activity_about"
-            android:screenOrientation="portrait" />
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".WebActivity"
             android:label="@string/title_activity_web"
-            android:screenOrientation="portrait" />
+            android:screenOrientation="portrait"/>
 
         <receiver
             android:name=".BootBroadcastReceiver"
             android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
             <intent-filter>
-
-                <action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
-                <action android:name="android.intent.action.BOOT_COMPLETED" />
-                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
+                <action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
+                <action android:name="android.intent.action.BOOT_COMPLETED"/>
+                <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
             </intent-filter>
         </receiver>
         <receiver android:name=".Alarmreceiver">
             <intent-filter>
-                <action android:name="com.usai.apex.push" />
-                <action android:name="com.usai.apex.push.cancel" />
+                <action android:name="com.usai.apex.push"/>
+                <action android:name="com.usai.apex.push.cancel"/>
             </intent-filter>
         </receiver>
 
         <activity
             android:name=".MessageDetailActivity"
             android:label="@string/title_activity_message_detail"
-            android:screenOrientation="portrait" />
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".InnerToolsActivity"
             android:label="@string/title_activity_inner_tools"
-            android:screenOrientation="portrait" />
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".DocumentsActivity"
             android:label="@string/title_activity_documents"
-            android:screenOrientation="portrait" />
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".LocalDocumentActivity"
             android:label="@string/title_activity_localdocuments"
-            android:screenOrientation="portrait" />
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".ApexHistoryActivity"
             android:label="@string/title_activity_apexhistory"
-            android:screenOrientation="portrait" />
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".SettingsActivity"
             android:label="@string/title_activity_settings"
-            android:screenOrientation="portrait" />
+            android:screenOrientation="portrait"/>
 
         <service
             android:name=".ApexBackgroundService"
-            android:label="Apex Mobile Background Service" />
-
+            android:label="Apex Mobile Background Service"/>
         <service
             android:name="com.baidu.location.f"
             android:enabled="true"
-            android:process=":remote" >
+            android:process=":remote">
             <intent-filter>
-                <action android:name="com.baidu.location.service_v2.2" >
+                <action android:name="com.baidu.location.service_v2.2">
                 </action>
             </intent-filter>
         </service>
@@ -318,8 +314,8 @@
         <activity
             android:name=".saved.CheckSavedActivity"
             android:screenOrientation="portrait"
-            android:theme="@style/FixedActionbarTheme" />
-        >
+            android:theme="@style/FixedActionbarTheme"/>
+
         <activity
             android:name=".TestAppComActivity"
             android:screenOrientation="portrait"
@@ -335,20 +331,25 @@
         <activity
             android:name=".Result.AMResultActivity"
             android:screenOrientation="portrait"
-            android:theme="@style/ResultActionbarTheme" />
+            android:theme="@style/ResultActionbarTheme"/>
         <activity
             android:name=".Result.SearchResultActivity"
-            android:screenOrientation="portrait" />
-        <activity android:name=".ContainerSearchActivity" />
+            android:screenOrientation="portrait"/>
+        <activity android:name=".ContainerSearchActivity"/>
         <activity
             android:name=".pdf.PDFPreviewActivity"
             android:screenOrientation="portrait"
-            android:theme="@style/ResultActionbarTheme" />
-        <activity android:name=".LicenseActivity" />
-        <activity android:name=".TestActivity"></activity>
-        <activity android:name=".mainframe.NewDetailActivity"
-            android:theme="@style/DetailActionbarTheme"
-            android:screenOrientation="portrait"></activity>
+            android:theme="@style/ResultActionbarTheme"/>
+        <activity android:name=".LicenseActivity"/>
+        <activity android:name=".TestActivity"/>
+        <activity
+            android:name=".mainframe.NewDetailActivity"
+            android:screenOrientation="portrait"
+            android:theme="@style/DetailActionbarTheme"/>
+        <activity android:name=".apexResult.ApexResultActivity"
+                  android:theme="@style/ResultActionbarTheme">
+        </activity>
+
     </application>
 
 </manifest>

+ 9 - 4
Apex Mobile/app/src/main/java/com/usai/apex/SearchListActivity.java

@@ -37,6 +37,7 @@ import android.widget.Spinner;
 import android.widget.TextView;
 
 import com.usai.apex.Result.AMResultActivity;
+import com.usai.apex.apexResult.ApexResultActivity;
 import com.usai.util.Network;
 import com.usai.util.dbUtil;
 
@@ -223,7 +224,7 @@ public class SearchListActivity extends AppCompatActivity implements OnClickList
 		// hashMap.clear();
 		ll_list.removeAllViews();
 
-		if (!mShowTable) {
+		if (!mShowTable && hashMap != null) {
 			hashMap.clear();
 			return;
 		}
@@ -612,9 +613,13 @@ public class SearchListActivity extends AppCompatActivity implements OnClickList
 
 //				startActivity(intent);
 
-				Intent intent = new Intent(this, AMResultActivity.class);
-				intent.putExtra("query_params",parms);
-				startActivity(intent);
+				// after 2019.1.8
+				ApexResultActivity.startResultActivity(this, parms);
+
+				// before 2019.1.8
+//				Intent intent = new Intent(this, AMResultActivity.class);
+//				intent.putExtra("query_params",parms);
+//				startActivity(intent);
 				break;
 			}
 			case R.id.btncancel:

+ 133 - 0
Apex Mobile/app/src/main/java/com/usai/apex/actionSheet/ActionSheet.java

@@ -0,0 +1,133 @@
+package com.usai.apex.actionSheet;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.graphics.Color;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.text.TextPaint;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+
+import com.usai.apex.R;
+import com.usai.apex.button.RAButton;
+
+import java.util.HashMap;
+
+public class ActionSheet extends Dialog implements View.OnClickListener {
+
+    private Context mCtx;
+    private LinearLayout mRootView;
+    private HashMap<Button,View.OnClickListener> buttonListenerMap = new HashMap<>();
+
+    public ActionSheet(@NonNull Context context) {
+        this(context,R.style.actionSheet);
+
+    }
+
+    public ActionSheet(@NonNull Context context, int themeResId) {
+        super(context, themeResId);
+
+        mCtx = context;
+        init();
+    }
+
+    protected ActionSheet(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) {
+        super(context, cancelable, cancelListener);
+
+        mCtx = context;
+        init();
+    }
+
+    private void init() {
+        mRootView = (LinearLayout) LayoutInflater.from(mCtx).inflate(R.layout.action_sheet, null);
+        setContentView(mRootView);
+    }
+
+    public void addAction(String title, ActionType actionType, View.OnClickListener clickListener) {
+
+        RAButton button = new RAButton(mCtx);
+        button.setText(title);
+        button.setTextColor(Color.parseColor("#2577ff"));
+        button.setTextSize(TypedValue.COMPLEX_UNIT_SP,20);
+        button.setAllCaps(false);
+        button.setBackgroundResource(R.drawable.actionsheet_round_corner_normal_bg);
+        button.setOnClickListener(this);
+        if (clickListener != null) {
+            buttonListenerMap.put(button,clickListener);
+        }
+
+        button.setTitleColorForState(RAButton.RAButtonState.RAButtonStateHighlight,Color.RED);
+        button.setBackgroundDrawableForState(RAButton.RAButtonState.RAButtonStateNormal,mCtx.getResources().getDrawable(R.drawable.actionsheet_round_corner_normal_bg));
+
+        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,dp2px(mCtx,50));
+
+        int marginH = dp2px(mCtx,10);
+        int marginV = dp2px(mCtx,5);
+        switch (actionType) {
+            case ACtionTypeCancel: {
+                layoutParams.setMargins(marginH,marginV,marginH,marginV);
+
+                TextPaint tp = button.getPaint();
+                tp.setFakeBoldText(true);
+            }
+            break;
+            case ActionTypeDefault: {
+                layoutParams.setMargins(marginH,0,marginH,marginV);
+            }
+            break;
+        }
+
+        mRootView.addView(button,layoutParams);
+    }
+
+    private static int dp2px(Context context, float dpValue) {
+        float scale = context.getResources().getDisplayMetrics().density;
+        return (int) (dpValue * scale + 0.5f);
+    }
+
+    @Override
+    public void show() {
+
+        Window dialogWindow = getWindow();
+        if (dialogWindow != null) {
+
+            dialogWindow.setGravity(Gravity.BOTTOM);
+            WindowManager.LayoutParams layoutParams = dialogWindow.getAttributes(); // 获取对话框当前的参数值
+            layoutParams.x = 0; // 新位置X坐标
+            layoutParams.y = 0; // 新位置Y坐标
+            layoutParams.width = (int) mCtx.getResources().getDisplayMetrics().widthPixels; // 宽度
+            mRootView.measure(0, 0);
+            layoutParams.height = mRootView.getMeasuredHeight();
+
+            layoutParams.alpha = 9f; // 透明度
+            dialogWindow.setAttributes(layoutParams);
+        }
+
+        super.show();
+    }
+
+    @Override
+    public void onClick(View v) {
+
+        dismiss();
+
+        View.OnClickListener listener = buttonListenerMap.get(v);
+        if (listener != null) {
+            listener.onClick(v);
+        }
+    }
+
+    public enum ActionType {
+        ActionTypeDefault,
+        ACtionTypeCancel
+    }
+}

+ 200 - 0
Apex Mobile/app/src/main/java/com/usai/apex/apexResult/ApexResultActivity.java

@@ -0,0 +1,200 @@
+package com.usai.apex.apexResult;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.support.v4.view.MenuItemCompat;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ListView;
+
+import com.usai.apex.R;
+import com.usai.apex.actionSheet.ActionSheet;
+import com.usai.util.RAUtil;
+
+public class ApexResultActivity extends AppCompatActivity implements ApexResultPresenter.ApexResultProtocol {
+
+    // region Build
+
+    private static final String ParametersKey = "Apex_Result_Parameters_Key";
+
+    public static void startResultActivity(Activity activity, Bundle params) {
+
+        if (activity != null) {
+
+            Intent intent = new Intent(activity, ApexResultActivity.class);
+            if (params != null) {
+                intent.putExtra(ParametersKey, params);
+            }
+            activity.startActivity(intent);
+        }
+
+    }
+
+    // endregion
+
+    // region Property
+
+    private Context mCtx = this;
+    private ListView mListView;
+    private ApexResultPresenter mPresenter;
+    private ApexResultAdapter mAdapter;
+    private Bundle mParams;
+
+    // endregion
+
+    // region Override
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_apex_result);
+
+        //
+        if (savedInstanceState != null) {
+            mParams = savedInstanceState.getBundle(ParametersKey);
+        } else {
+            mParams = getIntent().getBundleExtra(ParametersKey);
+        }
+        if (mParams == null) {
+            mParams = new Bundle();
+        }
+
+        setupActionBar();
+        setup();
+
+        if (savedInstanceState != null) {
+            mPresenter.onRestoreInstanceState(savedInstanceState);
+        } else {
+            mPresenter.loadData();
+        }
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+
+        if (item.getItemId() == android.R.id.home) {
+            finish();
+        } else if (item.getItemId() == R.id.apex_result_menu) {
+            menuItemClick();
+        }
+
+        return super.onOptionsItemSelected(item);
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        new MenuInflater(mCtx).inflate(R.menu.apex_result_menu, menu);
+        return true;
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+
+        outState.putBundle(ParametersKey, mParams);
+        mPresenter.onSaveInstanceState(outState);
+    }
+
+    // endregion
+
+    // region Setting
+
+    private void setup() {
+
+        mListView = findViewById(R.id.apex_result_list_view);
+        mPresenter = new ApexResultPresenter(this, mParams);
+        mAdapter = new ApexResultAdapter(mCtx, mPresenter);
+        mListView.setAdapter(mAdapter);
+    }
+
+    private void setupActionBar() {
+
+        android.support.v7.app.ActionBar actionBar = getSupportActionBar();
+        if(actionBar != null){
+            actionBar.setHomeButtonEnabled(true);
+            actionBar.setDisplayHomeAsUpEnabled(true);
+        }
+    }
+
+    // endregion
+
+    // region Presenter Delegate
+    @Override
+    public void onStartLoading() {
+
+    }
+
+    @Override
+    public void onStopLoading() {
+
+    }
+
+    @Override
+    public void onSuccess(String title) {
+
+        setTitle(title);
+        mAdapter.notifyDataSetChanged();
+    }
+
+    @Override
+    public void onFailed(String errMsg) {
+
+    }
+
+    @Override
+    public void onNoMoreData() {
+
+    }
+
+    @Override
+    public void onDownloadFile(String path) {
+
+    }
+    // endregion
+
+    // region Menu Action
+
+    private void menuItemClick() {
+
+        ActionSheet actionSheet = new ActionSheet(mCtx);
+
+        actionSheet.addAction("Setting", ActionSheet.ActionType.ActionTypeDefault, new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                showFieldsSetting();
+            }
+        });
+
+        actionSheet.addAction("Save", ActionSheet.ActionType.ActionTypeDefault, new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                saveSearchParameters();
+            }
+        });
+
+        actionSheet.addAction("Cancel", ActionSheet.ActionType.ACtionTypeCancel, new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+
+            }
+        });
+
+        actionSheet.show();
+
+    }
+
+    private void saveSearchParameters() {
+
+    }
+
+    private void showFieldsSetting() {
+
+    }
+
+    // endregion
+}

+ 173 - 0
Apex Mobile/app/src/main/java/com/usai/apex/apexResult/ApexResultAdapter.java

@@ -0,0 +1,173 @@
+package com.usai.apex.apexResult;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+import com.usai.apex.apexResult.cell.ApexResultDocumentCell;
+import com.usai.apex.apexResult.cell.ApexResultShipCell;
+import com.usai.apex.apexResult.model.ApexResultBaseModel;
+import com.usai.apex.apexResult.model.ApexResultDocumentModel;
+import com.usai.apex.apexResult.model.ApexResultShipModel;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+
+public class ApexResultAdapter extends BaseAdapter {
+
+    // region DataSource
+    public static interface ApexResultAdapterDataSource {
+
+        int numberOfResultItem();
+        ApexResultBaseModel resultModelForIndex(int index);
+    }
+    // endregion
+
+    // region Initial
+    private WeakReference<Context> mWeakContext;
+    private WeakReference<ApexResultAdapterDataSource> mWeakDataSource;
+
+    public ApexResultAdapter(Context context, ApexResultAdapterDataSource dataSource) {
+        if (context == null) {
+            mWeakContext = null;
+        } else {
+            mWeakContext = new WeakReference<>(context);
+        }
+
+        if (dataSource == null) {
+            mWeakDataSource = null;
+        } else {
+            mWeakDataSource = new WeakReference<>(dataSource);
+        }
+    }
+    // endregion
+
+    // region Getter
+
+    private Context getContext() {
+        if (mWeakContext == null) {
+            return null;
+        }
+        return mWeakContext.get();
+    }
+
+    private ApexResultAdapterDataSource getDataSource() {
+        if (mWeakDataSource == null) {
+            return null;
+        }
+        return mWeakDataSource.get();
+    }
+
+    // endregion
+
+    // region Override
+
+    @Override
+    public int getCount() {
+        ApexResultAdapterDataSource dataSource = getDataSource();
+        if (dataSource != null) {
+            return dataSource.numberOfResultItem();
+        }
+        return 0;
+    }
+
+    @Override
+    public Object getItem(int position) {
+        ApexResultAdapterDataSource dataSource = getDataSource();
+        if (dataSource != null) {
+            return dataSource.resultModelForIndex(position);
+        }
+        return null;
+    }
+
+    @Override
+    public boolean hasStableIds() {
+        return true;
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return position;
+    }
+
+    @Override
+    public int getViewTypeCount() {
+        return 2;
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        ApexResultBaseModel model = (ApexResultBaseModel)getItem(position);
+        return model.type;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+
+        Context context = getContext();
+        if (context != null) {
+
+            ApexResultBaseModel model = (ApexResultBaseModel)getItem(position);
+            if (model.type == ApexResultBaseModel.ApexResultType.APEX_RESULT_TYPE_SHIP.ordinal()) {
+
+                ApexResultShipModel shipModel = (ApexResultShipModel)model;
+                ApexResultShipCell cell = dequeueShipCell(context, convertView);
+                cell.prepareReuse();
+                cell.setTitle(shipModel.title).setDetail(shipModel.detail).setIcon(shipModel.icon).setPort(shipModel.port).setTime(shipModel.date).setDescription(shipModel.desc);
+                ArrayList<ApexResultShipModel.ApexResultAddition> additions = shipModel.getAddition();
+                if (additions != null && additions.size() > 0) {
+                    for (ApexResultShipModel.ApexResultAddition addition : additions) {
+                        cell.addAddition(addition.name, addition.value);
+                    }
+                }
+                return cell;
+
+            } else if (model.type == ApexResultBaseModel.ApexResultType.APEX_RESULT_TYPE_DOCUMENT.ordinal()) {
+
+                ApexResultDocumentModel documentModel = (ApexResultDocumentModel)model;
+                ApexResultDocumentCell cell = dequeueDocumentCell(context, convertView);
+                cell.prepareReuse();
+                cell.setFileName(documentModel.fileName).setFileType(documentModel.fileType).setFileDescription(documentModel.fileDesc);
+
+                return cell;
+            }
+
+            return new View(context);
+        }
+        return null;
+    }
+
+    // endregion
+
+    // region Configure Cell
+
+    private ApexResultShipCell dequeueShipCell(Context context, View convertView) {
+
+        ApexResultShipCell cell = null;
+
+        if (convertView == null) {
+            cell = ApexResultShipCell.makeShipCell(context);
+        } else {
+            cell = (ApexResultShipCell)convertView;
+        }
+
+        return cell;
+    }
+
+    private ApexResultDocumentCell dequeueDocumentCell(Context context, View convertView) {
+
+        ApexResultDocumentCell cell = null;
+
+        if (convertView == null) {
+            cell = ApexResultDocumentCell.makeDocumentCell(context);
+        } else {
+            cell = (ApexResultDocumentCell)convertView;
+        }
+
+        return cell;
+    }
+
+    // endregion
+
+}

+ 229 - 0
Apex Mobile/app/src/main/java/com/usai/apex/apexResult/ApexResultPresenter.java

@@ -0,0 +1,229 @@
+package com.usai.apex.apexResult;
+
+import android.os.Bundle;
+
+import com.usai.apex.apexResult.model.ApexResultBaseModel;
+import com.usai.apex.apexResult.model.ApexResultDocumentModel;
+import com.usai.apex.apexResult.model.ApexResultShipModel;
+import com.usai.apex.operationQueue.OperationQueue;
+import com.usai.util.Network;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+
+public class ApexResultPresenter implements ApexResultAdapter.ApexResultAdapterDataSource {
+
+    // region Protocol
+    public static interface ApexResultProtocol {
+
+        void onStartLoading();
+        void onStopLoading();
+        void onSuccess(String title);
+        void onFailed(String errMsg);
+        void onNoMoreData();
+        void onDownloadFile(String path);
+
+    }
+    // endregion
+
+    // region Enum
+
+    private enum ApexResultFetchDataType {
+        APEX_RESULT_FETCH_DATA_TYPE_INITIAL,
+        APEX_RESULT_FETCH_DATA_TYPE_REFRESH,
+        APEX_RESULT_FETCH_DATA_TYPE_LOAD_MORE
+    }
+
+    // endregion
+
+    // region Initial
+
+    private WeakReference<ApexResultProtocol> mWeakDelegate;
+    private Bundle mParams;
+    private int offset = 0;
+    private static final int detal = 20;
+    private ArrayList<ApexResultBaseModel> mDataArray;
+    private JSONArray rowActions;
+    private JSONArray actions;
+
+    public ApexResultPresenter(ApexResultProtocol delegate, Bundle params) {
+        if (delegate == null) {
+            mWeakDelegate = null;
+        } else {
+            mWeakDelegate = new WeakReference<>(delegate);
+        }
+        if (params == null) {
+            mParams = new Bundle();
+        } else {
+            mParams = params;
+        }
+    }
+    // endregion
+
+    // region Save Instance
+
+    public void onSaveInstanceState(Bundle outState) {
+        if (outState != null) {
+
+        }
+    }
+
+    public void onRestoreInstanceState(Bundle savedInstanceState) {
+        if (savedInstanceState != null) {
+
+        }
+    }
+
+    // endregion
+
+    // region Getter
+
+    private ApexResultProtocol getDelegate() {
+        if (mWeakDelegate == null) {
+            return null;
+        }
+        return mWeakDelegate.get();
+    }
+
+    public int dataCount() {
+        if (mDataArray == null) {
+            return 0;
+        }
+        return mDataArray.size();
+    }
+
+    public ApexResultBaseModel modelAtIndex(int index) {
+        if (index >= dataCount()) {
+            return null;
+        }
+        return mDataArray.get(index);
+    }
+
+    // endregion
+
+    // region DataSource
+
+    @Override
+    public int numberOfResultItem() {
+        return dataCount();
+    }
+
+    @Override
+    public ApexResultBaseModel resultModelForIndex(int index) {
+        return modelAtIndex(index);
+    }
+
+    // endregion
+
+    // region Data
+
+    private void loadData(final ApexResultFetchDataType option) {
+
+        if (getDelegate() != null) {
+            getDelegate().onStartLoading();
+        }
+
+        OperationQueue.sharedQueue().addOperationTask(new OperationQueue.OperationBackgroundCallBack() {
+            @Override
+            public Object operationDoInBackground() {
+
+                Bundle params = (Bundle) mParams.clone();
+                params.putInt("offset", offset);
+                params.putInt("limit", detal);
+                JSONObject json = Network.fetchResult(params);
+
+                return json;
+            }
+        }, new OperationQueue.OperationCompletionCallBack() {
+            @Override
+            public void operationCompletion(Object object) {
+
+                JSONObject json = (JSONObject)object;
+                int result = Network.RESULT_FALSE;
+                if (json != null) {
+                    result = json.optInt("result", Network.RESULT_FALSE);
+                }
+
+                if (getDelegate() != null) {
+                    getDelegate().onStopLoading();
+                }
+
+                if (result == Network.RESULT_TRUE) {
+
+                    ArrayList<ApexResultBaseModel> models = new ArrayList<>();
+                    if (option == ApexResultFetchDataType.APEX_RESULT_FETCH_DATA_TYPE_LOAD_MORE && mDataArray != null && mDataArray.size() > 0) {
+                        models.addAll(mDataArray);
+                    }
+
+                    int loadCount = 0;
+                    JSONArray items = json.optJSONArray("items");
+                    if (items != null) {
+                        loadCount = items.length();
+
+                        for (int i = 0; i < loadCount; i++) {
+                            JSONObject item = items.optJSONObject(i);
+                            if (item != null) {
+
+                                int type = item.optInt("type", -1);
+                                if (type == ApexResultBaseModel.ApexResultType.APEX_RESULT_TYPE_SHIP.ordinal()) {
+
+                                    ApexResultShipModel model = new ApexResultShipModel();
+                                    model.setValuesForKeysWithJSON(item);
+                                    models.add(model);
+                                } else if (type == ApexResultBaseModel.ApexResultType.APEX_RESULT_TYPE_DOCUMENT.ordinal()) {
+
+                                    ApexResultDocumentModel model = new ApexResultDocumentModel();
+                                    model.setValuesForKeysWithJSON(item);
+                                    models.add(model);
+                                }
+                            }
+                        }
+                    }
+
+                    offset = models.size();
+                    String title = json.optString("title");
+                    rowActions = json.optJSONArray("row_actions");
+                    actions = json.optJSONArray("actions");
+
+                    mDataArray = models;
+                    if (getDelegate() != null) {
+                        getDelegate().onSuccess(title);
+                        if (loadCount < detal) {
+                            getDelegate().onNoMoreData();
+                        }
+                    }
+
+                } else {
+
+                    String msg = "Sorry, something is wrong.";
+                    if (json != null) {
+                        json.optString("err_msg", "Sorry, something is wrong.");
+                    }
+
+                    if (getDelegate() != null) {
+                        getDelegate().onFailed(msg);
+                    }
+                }
+
+            }
+        },null);
+
+    }
+
+    public void loadData() {
+        loadData(ApexResultFetchDataType.APEX_RESULT_FETCH_DATA_TYPE_INITIAL);
+    }
+
+    public void refreshData() {
+        loadData(ApexResultFetchDataType.APEX_RESULT_FETCH_DATA_TYPE_REFRESH);
+    }
+
+    public void loadMoreData() {
+        loadData(ApexResultFetchDataType.APEX_RESULT_FETCH_DATA_TYPE_LOAD_MORE);
+    }
+
+    // endregion
+}

+ 53 - 0
Apex Mobile/app/src/main/java/com/usai/apex/apexResult/cell/ApexResultAdditionView.java

@@ -0,0 +1,53 @@
+package com.usai.apex.apexResult.cell;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.usai.apex.R;
+
+public class ApexResultAdditionView extends RelativeLayout {
+
+    public static ApexResultAdditionView makeAdditionView(Context context) {
+
+        ApexResultAdditionView additionView = (ApexResultAdditionView) LayoutInflater.from(context).inflate(R.layout.apex_result_addition_view, null);
+        additionView.init();
+        return additionView;
+    }
+
+    private TextView titleTv, valueTv;
+
+    public ApexResultAdditionView(Context context) {
+        super(context);
+    }
+
+    public ApexResultAdditionView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public ApexResultAdditionView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    private void init() {
+        titleTv = findViewById(R.id.apex_result_addition_title_tv);
+        valueTv = findViewById(R.id.apex_result_addition_value_tv);
+        prepareReuse();
+    }
+
+    private void prepareReuse() {
+        titleTv.setText("");
+        valueTv.setText("");
+    }
+
+    public void setTitle(String title) {
+        titleTv.setText(title);
+    }
+
+    public void setValue(String value) {
+        valueTv.setText(value);
+    }
+
+}

+ 70 - 0
Apex Mobile/app/src/main/java/com/usai/apex/apexResult/cell/ApexResultDocumentCell.java

@@ -0,0 +1,70 @@
+package com.usai.apex.apexResult.cell;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.usai.apex.R;
+
+
+public class ApexResultDocumentCell extends RelativeLayout {
+
+    public static ApexResultDocumentCell makeDocumentCell(Context context) {
+
+        ApexResultDocumentCell cell = (ApexResultDocumentCell) LayoutInflater.from(context).inflate(R.layout.apex_result_document_cell, null);
+        cell.init();
+
+        return cell;
+    }
+
+
+    private ImageView fileIconView;
+    private TextView fileNameTv, fileTypeTv, fileDescTv;
+
+    private void init() {
+
+        fileIconView = findViewById(R.id.apex_result_document_icon_view);
+        fileNameTv = findViewById(R.id.apex_result_document_file_name_tv);
+        fileTypeTv = findViewById(R.id.apex_result_document_file_type_tv);
+        fileDescTv = findViewById(R.id.apex_result_document_file_desc_tv);
+
+        prepareReuse();
+    }
+
+    public ApexResultDocumentCell(Context context) {
+        super(context);
+    }
+
+    public ApexResultDocumentCell(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public ApexResultDocumentCell(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public void prepareReuse() {
+        fileNameTv.setText("");
+        fileTypeTv.setText("");
+        fileDescTv.setText("");
+    }
+
+    public ApexResultDocumentCell setFileName(String name) {
+        fileNameTv.setText(name);
+        return this;
+    }
+
+    public ApexResultDocumentCell setFileType(String type) {
+        fileTypeTv.setText(type);
+        return this;
+    }
+
+    public ApexResultDocumentCell setFileDescription(String description) {
+        fileDescTv.setText(description);
+        return this;
+    }
+
+}

+ 165 - 0
Apex Mobile/app/src/main/java/com/usai/apex/apexResult/cell/ApexResultShipCell.java

@@ -0,0 +1,165 @@
+package com.usai.apex.apexResult.cell;
+
+import android.content.Context;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.usai.apex.ApexTrackingApplication;
+import com.usai.apex.R;
+import com.usai.apex.mainframe.TrackingImageView;
+
+import java.util.ArrayList;
+
+public class ApexResultShipCell extends LinearLayout {
+
+    // region initial
+    public static ApexResultShipCell makeShipCell(Context context) {
+        ApexResultShipCell cell = (ApexResultShipCell) LayoutInflater.from(context).inflate(R.layout.apex_result_ship_cell, null);
+        cell.init();
+
+        return cell;
+    }
+
+    private TextView titleTv, dateTv, descTv, detailTv, portTv;
+    private TrackingImageView statusIv;
+    private View stageView;
+    private LinearLayout additionLayout;
+
+    private ArrayList<ApexResultAdditionView> additionArray = new ArrayList<>();
+    private int additionCount = 0;
+
+    public ApexResultShipCell(Context context) {
+        super(context);
+    }
+
+    public ApexResultShipCell(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public ApexResultShipCell(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    private void init() {
+
+        titleTv = findViewById(R.id.tv_title);
+        dateTv = findViewById(R.id.tv_time);
+        descTv = findViewById(R.id.tv_description);
+        detailTv = findViewById(R.id.tv_detail);
+        portTv = findViewById(R.id.tv_port);
+        statusIv = findViewById(R.id.iv_status);
+        stageView = findViewById(R.id.v_transport_stage);
+        additionLayout = findViewById(R.id.apex_result_ship_addition_view);
+
+        prepareReuse();
+    }
+
+    public void prepareReuse() {
+
+        titleTv.setText("");
+        dateTv.setText("");
+        descTv.setText("");
+        detailTv.setText("");
+        portTv.setText("");
+        statusIv.setImageDrawable(null);
+        setTransportStage(0);
+        clearAdditionView();
+    }
+
+    public void setTransportStage(int stage) {
+        switch(stage)
+        {
+            case 0:
+                stageView.setBackground(ApexTrackingApplication.getInstance().getResources().getDrawable(R.drawable.list_corner_transport_stage_bg_0));
+                break;
+            case 1:
+                stageView.setBackground(ApexTrackingApplication.getInstance().getResources().getDrawable(R.drawable.list_corner_transport_stage_bg_1));
+                break;
+            case 2:
+                stageView.setBackground(ApexTrackingApplication.getInstance().getResources().getDrawable(R.drawable.list_corner_transport_stage_bg_2));
+                break;
+            case 3:
+                stageView.setBackground(ApexTrackingApplication.getInstance().getResources().getDrawable(R.drawable.list_corner_transport_stage_bg_3));
+                break;
+            default:
+                stageView.setBackground(ApexTrackingApplication.getInstance().getResources().getDrawable(R.drawable.list_corner_transport_stage_bg_0));
+                break;
+
+        }
+    }
+
+    // endregion
+
+    // region set
+
+    public ApexResultShipCell setTitle(String title) {
+        titleTv.setText(title);
+        return this;
+    }
+
+    public ApexResultShipCell setDetail(String detail) {
+        detailTv.setText(detail);
+        return this;
+    }
+
+    public ApexResultShipCell setIcon(String icon) {
+        if (icon != null) {
+            int resourceId = getContext().getResources().getIdentifier(icon, "drawable", getContext().getPackageName());
+            statusIv.setImageResource(resourceId);
+        } else {
+            statusIv.setImageDrawable(null);
+        }
+        return this;
+    }
+
+    public ApexResultShipCell setPort(String port) {
+        portTv.setText(port);
+        return this;
+    }
+
+    public ApexResultShipCell setTime(String time) {
+        dateTv.setText(time);
+        return this;
+    }
+
+    public ApexResultShipCell setDescription(String description) {
+        descTv.setText(description);
+        return this;
+    }
+
+    public void addAddition(String name, String value) {
+
+        ApexResultAdditionView additionView;
+        if (additionCount >= additionArray.size()) {
+
+            additionView = ApexResultAdditionView.makeAdditionView(getContext());
+            additionArray.add(additionView);
+
+        } else {
+            additionView = additionArray.get(additionCount);
+        }
+        additionCount++;
+
+        additionView.setTitle(name);
+        additionView.setValue(value);
+
+        LinearLayout.LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
+        additionLayout.addView(additionView, layoutParams);
+    }
+
+    // endregion
+
+    // region Private
+
+    private void clearAdditionView() {
+        additionLayout.removeAllViews();
+        additionCount = 0;
+    }
+
+    // endregion
+}

+ 16 - 0
Apex Mobile/app/src/main/java/com/usai/apex/apexResult/model/ApexResultBaseModel.java

@@ -0,0 +1,16 @@
+package com.usai.apex.apexResult.model;
+
+import com.usai.apex.base.BaseObject;
+
+import org.json.JSONArray;
+
+public class ApexResultBaseModel extends BaseObject {
+
+    public static enum ApexResultType {
+        APEX_RESULT_TYPE_SHIP,
+        APEX_RESULT_TYPE_DOCUMENT
+    }
+
+    public int type;
+    public JSONArray rowActionParameters;
+}

+ 8 - 0
Apex Mobile/app/src/main/java/com/usai/apex/apexResult/model/ApexResultDocumentModel.java

@@ -0,0 +1,8 @@
+package com.usai.apex.apexResult.model;
+
+public class ApexResultDocumentModel extends ApexResultBaseModel {
+
+    public String fileName;
+    public String fileType;
+    public String fileDesc;
+}

+ 61 - 0
Apex Mobile/app/src/main/java/com/usai/apex/apexResult/model/ApexResultShipModel.java

@@ -0,0 +1,61 @@
+package com.usai.apex.apexResult.model;
+
+import com.usai.apex.base.BaseObject;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+
+public class ApexResultShipModel extends ApexResultBaseModel {
+
+    public class ApexResultAddition extends BaseObject {
+        public String name;
+        public String value;
+    }
+
+    public String title;
+    public String icon;
+    public String desc;
+    public String detail;
+    public String date;
+    public String port;
+    public String transport_stage;
+
+    public Object addition; // 使用Object对象,便于baseObject赋值
+    private ArrayList<ApexResultAddition> additions;
+
+    public void setAddition(Object obj) {
+
+        if (obj != null && obj instanceof JSONArray) {
+
+            JSONArray addition = (JSONArray) obj;
+            if (addition != null && addition.length() > 0) {
+
+                this.additions = new ArrayList<>();
+                for (int i = 0; i < addition.length(); i++) {
+                    JSONObject additionItem = addition.optJSONObject(i);
+                    if (additionItem != null) {
+
+                        ApexResultAddition additionModel = new ApexResultAddition();
+                        additionModel.setValuesForKeysWithJSON(additionItem);
+                        this.additions.add(additionModel);
+                    }
+                }
+
+            } else {
+                this.additions = null;
+            }
+
+        } else {
+            this.additions = null;
+        }
+
+
+
+    }
+
+    public ArrayList<ApexResultAddition> getAddition() {
+        return additions;
+    }
+}

+ 318 - 0
Apex Mobile/app/src/main/java/com/usai/apex/base/BaseObject.java

@@ -0,0 +1,318 @@
+package com.usai.apex.base;
+
+import android.text.TextUtils;
+
+import org.json.JSONObject;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * 基础对象,方便使用json初始化对象,属性必须声明为public
+ * 如果json中元素为json对象,那么属性对应的应该为Object类型
+ * */
+public class BaseObject {
+
+    /**
+     * Utils
+     * */
+
+    private static String toUpperCaseFirstOne(String s){
+        if(Character.isUpperCase(s.charAt(0)))
+            return s;
+        else
+            return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
+    }
+
+    /**
+     * Setter
+     * */
+    private boolean invokeSetter(Class cls, Class type, String key, Object value) {
+
+        String setter = "set" + toUpperCaseFirstOne(key);
+        try {
+
+            Class<?> myClassType = Class.forName(cls.getName());
+
+            Method method = myClassType.getMethod(setter,type);
+            if (method != null) {
+
+                method.invoke(this,value);
+
+                return true;
+            }
+
+        } catch (Exception e) {
+//            e.printStackTrace();
+        }
+
+        return false;
+    }
+
+    private void setValue(Class cls, Field f, Class type, String key, Object value) {
+
+        if (!invokeSetter(cls, type, key, value)) {
+            try {
+                f.set(this,value);
+            } catch (IllegalAccessException e) {
+//                e.printStackTrace();
+            }
+        }
+    }
+
+    private void setValue(Class cls, Field f, String key, Object value) {
+
+        Class type = f.getType();
+
+        if (value == null) {
+
+            boolean isInt = (type == int.class || type == long.class);
+            boolean isFloat = (type == float.class || type == double.class);
+            boolean isBool = (type == Boolean.class || type == boolean.class);
+
+            if (isInt) {
+                value = 0;
+            } else if (isFloat) {
+                value = 0.0;
+            } else if (isBool) {
+                value = false;
+            }
+
+            setValue(cls, f, type, key, value);
+
+        } else {
+
+            if (type == value.getClass()) {
+
+                setValue(cls, f, type, key, value);
+
+            } else {
+
+                boolean isInt = ((type == int.class || type == long.class) && value.getClass() == Integer.class);
+                boolean isFloat = ((type == float.class || type == double.class) && (value.getClass() == Double.class || value.getClass() == Float.class));
+                boolean isBool = ((type == Boolean.class || type == boolean.class) && (value.getClass() == boolean.class || value.getClass() == Boolean.class));
+
+                if (isInt || isFloat || isBool) {
+                    setValue(cls, f, type, key, value);
+                } else {
+
+                    if (value.getClass() == String.class) {
+
+                        String string = (String)value;
+
+                        if (type == Integer.class || type == int.class || type == long.class) {
+
+                            value = Integer.valueOf(string);
+
+
+                        } else if (type == Double.class || type == double.class || type == float.class) {
+
+                            value = Double.valueOf(string);
+
+                        } else if (type == Boolean.class || type == boolean.class) {
+
+                            value = Boolean.valueOf(string);
+                        }
+
+                        setValue(cls, f, type, key, value);
+
+                    } else {
+
+                        if (type == Object.class) {
+                            setValue(cls, f, type, key, value);
+                        }
+
+                    }
+                }
+            }
+        }
+
+    }
+
+    public void setValueForKey(String key, Object value) {
+
+        if (key == null) {
+            return;
+        }
+
+        Class cls = getClass();
+//        out:while (cls != null && cls != Class.class) {
+//
+//            Field[] fields = cls.getFields();
+//            for (Field f : fields) {
+//
+//                String name = f.getName();
+//                if (name.equals(key)) {
+//
+//                    setValue(cls, f, key, value);
+//                    break out;
+//                }
+//            }
+//
+//            cls = cls.getSuperclass();
+//        }
+
+        try {
+            Field f = cls.getField(key);
+            setValue(cls, f, key, value);
+        } catch (NoSuchFieldException e) {
+//            e.printStackTrace();
+        }
+    }
+
+    public void setValueForKeyPath(String keyPath, Object value) {
+
+        if (keyPath != null) {
+            if (keyPath.contains(".")) {
+
+                Object receiver = this;
+                String[] nodes = keyPath.split("\\."); // split 实际上是正则表达式,所以特殊字符需要转译
+                for (int i = 0; i < nodes.length; i++) {
+                    String key = nodes[i];
+                    if (i == nodes.length - 1) {
+
+                        if (receiver != null) {
+
+                            if (receiver instanceof BaseObject) {
+                                ((BaseObject) receiver).setValueForKey(key,value);
+                            } else {
+
+                                try {
+
+                                    Class cls = receiver.getClass();
+                                    Field f = cls.getField(key);
+                                    setValue(cls, f, key, value);
+                                } catch (NoSuchFieldException e) {
+//                                    e.printStackTrace();
+                                }
+                            }
+                        }
+
+                    } else {
+
+                        receiver = getValueForKey(receiver, key);
+                        if (receiver == null) {
+                            break;
+                        }
+                    }
+                }
+
+            } else {
+                setValueForKey(keyPath,value);
+            }
+        }
+    }
+
+    public void setValuesForKeysWithJSON(JSONObject json) {
+
+        if (json == null || json.length() == 0) {
+            return;
+        }
+
+
+        try {
+            Class cls = getClass();
+            while (cls != null && cls != Class.class) {
+
+                Field[] fields = cls.getFields();
+                for (Field f : fields) {
+
+                    String key = f.getName();
+
+                    Object value = json.opt(key);
+
+//                    if (value == null) {
+//                        continue;
+//                    }
+
+                    setValue(cls, f, key, value);
+                }
+                cls = cls.getSuperclass();
+            }
+        } catch (Exception e) {
+//            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Getter
+     * */
+
+    private Object invokeGetter(Class cls, String key) {
+
+        String setter = "get" + toUpperCaseFirstOne(key);
+        try {
+
+            Class<?> myClassType = Class.forName(cls.getName());
+
+            Method method = myClassType.getMethod(setter,void.class);
+            if (method != null) {
+                return method.invoke(this);
+            }
+
+        } catch (Exception e) {
+//            e.printStackTrace();
+        }
+
+        return null;
+    }
+
+    private Object getValueForKey(Object receiver, String key) {
+
+        if (receiver == null || TextUtils.isEmpty(key)) {
+            return null;
+        }
+
+        try {
+
+            Class cls = receiver.getClass();
+
+            Object obj = invokeGetter(cls, key);
+
+            if (obj == null) {
+
+                Field field = cls.getField(key);
+                if (field != null) {
+                    obj = field.get(receiver);
+                    return obj;
+                } else {
+                    return null;
+                }
+            } else {
+                return obj;
+            }
+
+        } catch (NoSuchFieldException e) {
+//            e.printStackTrace();
+        } catch (IllegalAccessException e) {
+//            e.printStackTrace();
+        }
+        return null;
+
+    }
+
+    public Object getValueForKeyPath(String keyPath) {
+
+        if (keyPath != null) {
+
+            if (keyPath.contains(".")) {
+
+                Object receiver = this;
+                String[] nodes = keyPath.split("\\."); // split 实际上是正则表达式,所以特殊字符需要转译
+                for (int i = 0; i < nodes.length; i++) {
+                    String key = nodes[i];
+                    receiver = getValueForKey(receiver, key);
+                    if (receiver == null) {
+                        break;
+                    }
+                }
+                return receiver;
+
+            } else {
+                return getValueForKey(this,keyPath);
+            }
+
+        }
+        return null;
+    }
+}

+ 176 - 0
Apex Mobile/app/src/main/java/com/usai/apex/button/RAButton.java

@@ -0,0 +1,176 @@
+package com.usai.apex.button;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+
+import java.util.HashMap;
+
+public class RAButton extends android.support.v7.widget.AppCompatButton {
+
+    private HashMap<RAButtonState,Drawable> stateDrawableHashMap = new HashMap<>();
+    private HashMap<RAButtonState,String> stateTitleHashMap = new HashMap<>();
+    private HashMap<RAButtonState,Integer> stateTitleColorHashMap = new HashMap<>();
+
+    private RAButtonState state = RAButtonState.RAButtonStateNormal;
+    private boolean mSelected = false;
+
+    public RAButton(Context context) {
+        super(context);
+
+        init();
+    }
+
+    public RAButton(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        init();
+    }
+
+    public RAButton(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+
+        init();
+    }
+
+    private void init() {
+
+        setAllCaps(false);
+
+        String normalTitle = getText().toString();
+        Drawable normalDrawable = getBackground();
+        Integer normalTitleColor = getTextColors().getDefaultColor();
+
+        String title = stateTitleHashMap.get(RAButtonState.RAButtonStateNormal);
+        if (title == null && normalTitle != null) {
+            stateTitleHashMap.put(RAButtonState.RAButtonStateNormal,normalTitle);
+        }
+
+        Drawable background = stateDrawableHashMap.get(RAButtonState.RAButtonStateNormal);
+        if (background == null && normalDrawable != null) {
+            stateDrawableHashMap.put(RAButtonState.RAButtonStateNormal,normalDrawable);
+        }
+
+        stateTitleColorHashMap.put(RAButtonState.RAButtonStateNormal,normalTitleColor);
+
+    }
+
+    public void setBackgroundDrawableForState(RAButtonState state, Drawable drawable) {
+
+        if (state == null) {
+            return;
+        }
+
+        if (drawable != null) {
+            stateDrawableHashMap.put(state,drawable);
+        } else {
+            stateDrawableHashMap.remove(state);
+        }
+    }
+
+    public void setTitleForState(RAButtonState state, String title) {
+
+        if (state == null) {
+            return;
+        }
+        if (title == null) {
+            stateTitleHashMap.remove(state);
+        } else {
+            stateTitleHashMap.put(state,title);
+        }
+    }
+
+    public void setTitleColorForState(RAButtonState state, int color) {
+
+        if (state == null) {
+            return;
+        }
+
+        stateTitleColorHashMap.put(state,Integer.valueOf(color));
+    }
+
+    public void setText(String text) {
+        super.setText(text);
+
+        setTitleForState(state,text);
+    }
+
+    public void setTextColor(int color) {
+        super.setTextColor(color);
+
+        setTitleColorForState(state,color);
+    }
+
+    public void setBackgroundDrawable(Drawable drawable) {
+        super.setBackgroundDrawable(drawable);
+
+        setBackgroundDrawableForState(state,drawable);
+    }
+
+    private void refreshUI() {
+
+        Drawable drawable = stateDrawableHashMap.get(state);
+        if (drawable == null) {
+            drawable = stateDrawableHashMap.get(RAButtonState.RAButtonStateNormal);
+        }
+        super.setBackgroundDrawable(drawable);
+
+        String title = stateTitleHashMap.get(state);
+        if (title == null) {
+            title = stateTitleHashMap.get(RAButtonState.RAButtonStateNormal);
+        }
+        super.setText(title);
+
+        Integer colorInteger = stateTitleColorHashMap.get(state);
+        if (colorInteger != null) {
+            super.setTextColor(colorInteger.intValue());
+        }
+    }
+
+    public void setSelection(boolean selection) {
+        mSelected = selection;
+
+        if (selection) {
+            state = RAButtonState.RAButtonStateSelected;
+        } else {
+            state = RAButtonState.RAButtonStateNormal;
+        }
+
+        refreshUI();
+    }
+
+    public boolean getSelection() {
+        return mSelected;
+    }
+
+    /**
+     * 按钮触摸状态改变回调
+     * */
+    @Override
+    protected void drawableStateChanged() {
+        super.drawableStateChanged();
+
+        boolean pressed = isPressed();
+
+        if (pressed) {
+            state = RAButtonState.RAButtonStateHighlight;
+        } else {
+
+            if (mSelected) {
+                state = RAButtonState.RAButtonStateSelected;
+            } else {
+                state = RAButtonState.RAButtonStateNormal;
+            }
+
+        }
+
+        refreshUI();
+
+    }
+
+    public enum RAButtonState {
+        RAButtonStateNormal,
+        RAButtonStateHighlight,
+        RAButtonStateSelected
+    }
+}

+ 1 - 1
Apex Mobile/app/src/main/java/com/usai/apex/mainframe/RecentFragment.java

@@ -270,7 +270,7 @@ public class RecentFragment extends TrackingListFragment {
                     showRefreshButton(false);
                 setSelectedPosition(0);
 
-                checkDatabase();
+//                checkDatabase();
 
             } else {
                 String msg = jsobj.getString("err_msg");

+ 1 - 2
Apex Mobile/app/src/main/java/com/usai/apex/mainframe/TrackingImageView.java

@@ -7,10 +7,9 @@ import android.graphics.Paint;
 import android.graphics.Path;
 import android.support.annotation.Nullable;
 import android.util.AttributeSet;
-import android.widget.ImageView;
 
 
-public class TrackingImageView extends ImageView {
+public class TrackingImageView extends android.support.v7.widget.AppCompatImageView {
 
     public TrackingImageView(Context context) {
         super(context);

+ 92 - 0
Apex Mobile/app/src/main/java/com/usai/apex/operationQueue/OperationQueue.java

@@ -0,0 +1,92 @@
+package com.usai.apex.operationQueue;
+
+import android.os.AsyncTask;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+public class OperationQueue {
+
+    /**
+     * 根据CPU核心数控制线程数
+     * */
+    private static final int count = Runtime.getRuntime().availableProcessors() * 3;
+
+    private static ExecutorService limitedTaskExecutor = null;
+
+    private static volatile OperationQueue instance;
+
+    public static OperationQueue sharedQueue() {
+        if (instance == null) {
+            synchronized (OperationQueue.class) {
+                if (instance == null) {
+                    instance = new OperationQueue();
+                }
+            }
+        }
+        return instance;
+    }
+
+    private OperationQueue() {
+        limitedTaskExecutor = Executors.newFixedThreadPool(count);
+    }
+
+    public void addOperationTask(OperationBackgroundCallBack backgroundCallBack, OperationCompletionCallBack completion, OperationCancelCallBack cancelCallBack) {
+
+        OperationTask task = new OperationTask(backgroundCallBack,completion,cancelCallBack);
+        task.executeOnExecutor(limitedTaskExecutor);
+    }
+
+    private class OperationTask extends AsyncTask<Void, Void, Object> {
+
+        private OperationBackgroundCallBack mBackgroundCallBack;
+        private OperationCompletionCallBack mCompletion;
+        private OperationCancelCallBack mCancelCallBack;
+
+        OperationTask(OperationBackgroundCallBack backgroundCallBack, OperationCompletionCallBack completion, OperationCancelCallBack cancelCallBack) {
+            mBackgroundCallBack = backgroundCallBack;
+            mCompletion = completion;
+            mCancelCallBack = cancelCallBack;
+        }
+
+        @Override
+        protected Object doInBackground(Void... voids) {
+
+            if (mBackgroundCallBack != null) {
+                return mBackgroundCallBack.operationDoInBackground();
+            }
+
+            return null;
+        }
+
+        @Override
+        protected void onPostExecute(Object object) {
+
+            if (mCompletion != null) {
+                mCompletion.operationCompletion(object);
+            }
+        }
+
+        @Override
+        protected void onCancelled() {
+            super.onCancelled();
+
+            if (mCancelCallBack != null) {
+                mCancelCallBack.operationCancelled();
+            }
+        }
+    }
+
+    public interface OperationBackgroundCallBack {
+        Object operationDoInBackground();
+    }
+
+    public interface OperationCompletionCallBack {
+        void operationCompletion(Object object);
+    }
+
+    public interface OperationCancelCallBack {
+        void operationCancelled();
+    }
+
+}

+ 27 - 0
Apex Mobile/app/src/main/java/com/usai/util/Network.java

@@ -126,6 +126,7 @@ public class Network
 
 	// 2019.1.5
 	public static String		URL_UPLOAD_SQL					= "https://ra.apexshipping.com/main_new.php";
+	public static String		URL_FETCH_RESULT				= "https://ra.apexshipping.com/main_new.php";
 
 
 
@@ -1920,4 +1921,30 @@ public class Network
 
 		return handleResponse(jstr);
 	}
+
+	public static JSONObject fetchResult(Bundle params) {
+
+		params.putString("action","handset_search");
+
+		String url = "http://192.168.1.150:8080/MyWeb/SearchBooking";
+
+		String module_name = params.getString("module_name");
+		if (module_name.equals("Ocean Booking")) {
+
+		} else if (module_name.equals("Ocean B/L info.")) {
+
+			url = "http://192.168.1.150:8080/MyWeb/SearchBL";
+		} else if (module_name.equals("Container detail")) {
+
+			url = "http://192.168.1.150:8080/MyWeb/SearchContainer";
+		} else if (module_name.equals("Download Document")) {
+
+			url = "http://192.168.1.150:8080/MyWeb/SearchDoc";
+		}
+
+		// URL_FETCH_RESULT
+		String jstr = getJson(url, params);
+
+		return handleResponse(jstr);
+	}
 }

+ 5 - 0
Apex Mobile/app/src/main/res/anim/dialog_in.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<translate xmlns:android="http://schemas.android.com/apk/res/android"
+           android:duration="200"
+           android:fromYDelta="100%"
+           android:toYDelta="0" />

+ 5 - 0
Apex Mobile/app/src/main/res/anim/dialog_out.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<translate xmlns:android="http://schemas.android.com/apk/res/android"
+           android:duration="200"
+           android:fromYDelta="0"
+           android:toYDelta="100%" />

+ 13 - 0
Apex Mobile/app/src/main/res/drawable/actionsheet_round_corner_highlight_bg.xml

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <corners android:radius="10dp"/>
+
+    <solid android:color="#aaaaaaaa"/>
+
+    <stroke
+        android:width="1dp"
+        android:color="#aaaaaaaa"
+        />
+
+</shape>

+ 13 - 0
Apex Mobile/app/src/main/res/drawable/actionsheet_round_corner_normal_bg.xml

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <corners android:radius="10dp"/>
+
+    <solid android:color="#ffffff"/>
+
+    <stroke
+        android:width="1dp"
+        android:color="#ffffff"
+        />
+
+</shape>

+ 13 - 0
Apex Mobile/app/src/main/res/drawable/actionsheet_round_corner_selected_bg.xml

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <corners android:radius="10dp"/>
+
+    <solid android:color="#00ffff"/>
+
+    <stroke
+        android:width="1dp"
+        android:color="#ffffff"
+        />
+
+</shape>

+ 46 - 0
Apex Mobile/app/src/main/res/drawable/apex_result_cell_bg.xml

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_pressed="true">
+
+        <shape android:shape="rectangle">
+            <!-- 渐变 -->
+            <!--<gradient android:angle="180" android:endColor="#FFCCCCCC"-->
+            <!--android:startColor="@android:color/white" />-->
+            <!-- 描边 -->
+            <stroke android:width="0.3dp" android:color="@android:color/darker_gray" />
+
+            <!-- 实心填充 -->
+            <solid android:color="#cccccc" />
+
+            <!-- 圆角 -->
+            <corners android:bottomLeftRadius="5dip"
+                     android:bottomRightRadius="5dip" android:topLeftRadius="5dip"
+                     android:topRightRadius="5dip" />
+
+        </shape>
+
+    </item>
+
+    <item android:state_pressed="false">
+
+        <shape android:shape="rectangle">
+            <!-- 渐变 -->
+            <!--<gradient android:angle="180" android:endColor="#FFCCCCCC"-->
+            <!--android:startColor="@android:color/white" />-->
+            <!-- 描边 -->
+            <stroke android:width="0.3dp" android:color="@android:color/darker_gray" />
+
+            <!-- 实心填充 -->
+            <solid android:color="@android:color/white" />
+
+            <!-- 圆角 -->
+            <corners android:bottomLeftRadius="5dip"
+                     android:bottomRightRadius="5dip" android:topLeftRadius="5dip"
+                     android:topRightRadius="5dip" />
+
+        </shape>
+
+    </item>
+
+</selector>

+ 9 - 0
Apex Mobile/app/src/main/res/layout/action_sheet.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+    android:background="#00000000"
+    >
+
+</LinearLayout>

+ 18 - 0
Apex Mobile/app/src/main/res/layout/activity_apex_result.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".apexResult.ApexResultActivity">
+
+    <ListView
+        android:id="@+id/apex_result_list_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:divider="@null"
+        android:listSelector="#00000000"
+        />
+
+</RelativeLayout>

+ 29 - 0
Apex Mobile/app/src/main/res/layout/apex_result_addition_view.xml

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<com.usai.apex.apexResult.cell.ApexResultAdditionView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <TextView
+        android:id="@+id/apex_result_addition_title_tv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="5dp"
+        android:textColor="#000000"
+        android:textSize="12.7sp"
+        android:text="Consignee:"
+        />
+
+    <TextView
+        android:id="@+id/apex_result_addition_value_tv"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignTop="@id/apex_result_addition_title_tv"
+        android:layout_toRightOf="@id/apex_result_addition_title_tv"
+        android:layout_marginLeft="5dp"
+        android:textColor="#000000"
+        android:textSize="12.7sp"
+        android:text="FU YAMA TRADing"
+        />
+
+</com.usai.apex.apexResult.cell.ApexResultAdditionView>

+ 69 - 0
Apex Mobile/app/src/main/res/layout/apex_result_document_cell.xml

@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<com.usai.apex.apexResult.cell.ApexResultDocumentCell xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="90dp">
+
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="75dp"
+        android:layout_marginTop="15dp"
+        android:layout_marginLeft="5dp"
+        android:layout_marginRight="5dp"
+        android:background="@drawable/apex_result_cell_bg"
+        >
+
+        <ImageView
+            android:id="@+id/apex_result_document_icon_view"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:layout_marginLeft="10dp"
+            android:layout_centerVertical="true"
+            android:scaleType="fitCenter"
+            android:src="@drawable/mode_document"
+            />
+
+        <TextView
+            android:id="@+id/apex_result_document_file_type_tv"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignTop="@id/apex_result_document_icon_view"
+            android:layout_alignParentRight="true"
+            android:layout_marginLeft="8dp"
+            android:layout_marginRight="5dp"
+            android:textSize="17sp"
+            android:textColor="#000000"
+            android:text="HBL"
+            />
+
+        <TextView
+            android:id="@+id/apex_result_document_file_name_tv"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignTop="@id/apex_result_document_icon_view"
+            android:layout_toRightOf="@id/apex_result_document_icon_view"
+            android:layout_toLeftOf="@id/apex_result_document_file_type_tv"
+            android:layout_marginLeft="5dp"
+            android:textSize="17sp"
+            android:textColor="#000000"
+            android:text="A1811390637FR.pdf"
+            />
+
+        <TextView
+            android:id="@+id/apex_result_document_file_desc_tv"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_toRightOf="@id/apex_result_document_icon_view"
+            android:layout_below="@id/apex_result_document_file_name_tv"
+            android:layout_marginTop="5dp"
+            android:layout_marginLeft="5dp"
+            android:layout_marginRight="5dp"
+            android:layout_marginBottom="5dp"
+            android:textSize="14sp"
+            android:textColor="#aaaaaa"
+            android:text="A1811390637FR.pdf"
+            />
+
+    </RelativeLayout>
+
+</com.usai.apex.apexResult.cell.ApexResultDocumentCell>

+ 149 - 0
Apex Mobile/app/src/main/res/layout/apex_result_ship_cell.xml

@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="utf-8"?>
+<com.usai.apex.apexResult.cell.ApexResultShipCell xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+    android:orientation="vertical"
+    >
+
+    <RelativeLayout
+        android:id="@+id/apex_result_ship_top"
+        android:layout_width="match_parent"
+        android:layout_height="15dp"
+        >
+
+    </RelativeLayout>
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="5dp"
+        android:layout_marginRight="5dp"
+        android:layout_marginBottom="5dp"
+        android:background="@drawable/apex_result_cell_bg"
+        android:clipChildren="true"
+        >
+
+
+        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                      xmlns:app="http://schemas.android.com/apk/res-auto"
+                      android:layout_width="match_parent"
+                      android:layout_height="wrap_content"
+                      android:orientation="vertical"
+                      android:layout_marginRight="10dp"
+            >
+
+            <android.support.constraint.ConstraintLayout
+                android:id="@+id/cell_content_view"
+                android:layout_width="match_parent"
+                android:layout_height="96dp"
+                android:clipChildren="true">
+
+                <com.usai.apex.mainframe.TrackingImageView
+                    android:id="@+id/iv_status"
+                    android:layout_width="42dp"
+                    android:layout_height="42dp"
+                    android:layout_marginTop="4dp"
+                    app:layout_constraintStart_toStartOf="@+id/tv_title"
+                    app:layout_constraintTop_toBottomOf="@+id/tv_time"
+                    app:srcCompat="@drawable/ic_launcher" />
+
+                <TextView
+                    android:id="@+id/tv_title"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginEnd="13dp"
+                    android:layout_marginStart="13dp"
+                    android:layout_marginTop="8dp"
+                    android:ellipsize="end"
+                    android:singleLine="true"
+                    android:text="TextView"
+                    android:textColor="@color/icon_gray"
+                    android:textSize="12.7sp"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toTopOf="parent" />
+
+                <TextView
+                    android:id="@+id/tv_time"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginRight="8dp"
+                    android:layout_marginTop="2dp"
+                    android:text="TextView"
+                    android:textColor="@color/icon_red"
+                    android:textSize="9.7sp"
+                    app:layout_constraintEnd_toStartOf="@+id/tv_port"
+                    app:layout_constraintStart_toStartOf="@+id/tv_title"
+                    app:layout_constraintTop_toBottomOf="@+id/tv_title" />
+
+                <TextView
+                    android:id="@+id/tv_port"
+                    android:layout_width="94dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="3dp"
+                    android:gravity="right"
+                    android:text="CNTAO - USLAX"
+                    android:textColor="@color/icon_red"
+                    android:textSize="9.7sp"
+                    app:layout_constraintEnd_toEndOf="@+id/tv_title"
+                    app:layout_constraintTop_toBottomOf="@+id/tv_title" />
+
+                <TextView
+                    android:id="@+id/tv_description"
+                    android:layout_width="0dp"
+                    android:layout_height="16dp"
+                    android:layout_marginLeft="7dp"
+                    android:ellipsize="end"
+                    android:singleLine="true"
+                    android:text="TextView"
+                    android:textColor="@color/icon_gray"
+                    android:textSize="12.7sp"
+                    app:layout_constraintEnd_toEndOf="@+id/tv_title"
+                    app:layout_constraintStart_toEndOf="@+id/iv_status"
+                    app:layout_constraintTop_toTopOf="@+id/iv_status" />
+
+                <TextView
+                    android:id="@+id/tv_detail"
+                    android:layout_width="0dp"
+                    android:layout_height="0dp"
+                    android:layout_marginBottom="2dp"
+                    android:layout_marginLeft="7dp"
+                    android:layout_marginTop="2dp"
+                    android:ellipsize="end"
+                    android:lines="2"
+                    android:text="TextView"
+                    android:textColor="@android:color/darker_gray"
+                    android:textSize="9.7sp"
+                    app:layout_constraintBottom_toBottomOf="parent"
+                    app:layout_constraintEnd_toEndOf="@+id/tv_title"
+                    app:layout_constraintStart_toEndOf="@+id/iv_status"
+                    app:layout_constraintTop_toBottomOf="@+id/tv_description" />
+
+            </android.support.constraint.ConstraintLayout>
+
+            <LinearLayout
+                android:id="@+id/apex_result_ship_addition_view"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical"
+                android:layout_marginLeft="13dp"
+                >
+
+            </LinearLayout>
+
+        </LinearLayout>
+
+        <View
+            android:id="@+id/v_transport_stage"
+            android:layout_width="5dp"
+            android:layout_height="match_parent"
+            android:background="@drawable/list_corner_transport_stage_bg_0"
+            android:layout_alignParentRight="true"
+            />
+
+    </RelativeLayout>
+
+
+
+
+</com.usai.apex.apexResult.cell.ApexResultShipCell>

+ 12 - 0
Apex Mobile/app/src/main/res/menu/apex_result_menu.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+      xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <item
+        android:id="@+id/apex_result_menu"
+        android:icon="@drawable/ic_setting"
+        android:title=""
+        app:showAsAction="always"
+        />
+
+</menu>

+ 22 - 0
Apex Mobile/app/src/main/res/values/actionsheet_styles.xml

@@ -0,0 +1,22 @@
+<resources>
+
+    <style name="actionSheet" parent="@android:style/Theme.Dialog">
+
+        <!-- 背景透明 -->
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:windowContentOverlay">@null</item>
+        <!-- 浮于Activity之上 -->
+        <item name="android:windowIsFloating">true</item>
+        <!-- 边框 -->
+        <item name="android:windowFrame">@null</item>
+        <!-- Dialog以外的区域模糊效果 -->
+        <item name="android:backgroundDimEnabled">true</item>
+        <!-- 无标题 -->
+        <item name="android:windowNoTitle">true</item>
+        <!-- 半透明 -->
+        <item name="android:windowIsTranslucent">true</item>
+        <!-- Dialog进入及退出动画 -->
+        <item name="android:windowAnimationStyle">@style/DialogAnimation</item>
+    </style>
+
+</resources>

+ 10 - 0
Apex Mobile/app/src/main/res/values/animation.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <!-- Dialog进出动画 -->
+    <style name="DialogAnimation" parent="@android:style/Animation.Dialog">
+        <item name="android:windowEnterAnimation">@anim/dialog_in</item>
+        <item name="android:windowExitAnimation">@anim/dialog_out</item>
+    </style>
+
+</resources>

+ 1 - 1
Apex Mobile/build.gradle

@@ -5,7 +5,7 @@ buildscript {
         google()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:3.1.1'
+        classpath 'com.android.tools.build:gradle:3.2.1'
     }
 }
 

+ 2 - 2
Apex Mobile/gradle/wrapper/gradle-wrapper.properties

@@ -1,6 +1,6 @@
-#Tue Apr 17 13:08:42 CST 2018
+#Tue Jan 08 10:08:53 CST 2019
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip