Преглед изворни кода

1.完成Android Apex Drivers Setting。

Pen Li пре 7 година
родитељ
комит
11c17e77c3
39 измењених фајлова са 1743 додато и 40 уклоњено
  1. 36 39
      ApexDrivers/app/src/main/AndroidManifest.xml
  2. 56 0
      ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/ApexDriverApplication.java
  3. 91 0
      ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/base/BasicObject.java
  4. 156 1
      ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/SettingActivity.java
  5. 349 0
      ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/SettingAdapter.java
  6. 70 0
      ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/changepassword/ChangePasswordDialog.java
  7. 52 0
      ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/model/AboutModel.java
  8. 11 0
      ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/model/ActionModel.java
  9. 31 0
      ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/model/BaseModel.java
  10. 105 0
      ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/model/OptionModel.java
  11. 73 0
      ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/model/SectionModel.java
  12. 9 0
      ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/model/SettingOption.java
  13. 7 0
      ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/model/SwitchModel.java
  14. 231 0
      ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/option/OptionActivity.java
  15. 5 0
      ApexDrivers/app/src/main/res/anim/dialog_in.xml
  16. 5 0
      ApexDrivers/app/src/main/res/anim/dialog_out.xml
  17. BIN
      ApexDrivers/app/src/main/res/drawable-hdpi/icon_50.png
  18. BIN
      ApexDrivers/app/src/main/res/drawable-hdpi/redant_logo.png
  19. BIN
      ApexDrivers/app/src/main/res/drawable-ldpi/icon_50.png
  20. BIN
      ApexDrivers/app/src/main/res/drawable-ldpi/redant_logo.png
  21. BIN
      ApexDrivers/app/src/main/res/drawable-mdpi/icon_50.png
  22. BIN
      ApexDrivers/app/src/main/res/drawable-mdpi/redant_logo.png
  23. BIN
      ApexDrivers/app/src/main/res/drawable-xhdpi/icon_50.png
  24. BIN
      ApexDrivers/app/src/main/res/drawable-xhdpi/redant_logo.png
  25. BIN
      ApexDrivers/app/src/main/res/drawable-xxhdpi/icon_50.png
  26. BIN
      ApexDrivers/app/src/main/res/drawable-xxhdpi/redant_logo.png
  27. 8 0
      ApexDrivers/app/src/main/res/drawable/animate.xml
  28. 9 0
      ApexDrivers/app/src/main/res/drawable/change_password_dialog_round_corner_bg.xml
  29. 16 0
      ApexDrivers/app/src/main/res/layout/activity_option.xml
  30. 9 0
      ApexDrivers/app/src/main/res/layout/activity_setting.xml
  31. 89 0
      ApexDrivers/app/src/main/res/layout/change_password_dialog.xml
  32. 33 0
      ApexDrivers/app/src/main/res/layout/option_item_cell.xml
  33. 84 0
      ApexDrivers/app/src/main/res/layout/setting_about_cell.xml
  34. 37 0
      ApexDrivers/app/src/main/res/layout/setting_action_cell.xml
  35. 48 0
      ApexDrivers/app/src/main/res/layout/setting_option_cell.xml
  36. 14 0
      ApexDrivers/app/src/main/res/layout/setting_section_header.xml
  37. 34 0
      ApexDrivers/app/src/main/res/layout/setting_switch_cell.xml
  38. 53 0
      ApexDrivers/app/src/main/res/raw/setting.json
  39. 22 0
      ApexDrivers/app/src/main/res/values/styles.xml

+ 36 - 39
ApexDrivers/app/src/main/AndroidManifest.xml

@@ -7,27 +7,22 @@
     <!-- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> -->
     <!-- <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> -->
 
-    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
-    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
-    <uses-permission android:name="android.permission.CAMERA" />
-    <uses-permission android:name="android.permission.WAKE_LOCK" />
-    <uses-permission android:name="android.permission.VIBRATE" />
-    <uses-permission android:name="android.permission.FLASHLIGHT" />
-
-
-
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
+    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
+    <uses-permission android:name="android.permission.CAMERA"/>
+    <uses-permission android:name="android.permission.WAKE_LOCK"/>
+    <uses-permission android:name="android.permission.VIBRATE"/>
+    <uses-permission android:name="android.permission.FLASHLIGHT"/>
     <uses-permission android:name="android.alarm.permission.SET_ALARM"/>
-
-    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
-
+    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
     <uses-permission android:name="android.permission.INTERNET"/>
 
     <!-- 调用硬件相机权限 -->
-    <uses-feature android:name="android.hardware.camera" />
-    <uses-feature android:name="android.hardware.camera.autofocus" />
+    <uses-feature android:name="android.hardware.camera"/>
+    <uses-feature android:name="android.hardware.camera.autofocus"/>
     <!-- 文件读写权限 -->
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
 
     <application
         android:name=".ApexDriverApplication"
@@ -37,8 +32,7 @@
         android:roundIcon="@mipmap/ic_launcher_round"
         android:supportsRtl="true"
         android:theme="@style/ApexDriverTheme"
-        tools:replace="android:theme,android:icon"
-        >
+        tools:replace="android:theme,android:icon">
         <provider
             android:name="android.support.v4.content.FileProvider"
             android:authorities="com.usai.apex.driver.fileprovider"
@@ -46,7 +40,7 @@
             android:grantUriPermissions="true">
             <meta-data
                 android:name="android.support.FILE_PROVIDER_PATHS"
-                android:resource="@xml/download_dir"></meta-data>
+                android:resource="@xml/download_dir"/>
         </provider>
 
         <activity
@@ -54,9 +48,9 @@
             android:launchMode="singleTop"
             android:screenOrientation="portrait">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
+                <action android:name="android.intent.action.MAIN"/>
 
-                <category android:name="android.intent.category.LAUNCHER" />
+                <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
 
@@ -78,20 +72,20 @@
             android:exported="false"
             android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
             <intent-filter>
-                <action android:name="android.intent.action.BOOT_COMPLETED" />
-                <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
+                <action android:name="android.intent.action.BOOT_COMPLETED"/>
+                <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED"/>
             </intent-filter>
         </receiver>
 
         <activity
             android:name=".detail.DetailActivity"
-            android:screenOrientation="portrait"></activity>
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".update.UpdateActivity"
-            android:screenOrientation="portrait"></activity>
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".camera.PreferencesActivity"
-            android:screenOrientation="portrait"></activity>
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".codescanner.CaptureActivity"
             android:clearTaskOnLaunch="true"
@@ -99,44 +93,47 @@
             android:screenOrientation="sensorLandscape"
             android:stateNotNeeded="true"
             android:theme="@style/CaptureTheme"
-            android:windowSoftInputMode="stateAlwaysHidden"></activity>
+            android:windowSoftInputMode="stateAlwaysHidden"/>
         <activity
             android:name=".update.PhotoPreviewActivity"
-            android:screenOrientation="portrait"></activity>
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".login.RetrievePasswordActivity"
-            android:screenOrientation="portrait"></activity>
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".home.HomeMoreActivity"
-            android:screenOrientation="portrait"></activity>
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".upload.UploadListActivity"
-            android:screenOrientation="portrait"></activity>
+            android:screenOrientation="portrait"/>
         <activity
             android:name=".upload.TaskActivity"
-            android:screenOrientation="portrait"></activity>
-        <activity android:name=".filter.OrderFilterActivity"></activity>
-        <activity android:name=".signature.SignatureActivity"></activity>
+            android:screenOrientation="portrait"/>
+        <activity android:name=".filter.OrderFilterActivity"/>
+        <activity android:name=".signature.SignatureActivity"/>
 
         <receiver
             android:name=".receiver.ApexDriverAlarmReceiver"
+            android:directBootAware="true"
             android:enabled="true"
             android:exported="true"
-            android:directBootAware="true"
             android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
             >
             <intent-filter>
 
-                <!--<action android:name="REDANT.BROADCAST.ACTION_REDANT_INIT_ALARM" />-->
-                <!--<action android:name="REDANT.BROADCAST.ACTION_REDANT_ALARM" />-->
-                <action android:name="android.intent.action.BOOT_COMPLETED" />
-                <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
+                <!-- <action android:name="REDANT.BROADCAST.ACTION_REDANT_INIT_ALARM" /> -->
+                <!-- <action android:name="REDANT.BROADCAST.ACTION_REDANT_ALARM" /> -->
+                <action android:name="android.intent.action.BOOT_COMPLETED"/>
+                <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED"/>
             </intent-filter>
         </receiver>
+
         <activity android:name=".message.MessageActivity">
         </activity>
         <activity android:name=".setting.SettingActivity">
         </activity>
+        <activity android:name=".setting.option.OptionActivity">
+        </activity>
     </application>
 
 </manifest>

+ 56 - 0
ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/ApexDriverApplication.java

@@ -9,6 +9,7 @@ import android.content.SharedPreferences;
 import android.location.Location;
 import android.os.Build;
 import android.os.IBinder;
+import android.text.TextUtils;
 import android.util.Log;
 
 import com.usai.redant.apexdrivers.receiver.ApexDriverAlarmReceiver;
@@ -16,6 +17,9 @@ import com.usai.redant.apexdrivers.utils.OperationQueue;
 import com.usai.redant.rautils.receiver.RABroadcast;
 import com.usai.redant.rautils.utils.AESUtil;
 
+import java.io.File;
+import java.lang.reflect.Field;
+
 public class ApexDriverApplication extends Application {
 
     public final static String secretKey = "usai";
@@ -26,6 +30,14 @@ public class ApexDriverApplication extends Application {
     public String password;
 
 
+    public final static int BackgroundReportTypeNone = 0;
+    public final static int BackgroundReportTypeReject = 1;
+    public final static int BackgroundReportTypeAlways = 2;
+    public final static int BackgroundReportTypeAllow = 3;
+
+    public int backgroundReportType;
+
+
     private ServiceConnection mServiceConnection;
     private ApexDriversBackgroundService mService;
     private boolean mRequiredLocation = false;
@@ -212,6 +224,50 @@ public class ApexDriverApplication extends Application {
 
     }
 
+    public Object getValueForKeyPath(String keyPath) {
+        if (TextUtils.isEmpty(keyPath)) {
+            return null;
+        }
+
+        try {
+
+            Field field = getClass().getField(keyPath);
+            if (field != null) {
+                Object obj = field.get(this);
+                return obj;
+            } else {
+                return null;
+            }
+
+        } catch (NoSuchFieldException e) {
+            e.printStackTrace();
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public void setValueForKeyPath(String keyPath,Object value) {
+
+        if (TextUtils.isEmpty(keyPath)) {
+            return;
+        }
+
+        try {
+
+            Field field = getClass().getField(keyPath);
+            if (field != null) {
+                field.set(this,value);
+            }
+
+        } catch (NoSuchFieldException e) {
+            e.printStackTrace();
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+        }
+
+    }
+
     public static ApexDriverApplication sharedApplication() {
         return mApp;
     }

+ 91 - 0
ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/base/BasicObject.java

@@ -0,0 +1,91 @@
+package com.usai.redant.apexdrivers.base;
+
+import org.json.JSONObject;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+public class BasicObject {
+
+    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;
+                    }
+
+                    Class type = f.getType();
+                    if (type == value.getClass() || ((type == int.class || type == long.class) && value.getClass() == Integer.class) || ((type == float.class || type == double.class) && (value.getClass() == Double.class || value.getClass() == Float.class))) {
+
+
+                        String setter = "set" + toUpperCaseFirstOne(key);
+                       try {
+                           Method method = cls.getMethod(setter,type);
+                           if (method != null) {
+                               method.invoke(this,value);
+                           } else {
+                               f.set(this,value);
+                           }
+                       } catch (NoSuchMethodException e) {
+
+                           e.printStackTrace();
+
+                           f.set(this,value);
+                       } catch (SecurityException e) {
+                           e.printStackTrace();
+
+                           f.set(this,value);
+                       }
+
+                    } else {
+                        if (value.getClass() == String.class) {
+                            String string = (String)value;
+                            if (type == Integer.class) {
+
+                                value = Integer.valueOf(string);
+                                f.set(this,value);
+
+                            } else if (type == Double.class) {
+
+                                value = Double.valueOf(string);
+                                f.set(this,value);
+
+                            } else if (type == Boolean.class) {
+
+                                value = Boolean.valueOf(string);
+                                f.set(this,value);
+                            }
+
+                        }
+                    }
+
+                }
+                cls = cls.getSuperclass();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public 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();
+    }
+}

+ 156 - 1
ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/SettingActivity.java

@@ -6,10 +6,24 @@ import android.support.v7.app.ActionBar;
 import android.support.v7.app.AppCompatActivity;
 import android.os.Bundle;
 import android.view.MenuItem;
+import android.view.View;
+import android.widget.ExpandableListView;
 
 import com.usai.redant.apexdrivers.R;
+import com.usai.redant.apexdrivers.network.Network;
+import com.usai.redant.apexdrivers.setting.changepassword.ChangePasswordDialog;
+import com.usai.redant.apexdrivers.setting.model.ActionModel;
+import com.usai.redant.apexdrivers.setting.model.BaseModel;
+import com.usai.redant.apexdrivers.setting.model.OptionModel;
+import com.usai.redant.apexdrivers.setting.model.SectionModel;
+import com.usai.redant.apexdrivers.setting.option.OptionActivity;
 
-public class SettingActivity extends AppCompatActivity {
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+
+public class SettingActivity extends AppCompatActivity implements SettingAdapter.SettingAdapterDelegate {
 
     public static void startSettingActivity(Context context) {
         if (context == null) {
@@ -20,6 +34,15 @@ public class SettingActivity extends AppCompatActivity {
         context.startActivity(intent);
     }
 
+    private static final int REQUEST_CODE_OPTION = 0;
+
+    private ExpandableListView mListView;
+    private SettingAdapter mAdapter;
+    private ArrayList<SectionModel> mSections;
+    private Context mCtx = this;
+
+    private OptionModel mClickedOptionModel = null;
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -30,6 +53,64 @@ public class SettingActivity extends AppCompatActivity {
             actionBar.setHomeButtonEnabled(true);
             actionBar.setDisplayHomeAsUpEnabled(true);
         }
+        mSections = new ArrayList<>();
+        loadData();
+
+        mAdapter = new SettingAdapter(mCtx,this,mSections);
+
+        mListView = findViewById(R.id.setting_list_view);
+        mListView.setAdapter(mAdapter);
+        mListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
+            @Override
+            public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
+                return true;
+            }
+        });
+        mListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
+            @Override
+            public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
+
+                SectionModel sectionModel = mSections.get(groupPosition);
+                BaseModel baseModel = sectionModel.settings.get(childPosition);
+                switch (baseModel.type) {
+                    case BaseModel.SettingTypeOption: {
+
+                        showOption((OptionModel)baseModel);
+
+                    }
+                    break;
+                    case BaseModel.SettingTypeSwitch: {
+
+                    }
+                    break;
+                    case BaseModel.SettingTypeAction: {
+
+                        clickAction((ActionModel)baseModel);
+
+                    }
+                    break;
+                    case BaseModel.SettingTypeAbout: {
+
+                    }
+                    break;
+                }
+
+                return false;
+            }
+        });
+
+        /**
+         *
+         *  打开所有Group,否则默认关闭
+         *
+         * */
+        if (mSections.size() > 0) {
+            for (int i = 0; i < mSections.size(); i++) {
+                mListView.expandGroup(i);
+            }
+        }
+        mAdapter.notifyDataSetChanged();
+
     }
 
     @Override
@@ -42,4 +123,78 @@ public class SettingActivity extends AppCompatActivity {
         }
         return super.onOptionsItemSelected(item);
     }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        switch (requestCode) {
+            case REQUEST_CODE_OPTION: {
+                if (resultCode == RESULT_OK && data != null) {
+
+                    int selectedOption = data.getIntExtra(OptionActivity.SelectedKey,-1);
+                    if (mClickedOptionModel != null) {
+                        mClickedOptionModel.setSelectedOption(selectedOption);
+                    }
+
+                }
+                mClickedOptionModel = null;
+            }
+            break;
+        }
+
+    }
+
+    public void loadData() {
+
+        mSections.clear();
+
+        JSONObject json = Network.loadFakeData(mCtx,R.raw.setting);
+        if (json != null) {
+            JSONArray sections = json.optJSONArray("sections");
+            if (sections != null) {
+                for (int i = 0; i < sections.length(); i++) {
+                    JSONObject section = sections.optJSONObject(i);
+                    if (section != null) {
+
+                        SectionModel model = new SectionModel();
+                        JSONArray settings = section.optJSONArray("settings");
+                        if (settings != null) {
+                            model.setSettings(settings);
+                        }
+                        mSections.add(model);
+                    }
+                }
+            }
+        }
+    }
+
+    private void showOption(OptionModel model) {
+        if (model == null) {
+            return;
+        }
+
+        mClickedOptionModel = model;
+        OptionActivity.startOptionActivity(this,model.optionsJsonString(),model.selectedOption(), REQUEST_CODE_OPTION);
+
+    }
+
+    private void clickAction(ActionModel model) {
+        if (model == null) {
+            return;
+        }
+
+        switch (model.actionType) {
+            case ActionModel.ActionTypeChangePassword : {
+
+                new ChangePasswordDialog(mCtx).show();
+
+            }
+            break;
+            case ActionModel.ActionTypeCleanCache: {
+
+            }
+            break;
+        }
+
+    }
 }

+ 349 - 0
ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/SettingAdapter.java

@@ -0,0 +1,349 @@
+package com.usai.redant.apexdrivers.setting;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseExpandableListAdapter;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import com.usai.redant.apexdrivers.R;
+import com.usai.redant.apexdrivers.setting.model.AboutModel;
+import com.usai.redant.apexdrivers.setting.model.ActionModel;
+import com.usai.redant.apexdrivers.setting.model.BaseModel;
+import com.usai.redant.apexdrivers.setting.model.OptionModel;
+import com.usai.redant.apexdrivers.setting.model.SectionModel;
+import com.usai.redant.apexdrivers.setting.model.SwitchModel;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+
+public class SettingAdapter extends BaseExpandableListAdapter {
+
+    public interface SettingAdapterDelegate {
+
+    }
+
+
+    private WeakReference<SettingAdapterDelegate> weakDelegate;
+    private ArrayList<SectionModel> sections;
+    private Context mCtx;
+    SettingAdapter(Context context,SettingAdapterDelegate delegate,ArrayList<SectionModel> sections) {
+        mCtx = context;
+        if (delegate != null) {
+            weakDelegate = new WeakReference<>(delegate);
+        }
+        this.sections = sections;
+    }
+
+    @Override
+    public int getGroupCount() {
+        if (sections == null) {
+            return 0;
+        }
+        return sections.size();
+    }
+
+    @Override
+    public int getChildrenCount(int groupPosition) {
+
+        SectionModel sectionModel = sections.get(groupPosition);
+        if (sectionModel.settings == null) {
+            return 0;
+        }
+
+        return sectionModel.settings.size();
+    }
+
+    @Override
+    public Object getGroup(int groupPosition) {
+        SectionModel sectionModel = sections.get(groupPosition);
+        return sectionModel;
+    }
+
+    @Override
+    public Object getChild(int groupPosition, int childPosition) {
+        SectionModel sectionModel = sections.get(groupPosition);
+        return sectionModel.settings.get(childPosition);
+    }
+
+    @Override
+    public long getGroupId(int groupPosition) {
+        return groupPosition;
+    }
+
+    @Override
+    public long getChildId(int groupPosition, int childPosition) {
+        return childPosition;
+    }
+
+    @Override
+    public int getChildTypeCount() {
+        return BaseModel.settingTypeCount();
+    }
+
+    @Override
+    public int getChildType(int groupPosition, int childPosition) {
+        SectionModel sectionModel = sections.get(groupPosition);
+        return sectionModel.settings.get(childPosition).type;
+    }
+
+    @Override
+    public boolean hasStableIds() {
+        return false;
+    }
+
+    @Override
+    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
+
+        SectionHolder holder;
+        if (convertView == null) {
+
+            convertView = LayoutInflater.from(mCtx).inflate(R.layout.setting_section_header,null);
+            holder = new SectionHolder(convertView);
+
+        } else {
+            holder = (SectionHolder)convertView.getTag();
+        }
+
+        return convertView;
+    }
+
+    @Override
+    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
+
+        SectionModel sectionModel = sections.get(groupPosition);
+        BaseModel model = sectionModel.settings.get(childPosition);
+        switch (model.type) {
+            case BaseModel.SettingTypeOption: {
+
+                OptionHolder holder;
+                if (convertView == null) {
+
+                    convertView = LayoutInflater.from(mCtx).inflate(R.layout.setting_option_cell,null);
+                    holder = new OptionHolder(convertView);
+
+                } else {
+                    holder = (OptionHolder)convertView.getTag();
+                }
+                holder.setModel(model);
+            }
+            break;
+            case BaseModel.SettingTypeSwitch: {
+
+                SwitchHolder holder;
+                if (convertView == null) {
+
+                    convertView = LayoutInflater.from(mCtx).inflate(R.layout.setting_switch_cell,null);
+                    holder = new SwitchHolder(convertView);
+
+                } else {
+                    holder = (SwitchHolder)convertView.getTag();
+                }
+                holder.setModel(model);
+            }
+            break;
+            case BaseModel.SettingTypeAction: {
+
+                ActionHolder holder;
+                if (convertView == null) {
+
+                    convertView = LayoutInflater.from(mCtx).inflate(R.layout.setting_action_cell,null);
+                    holder = new ActionHolder(convertView);
+
+                } else {
+                    holder = (ActionHolder)convertView.getTag();
+                }
+                holder.setModel(model);
+            }
+            break;
+            case BaseModel.SettingTypeAbout: {
+
+                AboutHolder holder;
+                if (convertView == null) {
+
+                    convertView = LayoutInflater.from(mCtx).inflate(R.layout.setting_about_cell,null);
+                    holder = new AboutHolder(convertView);
+
+                } else {
+                    holder = (AboutHolder)convertView.getTag();
+                }
+                holder.setModel(model);
+            }
+            break;
+
+        }
+
+        return convertView;
+    }
+
+    @Override
+    public boolean isChildSelectable(int groupPosition, int childPosition) {
+        return true;
+    }
+
+
+    private class SectionHolder {
+
+        SectionHolder(View view) {
+            view.setTag(this);
+        }
+    }
+
+    private class BaseHolder implements BaseModel.ModelDelegate {
+
+        private BaseModel model;
+
+        public void setModel(BaseModel model) {
+            if (this.model != null) {
+                this.model.setDelegate(null);
+            }
+            this.model = model;
+            if (this.model != null) {
+                this.model.setDelegate(this);
+            }
+
+            refreshUI();
+        }
+
+        public BaseModel getModel() {
+            return model;
+        }
+
+        @Override
+        public void refreshUI() {
+
+        }
+    }
+
+    private class OptionHolder extends BaseHolder {
+
+        private TextView titleTv;
+        private TextView valueTv;
+
+        OptionHolder(View view) {
+            view.setTag(this);
+
+            titleTv = view.findViewById(R.id.setting_option_title_tv);
+            valueTv = view.findViewById(R.id.setting_option_value_tv);
+        }
+
+        @Override
+        public void refreshUI() {
+            super.refreshUI();
+
+            OptionModel model = (OptionModel) getModel();
+            if (model != null) {
+                titleTv.setText(model.title);
+                if (model.option != null) {
+                    valueTv.setText(model.option.title);
+                } else {
+                    valueTv.setText(null);
+                }
+            } else {
+                valueTv.setText(null);
+            }
+
+        }
+    }
+
+    private class SwitchHolder extends BaseHolder {
+
+        private TextView titleTv;
+        private Switch aSwitch;
+
+        SwitchHolder(View view) {
+            view.setTag(this);
+
+            titleTv = view.findViewById(R.id.setting_switch_title_tv);
+            aSwitch = view.findViewById(R.id.setting_action_switch_view);
+        }
+
+        @Override
+        public void refreshUI() {
+            super.refreshUI();
+
+            SwitchModel model = (SwitchModel)getModel();
+            if (model != null) {
+
+                titleTv.setText(model.title);
+                aSwitch.setChecked(model.switchValue);
+
+            } else {
+                titleTv.setText(null);
+                aSwitch.setChecked(false);
+            }
+        }
+    }
+
+    private class ActionHolder extends BaseHolder {
+
+        private TextView titleTv;
+        private ProgressBar indicator;
+
+        ActionHolder(View view) {
+            view.setTag(this);
+
+            titleTv = view.findViewById(R.id.setting_action_title_tv);
+            indicator = view.findViewById(R.id.setting_action_indicator_view);
+        }
+
+        @Override
+        public void refreshUI() {
+            super.refreshUI();
+
+            ActionModel model = (ActionModel)getModel();
+            if (model != null) {
+
+                titleTv.setText(model.title);
+                indicator.setVisibility(model.active ? View.VISIBLE : View.GONE);
+
+            } else {
+                titleTv.setText(null);
+                indicator.setVisibility(View.GONE);
+            }
+        }
+    }
+
+    private class AboutHolder extends BaseHolder {
+
+        private ImageView iconView,redantLogoView;
+        private TextView appNameTv,appVerTv,appSupportTv;
+
+        AboutHolder(View view) {
+            view.setTag(this);
+
+            iconView = view.findViewById(R.id.setting_about_icon_view);
+            redantLogoView = view.findViewById(R.id.setting_about_redant_view);
+            appNameTv = view.findViewById(R.id.setting_about_name_tv);
+            appVerTv = view.findViewById(R.id.setting_about_ver_tv);
+            appSupportTv = view.findViewById(R.id.setting_about_surpport_value_tv);
+        }
+
+        @Override
+        public void refreshUI() {
+            super.refreshUI();
+
+            AboutModel model = (AboutModel)getModel();
+            if (model != null) {
+
+                iconView.setImageResource(model.appIcon());
+                redantLogoView.setImageResource(model.redantLogo());
+                appNameTv.setText(model.appName(mCtx));
+                appVerTv.setText(model.appVer(mCtx));
+                appSupportTv.setText(model.appSupport());
+
+            } else {
+                iconView.setImageBitmap(null);
+                redantLogoView.setImageBitmap(null);
+                appNameTv.setText(null);
+                appVerTv.setText(null);
+                appSupportTv.setText(null);
+
+            }
+        }
+    }
+}

+ 70 - 0
ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/changepassword/ChangePasswordDialog.java

@@ -0,0 +1,70 @@
+package com.usai.redant.apexdrivers.setting.changepassword;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.LinearLayout;
+
+import com.usai.redant.apexdrivers.R;
+
+public class ChangePasswordDialog extends Dialog {
+
+
+    private Context mCtx;
+    private LinearLayout mRootView;
+
+    public ChangePasswordDialog(@NonNull Context context) {
+        this(context,R.style.changePasswordDialog);
+    }
+
+    public ChangePasswordDialog(@NonNull Context context, int themeResId) {
+        super(context, themeResId);
+
+        mCtx = context;
+        init();
+    }
+
+    protected ChangePasswordDialog(@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.change_password_dialog, null);
+        setContentView(mRootView);
+    }
+
+    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.CENTER);
+            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();
+    }
+}

+ 52 - 0
ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/model/AboutModel.java

@@ -0,0 +1,52 @@
+package com.usai.redant.apexdrivers.setting.model;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+
+import com.usai.redant.apexdrivers.R;
+import com.usai.redant.rautils.utils.RAUtil;
+
+public class AboutModel extends BaseModel {
+
+    public String appName(Context context) {
+        if (context == null)
+            return null;
+
+        return RAUtil.getApplicationName(context);
+    }
+
+    public String appVer(Context context) {
+        if (context == null)
+            return null;
+
+        try {
+            PackageManager pm = context.getPackageManager();
+            PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
+            String ver_name = pi.versionName;
+            int ver_code = pi.versionCode;
+
+            return "Ver: " + ver_name + " " + ver_code;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+
+    public String appCopyright() {
+        return "Copyright © 2014 United Software Applications, Inc.";
+    }
+
+    public String appSupport() {
+        return "redantsupport@united-us.net";
+    }
+
+    public int appIcon() {
+        return R.drawable.launch_icon;
+    }
+
+    public int redantLogo() {
+        return R.drawable.redant_logo;
+    }
+}

+ 11 - 0
ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/model/ActionModel.java

@@ -0,0 +1,11 @@
+package com.usai.redant.apexdrivers.setting.model;
+
+public class ActionModel extends BaseModel {
+
+    public static final int ActionTypeCleanCache = 0;
+    public static final int ActionTypeChangePassword = 1;
+
+
+    public int actionType;
+    public boolean active;
+}

+ 31 - 0
ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/model/BaseModel.java

@@ -0,0 +1,31 @@
+package com.usai.redant.apexdrivers.setting.model;
+
+import com.usai.redant.apexdrivers.base.BasicObject;
+
+public class BaseModel extends BasicObject {
+
+    public static final int SettingTypeOption = 0;
+    public static final int SettingTypeSwitch = 1;
+    public static final int SettingTypeAction = 2;
+    public static final int SettingTypeAbout = 3;
+
+    public static int settingTypeCount() {
+        return 4;
+    }
+
+    public interface ModelDelegate {
+        void refreshUI();
+    }
+
+    public int type;
+    public String title;
+
+    private ModelDelegate delegate;
+    public void setDelegate(ModelDelegate delegate) {
+        this.delegate = delegate;
+    }
+
+    public ModelDelegate getDelegate() {
+        return delegate;
+    }
+}

+ 105 - 0
ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/model/OptionModel.java

@@ -0,0 +1,105 @@
+package com.usai.redant.apexdrivers.setting.model;
+
+import android.content.Intent;
+import android.text.TextUtils;
+
+import com.usai.redant.apexdrivers.ApexDriverApplication;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+
+public class OptionModel extends BaseModel {
+
+    public String keyPath;
+    public SettingOption option;
+    public ArrayList<SettingOption> options;
+    private JSONArray optionsJson;
+
+    public void setSelectedOption(int option) {
+
+        if (options != null && options.size() > 0) {
+            for (SettingOption op : options) {
+                if (op.option == option) {
+
+                    setOption(op);
+                    return;
+                }
+            }
+        }
+    }
+
+    public int selectedOption() {
+        if (option == null) {
+            return -1;
+        }
+        return option.option;
+    }
+
+    public void setOption(SettingOption option) {
+        this.option = option;
+
+        if (getDelegate() != null) {
+            getDelegate().refreshUI();
+        }
+
+        if (option != null && !TextUtils.isEmpty(keyPath)) {
+            ApexDriverApplication.sharedApplication().setValueForKeyPath(keyPath,option.option);
+        }
+    }
+
+    public void setKeyPath(String keyPath) {
+        this.keyPath = keyPath;
+        if (!TextUtils.isEmpty(keyPath) && options != null && options.size() > 0) {
+            for (SettingOption option : options) {
+
+
+                Object obj = ApexDriverApplication.sharedApplication().getValueForKeyPath(keyPath);
+
+                if (obj != null && obj.getClass() == Integer.class && option.option == (Integer)obj) {
+                    setOption(option);
+                }
+            }
+        }
+    }
+
+    public void setOptions(JSONArray options) {
+        optionsJson = options;
+
+        if (options != null) {
+
+            ArrayList<SettingOption> tmpArr = new ArrayList<>();
+            for (int i = 0; i < options.length(); i++) {
+                JSONObject json = options.optJSONObject(i);
+                if (json != null) {
+
+                    SettingOption option = new SettingOption();
+                    option.setValuesForKeysWithJSON(json);
+                    tmpArr.add(option);
+
+                    if (!TextUtils.isEmpty(keyPath)) {
+
+                        Object obj = ApexDriverApplication.sharedApplication().getValueForKeyPath(keyPath);
+                        if (obj != null && obj.getClass() == Integer.class && option.option == (Integer)obj) {
+                            setOption(option);
+                        }
+
+                    }
+                }
+            }
+            this.options = tmpArr;
+
+        } else {
+            this.options = null;
+        }
+    }
+
+    public String optionsJsonString() {
+        if (optionsJson == null) {
+            return null;
+        }
+        return optionsJson.toString();
+    }
+
+}

+ 73 - 0
ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/model/SectionModel.java

@@ -0,0 +1,73 @@
+package com.usai.redant.apexdrivers.setting.model;
+
+import com.usai.redant.apexdrivers.base.BasicObject;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+
+public class SectionModel extends BasicObject {
+
+    public ArrayList<BaseModel> settings;
+
+    public void setSettings(JSONArray settings) {
+        if (settings != null) {
+
+            ArrayList<BaseModel> tmpArr = new ArrayList<>();
+
+            for (int i = 0; i < settings.length(); i++) {
+
+                JSONObject json = settings.optJSONObject(i);
+                if (json != null) {
+
+
+                    int type = json.optInt("type");
+                    BaseModel model = null;
+
+                    switch (type) {
+
+                        case BaseModel.SettingTypeOption: {
+
+                            model = new OptionModel();
+                            JSONArray options = json.optJSONArray("options");
+                            if (options != null) {
+                                ((OptionModel)model).setOptions(options);
+                            }
+                        }
+                        break;
+                        case BaseModel.SettingTypeSwitch: {
+
+                            model = new SwitchModel();
+
+                        }
+                        break;
+                        case BaseModel.SettingTypeAction: {
+
+                            model = new ActionModel();
+
+                        }
+                        break;
+                        case BaseModel.SettingTypeAbout: {
+
+                           model = new AboutModel();
+                        }
+                        break;
+
+                    }
+
+                    if (model != null) {
+                        model.setValuesForKeysWithJSON(json);
+                        tmpArr.add(model);
+                    }
+
+                }
+
+            }
+
+            this.settings = tmpArr;
+        } else {
+            this.settings = null;
+        }
+    }
+}

+ 9 - 0
ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/model/SettingOption.java

@@ -0,0 +1,9 @@
+package com.usai.redant.apexdrivers.setting.model;
+
+import com.usai.redant.apexdrivers.base.BasicObject;
+
+public class SettingOption extends BasicObject {
+
+    public int option;
+    public String title;
+}

+ 7 - 0
ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/model/SwitchModel.java

@@ -0,0 +1,7 @@
+package com.usai.redant.apexdrivers.setting.model;
+
+public class SwitchModel extends BaseModel {
+
+    public String keyPath;
+    public boolean switchValue;
+}

+ 231 - 0
ApexDrivers/app/src/main/java/com/usai/redant/apexdrivers/setting/option/OptionActivity.java

@@ -0,0 +1,231 @@
+package com.usai.redant.apexdrivers.setting.option;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.usai.redant.apexdrivers.R;
+import com.usai.redant.apexdrivers.setting.model.SettingOption;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+
+public class OptionActivity extends AppCompatActivity {
+
+    private static final String OptionsKey = "OptionsKey";
+    public static final String SelectedKey = "SelectedKey";
+    private static final String SelectedIndexKey = "SelectedIndexKey";
+
+    public static void startOptionActivity(Activity activity, String optionsJson, int selectedOption, int requestCode) {
+        if (activity == null) {
+            return;
+        }
+
+        Intent intent = new Intent(activity,OptionActivity.class);
+        if (optionsJson != null) {
+            intent.putExtra(OptionsKey,optionsJson);
+        }
+        intent.putExtra(SelectedKey,selectedOption);
+
+        activity.startActivityForResult(intent,requestCode);
+    }
+
+    private Context mCtx = this;
+    private String optionsJson;
+    private int selectedOption;
+
+    private ArrayList<SettingOption> options = new ArrayList<>();
+    private int selectedIndex = -1;
+
+    private ListView mListView;
+    private OptionAdapter mAdapter;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_option);
+
+        ActionBar actionBar = getSupportActionBar();
+        if (actionBar != null) {
+            actionBar.setHomeButtonEnabled(true);
+            actionBar.setDisplayHomeAsUpEnabled(true);
+        }
+
+        if (savedInstanceState != null) {
+
+            optionsJson = savedInstanceState.getString(OptionsKey);
+            selectedIndex = savedInstanceState.getInt(SelectedIndexKey);
+
+        } else {
+            if (getIntent() != null) {
+
+                optionsJson = getIntent().getStringExtra(OptionsKey);
+                selectedOption = getIntent().getIntExtra(SelectedKey,-1);
+            }
+        }
+
+
+        if (optionsJson != null) {
+            try {
+
+                JSONArray jsonArr = new JSONArray(optionsJson);
+                for (int i = 0; i < jsonArr.length(); i++) {
+                    JSONObject json = jsonArr.optJSONObject(i);
+                    if (json != null) {
+
+                        SettingOption model = new SettingOption();
+                        model.setValuesForKeysWithJSON(json);
+
+                        if (model.option == selectedOption) {
+                            selectedIndex = i;
+                        }
+
+                        options.add(model);
+                    }
+
+                }
+
+            } catch (JSONException e) {
+                e.printStackTrace();
+            }
+        }
+
+        mAdapter = new OptionAdapter();
+        mListView = findViewById(R.id.option_list_view);
+        mListView.setAdapter(mAdapter);
+        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+
+                if (position != selectedIndex) {
+                    selectedIndex = position;
+                    mAdapter.notifyDataSetChanged();
+                }
+
+            }
+        });
+
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+
+        outState.putInt(SelectedIndexKey,selectedIndex);
+        if (optionsJson != null) {
+            outState.putString(OptionsKey,optionsJson);
+        }
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case android.R.id.home: {
+                finish();
+                return true;
+            }
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    @Override
+    public void finish() {
+
+        int selectedOption = -1;
+        if (selectedIndex >= 0) {
+            SettingOption option = options.get(selectedIndex);
+            if (option != null) {
+                selectedOption = option.option;
+            }
+        }
+
+        Intent intent = new Intent();
+        intent.putExtra(SelectedKey,selectedOption);
+        setResult(RESULT_OK,intent);
+
+        super.finish();
+    }
+
+    private class OptionAdapter extends BaseAdapter {
+
+        @Override
+        public int getCount() {
+            return options.size();
+        }
+
+        @Override
+        public Object getItem(int position) {
+            return options.get(position);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+
+            Holder holder;
+            if (convertView == null) {
+
+                convertView = LayoutInflater.from(mCtx).inflate(R.layout.option_item_cell,null);
+                holder = new Holder(convertView);
+
+            } else {
+
+                holder = (Holder)convertView.getTag();
+            }
+
+            SettingOption option = options.get(position);
+            holder.setModel(option,position);
+
+            return convertView;
+        }
+    }
+
+    private class Holder {
+
+        private TextView titleTv;
+        private ImageView markView;
+
+        Holder(View v) {
+            v.setTag(this);
+
+            titleTv = v.findViewById(R.id.option_title_tv);
+            markView = v.findViewById(R.id.option_mark_view);
+        }
+
+        public void setModel(SettingOption model, int position) {
+            if (model != null) {
+
+                titleTv.setText(model.title);
+                if (position == selectedIndex) {
+                    markView.setVisibility(View.VISIBLE);
+                } else {
+                    markView.setVisibility(View.GONE);
+                }
+
+            } else {
+
+                titleTv.setText(null);
+                markView.setVisibility(View.GONE);
+            }
+        }
+    }
+}

+ 5 - 0
ApexDrivers/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
ApexDrivers/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%" />

BIN
ApexDrivers/app/src/main/res/drawable-hdpi/icon_50.png


BIN
ApexDrivers/app/src/main/res/drawable-hdpi/redant_logo.png


BIN
ApexDrivers/app/src/main/res/drawable-ldpi/icon_50.png


BIN
ApexDrivers/app/src/main/res/drawable-ldpi/redant_logo.png


BIN
ApexDrivers/app/src/main/res/drawable-mdpi/icon_50.png


BIN
ApexDrivers/app/src/main/res/drawable-mdpi/redant_logo.png


BIN
ApexDrivers/app/src/main/res/drawable-xhdpi/icon_50.png


BIN
ApexDrivers/app/src/main/res/drawable-xhdpi/redant_logo.png


BIN
ApexDrivers/app/src/main/res/drawable-xxhdpi/icon_50.png


BIN
ApexDrivers/app/src/main/res/drawable-xxhdpi/redant_logo.png


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

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
+                 android:drawable="@drawable/action_setting"
+                 android:fromDegrees="0.0"
+                 android:pivotX="50.0%"
+                 android:pivotY="50.0%"
+                 android:toDegrees="360.0"
+    />

+ 9 - 0
ApexDrivers/app/src/main/res/drawable/change_password_dialog_round_corner_bg.xml

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

+ 16 - 0
ApexDrivers/app/src/main/res/layout/activity_option.xml

@@ -0,0 +1,16 @@
+<?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=".setting.option.OptionActivity">
+
+    <ListView
+        android:id="@+id/option_list_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        />
+
+</RelativeLayout>

+ 9 - 0
ApexDrivers/app/src/main/res/layout/activity_setting.xml

@@ -7,4 +7,13 @@
     android:layout_height="match_parent"
     tools:context=".setting.SettingActivity">
 
+    <ExpandableListView
+        android:id="@+id/setting_list_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:groupIndicator="@null"
+        android:divider="@null"
+        android:background="#e6e6e6"
+        />
+
 </android.support.constraint.ConstraintLayout>

+ 89 - 0
ApexDrivers/app/src/main/res/layout/change_password_dialog.xml

@@ -0,0 +1,89 @@
+<?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"
+    >
+
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="20dp"
+        android:layout_marginRight="20dp"
+        android:background="@drawable/change_password_dialog_round_corner_bg"
+        >
+
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textSize="18sp"
+            android:textStyle="bold"
+            android:textAlignment="center"
+            android:text="Change Password"
+            />
+
+        <EditText
+            android:layout_width="match_parent"
+            android:layout_height="40dp"
+            android:layout_margin="10dp"
+            android:hint="Old Password"
+            />
+
+        <EditText
+            android:layout_width="match_parent"
+            android:layout_height="40dp"
+            android:layout_margin="10dp"
+            android:hint="New Password"
+            />
+
+        <EditText
+            android:layout_width="match_parent"
+            android:layout_height="40dp"
+            android:layout_margin="10dp"
+            android:hint="Confirm Password"
+            />
+
+        <LinearLayout
+            android:orientation="horizontal"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            >
+
+            <RelativeLayout
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                >
+
+                <Button
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_centerInParent="true"
+                    android:text="Cancel"
+                    />
+
+            </RelativeLayout>
+
+            <RelativeLayout
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                >
+
+                <Button
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_centerInParent="true"
+                    android:text="Change"
+                    />
+
+            </RelativeLayout>
+
+
+        </LinearLayout>
+
+    </LinearLayout>
+
+
+</LinearLayout>

+ 33 - 0
ApexDrivers/app/src/main/res/layout/option_item_cell.xml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="60dp"
+        />
+
+    <TextView
+        android:id="@+id/option_title_tv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"
+        android:layout_alignParentLeft="true"
+        android:layout_marginLeft="10dp"
+        android:textColor="#000000"
+        android:textSize="17sp"
+        android:text="Title"
+        />
+
+    <ImageView
+        android:id="@+id/option_mark_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"
+        android:layout_alignParentRight="true"
+        android:layout_marginRight="10dp"
+        android:src="@drawable/action_setting"
+        />
+
+</RelativeLayout>

+ 84 - 0
ApexDrivers/app/src/main/res/layout/setting_about_cell.xml

@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingBottom="10dp"
+                android:background="@color/ApexDriverWhite"
+    >
+
+    <ImageView
+        android:id="@+id/setting_about_icon_view"
+        android:layout_width="50dp"
+        android:layout_height="50dp"
+        android:layout_alignParentLeft="true"
+        android:layout_margin="10dp"
+        android:src="@drawable/icon_50"
+        />
+
+    <TextView
+        android:id="@+id/setting_about_name_tv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_toRightOf="@id/setting_about_icon_view"
+        android:layout_alignTop="@id/setting_about_icon_view"
+        android:layout_marginLeft="5dp"
+        android:layout_marginBottom="5dp"
+        android:textColor="#000000"
+        android:textSize="20sp"
+        android:textStyle="bold"
+        android:text="Apex Drivers"
+        />
+
+    <TextView
+        android:id="@+id/setting_about_ver_tv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_toRightOf="@id/setting_about_icon_view"
+        android:layout_below="@id/setting_about_name_tv"
+        android:layout_alignLeft="@id/setting_about_name_tv"
+        android:textColor="#000000"
+        android:textSize="18sp"
+        android:text="Ver:1.0 build 180913"
+        />
+
+
+    <ImageView
+        android:id="@+id/setting_about_redant_view"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:layout_alignParentLeft="true"
+        android:layout_below="@id/setting_about_icon_view"
+        android:layout_alignLeft="@id/setting_about_icon_view"
+        android:layout_marginTop="5dp"
+        android:layout_marginLeft="10dp"
+        android:src="@drawable/redant_logo"
+        />
+
+    <TextView
+        android:id="@+id/setting_about_surpport_tv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_toRightOf="@id/setting_about_redant_view"
+        android:layout_alignTop="@id/setting_about_redant_view"
+        android:layout_alignLeft="@id/setting_about_name_tv"
+        android:layout_marginBottom="5dp"
+        android:textColor="#000000"
+        android:textSize="18sp"
+        android:textStyle="bold"
+        android:text="Support:"
+        />
+
+    <TextView
+        android:id="@+id/setting_about_surpport_value_tv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_toRightOf="@id/setting_about_redant_view"
+        android:layout_below="@id/setting_about_surpport_tv"
+        android:layout_alignLeft="@id/setting_about_surpport_tv"
+        android:textColor="#000000"
+        android:textSize="16sp"
+        android:autoLink="email"
+        android:text="redantsupport@united-us.net"
+        />
+
+</RelativeLayout>

+ 37 - 0
ApexDrivers/app/src/main/res/layout/setting_action_cell.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="60dp"
+                android:background="@color/ApexDriverWhite">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="60dp"
+        android:background="#00000000"
+        />
+
+    <TextView
+        android:id="@+id/setting_action_title_tv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"
+        android:layout_alignParentLeft="true"
+        android:layout_marginLeft="10dp"
+        android:textColor="#000000"
+        android:textSize="17sp"
+        android:text="Title"
+        />
+
+    <ProgressBar
+        android:id="@+id/setting_action_indicator_view"
+        android:layout_width="30dp"
+        android:layout_height="30dp"
+        android:layout_centerVertical="true"
+        android:layout_alignParentRight="true"
+        android:layout_marginRight="10dp"
+        android:layout_gravity="center_horizontal"
+        android:indeterminateBehavior="repeat"
+        android:indeterminateDrawable="@drawable/animate"
+        />
+
+</RelativeLayout>

+ 48 - 0
ApexDrivers/app/src/main/res/layout/setting_option_cell.xml

@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="60dp"
+                android:background="@color/ApexDriverWhite">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="60dp"
+        android:background="#00000000"
+        />
+
+    <TextView
+        android:id="@+id/setting_option_title_tv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"
+        android:layout_alignParentLeft="true"
+        android:layout_marginLeft="10dp"
+        android:textColor="#000000"
+        android:textSize="17sp"
+        android:text="Title"
+        />
+
+    <ImageView
+        android:id="@+id/setting_option_detail_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"
+        android:layout_alignParentRight="true"
+        android:layout_marginRight="10dp"
+        />
+
+    <TextView
+        android:id="@+id/setting_option_value_tv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"
+        android:layout_marginLeft="5dp"
+        android:layout_marginRight="5dp"
+        android:layout_toLeftOf="@id/setting_option_detail_view"
+        android:textColor="#000000"
+        android:textSize="15sp"
+        android:text="Reject"
+        />
+
+
+</RelativeLayout>

+ 14 - 0
ApexDrivers/app/src/main/res/layout/setting_section_header.xml

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="25dp"
+    android:background="#00000000"
+    >
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="25dp"
+        android:background="#00000000"
+        />
+
+</RelativeLayout>

+ 34 - 0
ApexDrivers/app/src/main/res/layout/setting_switch_cell.xml

@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="60dp"
+                android:background="@color/ApexDriverWhite">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="60dp"
+        android:background="#00000000"
+        />
+
+    <TextView
+        android:id="@+id/setting_switch_title_tv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"
+        android:layout_alignParentLeft="true"
+        android:layout_marginLeft="10dp"
+        android:textColor="#000000"
+        android:textSize="17sp"
+        android:text="Title"
+        />
+
+    <Switch
+        android:id="@+id/setting_action_switch_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"
+        android:layout_alignParentRight="true"
+        android:layout_marginRight="10dp"
+        />
+
+</RelativeLayout>

+ 53 - 0
ApexDrivers/app/src/main/res/raw/setting.json

@@ -0,0 +1,53 @@
+{
+    "sections": [
+                 {
+                 "settings": [
+                              {
+                              "type": 0,
+                              "keyPath": "backgroundReportType",
+                              "title": "Background Location",
+                              "options": [
+                                          {
+                                          "option": 1,
+                                          "title": "Reject"
+                                          },
+                                          {
+                                          "option": 2,
+                                          "title": "Always ask"
+                                          },
+                                          {
+                                          "option": 3,
+                                          "title": "Allow"
+                                          }
+                                          ]
+                              }
+                              ]
+                 },
+                 {
+                 "settings": [
+                              {
+                              "type": 2,
+                              "actionType": 1,
+                              "title": "Change Password"
+                              }
+                              ]
+                 },
+                 {
+                 "settings": [
+                              {
+                              "type": 2,
+                              "actionType": 0,
+                              "title": "Clean Cache"
+                              }
+                              ]
+                 },
+                 {
+                 "settings": [
+                              {
+                              "type": 3,
+                              "title": "About"
+                              }
+                              ]
+                 }
+                 ]
+}

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

@@ -36,6 +36,28 @@
 
     </style>
 
+    <style name="changePasswordDialog" 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>
+    <!-- ActionSheet进出动画 -->
+    <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>