Răsfoiți Sursa

Organize the permission statement -- 整理权限申明(resolve: #14499)

Ray Zhang 4 ani în urmă
părinte
comite
25fc34739c
67 a modificat fișierele cu 10640 adăugiri și 0 ștergeri
  1. 1 0
      ApexDrivers/CommonEditorLib/.gitignore
  2. 37 0
      ApexDrivers/CommonEditorLib/build.gradle
  3. 0 0
      ApexDrivers/CommonEditorLib/consumer-rules.pro
  4. 21 0
      ApexDrivers/CommonEditorLib/proguard-rules.pro
  5. 28 0
      ApexDrivers/CommonEditorLib/src/androidTest/java/com/example/commoneditorlib/ExampleInstrumentedTest.java
  6. 5 0
      ApexDrivers/CommonEditorLib/src/main/AndroidManifest.xml
  7. 55 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/AddressEditorActivity.java
  8. 14 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/Application.java
  9. 204 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/BrushView.java
  10. 191 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/BundleItemDialog.java
  11. 161 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/BundleModelActivity.java
  12. 27 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorActionCellHolder.java
  13. 161 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorAutoCompleteAdapter.java
  14. 36 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorCellHolder.java
  15. 82 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorDateRangeCellHolder.java
  16. 36 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorEditAutoCompleteCellHolder.java
  17. 32 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorEditCellHolder.java
  18. 33 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorEnumCellHolder.java
  19. 125 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorImageCellHolder.java
  20. 34 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorLabelCellHolder.java
  21. 69 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorModelCellHolder.java
  22. 31 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorMultipleActionCellHolder.java
  23. 195 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorRangeCellHolder.java
  24. 69 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorSectionHeaderHolder.java
  25. 30 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorSignatureCellHolder.java
  26. 32 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorSwitchCellHolder.java
  27. 44 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorTextViewCellHolder.java
  28. 4776 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditorActivity.java
  29. 59 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/ContactListActivity.java
  30. 66 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CreditCardEditorActivity.java
  31. 61 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/DatePickerActivity.java
  32. 343 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/EnumSelectAndSort/DragListView.java
  33. 642 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/EnumSelectAndSort/EnumSelectAndSortActivity.java
  34. 506 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/EnumSlectActivity.java
  35. 204 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/ImageUploadActivity.java
  36. 16 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/ImageViewActivity.java
  37. 113 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/MonthPickerActivity.java
  38. 93 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/SignatureActivity.java
  39. 314 0
      ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/Utils.java
  40. 21 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/activity_address_editor.xml
  41. 18 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_action_cell.xml
  42. 18 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_auto_complete_list_cell.xml
  43. 100 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_date_range_cell.xml
  44. 63 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_edit_auto_complete_cell.xml
  45. 66 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_edit_auto_complete_cell_small.xml
  46. 63 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_edit_cell.xml
  47. 66 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_edit_cell_small.xml
  48. 90 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_enum_cell.xml
  49. 90 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_enum_cell_small.xml
  50. 67 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_image_cell.xml
  51. 79 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_image_cell_small.xml
  52. 43 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_label_cell.xml
  53. 43 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_label_cell_small.xml
  54. 204 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_model_cell.xml
  55. 62 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_multiple_action_cell.xml
  56. 100 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_range_cell.xml
  57. 44 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_section_header.xml
  58. 58 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_signature_cell.xml
  59. 58 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_signature_cell_small.xml
  60. 50 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_switch_cell.xml
  61. 68 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_switch_cell_small.xml
  62. 59 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_text_view_cell.xml
  63. 59 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_text_view_cell_small.xml
  64. 37 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/enum_select_cell.xml
  65. 48 0
      ApexDrivers/CommonEditorLib/src/main/res/layout/enum_select_sort_cell.xml
  66. 19 0
      ApexDrivers/CommonEditorLib/src/test/java/com/example/commoneditorlib/ExampleUnitTest.java
  67. 1 0
      ApexDrivers/settings.gradle

+ 1 - 0
ApexDrivers/CommonEditorLib/.gitignore

@@ -0,0 +1 @@
+/build

+ 37 - 0
ApexDrivers/CommonEditorLib/build.gradle

@@ -0,0 +1,37 @@
+plugins {
+    id 'com.android.library'
+}
+
+android {
+    compileSdkVersion 29
+
+    defaultConfig {
+        minSdkVersion 26
+        targetSdkVersion 29
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+        consumerProguardFiles "consumer-rules.pro"
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+}
+
+dependencies {
+
+    implementation 'androidx.appcompat:appcompat:1.3.0'
+    implementation 'com.google.android.material:material:1.4.0'
+    testImplementation 'junit:junit:4.+'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+}

+ 0 - 0
ApexDrivers/CommonEditorLib/consumer-rules.pro


+ 21 - 0
ApexDrivers/CommonEditorLib/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 28 - 0
ApexDrivers/CommonEditorLib/src/androidTest/java/com/example/commoneditorlib/ExampleInstrumentedTest.java

@@ -0,0 +1,28 @@
+package com.example.commoneditorlib;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest
+{
+    @Test
+    public void useAppContext()
+    {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        assertEquals("com.example.commoneditorlib.test", appContext.getPackageName());
+    }
+}

+ 5 - 0
ApexDrivers/CommonEditorLib/src/main/AndroidManifest.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.commoneditorlib">
+
+</manifest>

+ 55 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/AddressEditorActivity.java

@@ -0,0 +1,55 @@
+package com.example.commoneditorlib;
+
+import android.content.Context;
+import android.content.Intent;
+//import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+//import com.usai.redant.redantmobile.R;
+
+public class AddressEditorActivity extends AppCompatActivity
+{
+
+
+    static String URL_TYPE = "url_type";
+    static String REQUEST_URL = "request_url";
+    static String IS_SUBACTION = "is_subaction";
+    static String SUBACTION_TAG = "subaction_tag";
+    static String GROUP = "group";
+    static String CHILD = "child";
+    static String RETURN_VALUE = "return_value";
+
+    public static class Builder {
+
+        public Intent build(Context ctx,int url_type,String request_url,String is_subaction,String subaction_tag,int group,int child) {
+            if (ctx == null) {
+                return null;
+            }
+            Intent intent = new Intent(ctx,AddressEditorActivity.class);
+
+            intent.putExtra(URL_TYPE ,url_type);
+
+            if (request_url != null) {
+                intent.putExtra(REQUEST_URL,request_url);
+            }
+            if (is_subaction != null) {
+                intent.putExtra(IS_SUBACTION,is_subaction);
+            }
+            if (subaction_tag != null) {
+                intent.putExtra(SUBACTION_TAG,subaction_tag);
+            }
+            intent.putExtra(GROUP,group);
+            intent.putExtra(CHILD,child);
+
+            return intent;
+        }
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_address_editor);
+    }
+}

+ 14 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/Application.java

@@ -0,0 +1,14 @@
+package com.example.commoneditorlib;
+
+import org.json.JSONObject;
+
+/**
+ * Created by macmini1 on 2017/8/22.
+ */
+
+public class Application {
+
+    public static JSONObject customerInfo;
+    public static String order_code;
+
+}

+ 204 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/BrushView.java

@@ -0,0 +1,204 @@
+package com.example.commoneditorlib;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.BitmapRegionDecoder;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Created by macmini1 on 2017/8/31.
+ */
+
+public class BrushView extends View {
+
+
+    private Paint brush = new Paint();
+    private Path path = new Path();
+
+    private float minX;
+    private float minY;
+    private float maxX;
+    private float maxY;
+    private float lineWidth;
+
+    public BrushView(Context context) {
+        this(context,null);
+    }
+
+    public BrushView(Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs,0);
+    }
+
+    public BrushView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+
+        lineWidth = 10.f;
+        init();
+    }
+
+
+    private void init() {
+
+        // fix saved jpg file seen black
+        // 没有颜色的位置默认使用的是白色的替代的,但是保存成png后,没有颜色的位置使用的是黑色替代的,所以会看到生成的图片是全黑的。
+        setBackgroundColor(Color.WHITE);
+
+        // 抗锯齿
+        brush.setAntiAlias(true);
+        brush.setColor(Color.BLACK);
+        brush.setStyle(Paint.Style.STROKE);
+        brush.setStrokeJoin(Paint.Join.ROUND);
+        brush.setStrokeWidth(lineWidth);
+        brush.setStrokeCap(Paint.Cap.ROUND); // 线条两端圆角
+
+        minX = Float.MAX_VALUE;
+        minY = Float.MAX_VALUE;
+
+        maxX = Float.MIN_VALUE;
+        maxY = Float.MIN_VALUE;
+
+
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+
+        float x = event.getX();
+        float y = event.getY();
+
+
+
+        switch (event.getAction()) {
+            case MotionEvent.ACTION_DOWN: {
+                path.moveTo(x,y);
+                checkPoin(x,y);
+                return true;
+            }
+
+            case MotionEvent.ACTION_MOVE: {
+                path.lineTo(x,y);
+                checkPoin(x,y);
+                ispainted = true;
+            }
+            break;
+            case MotionEvent.ACTION_UP:
+                break;
+            default:
+            return false;
+        }
+
+        postInvalidate();
+
+        return false;
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        canvas.drawPath(path,brush);
+
+    }
+
+    private void checkPoin(float x,float y) {
+
+        if (x < minX) {
+            minX = x;
+        }
+
+        if (y < minY) {
+            minY = y;
+        }
+
+        if (x > maxX) {
+            maxX = x;
+        }
+
+        if (y > maxY) {
+            maxY = y;
+        }
+
+
+    }
+
+    public void setBrushColor(int color) {
+        brush.setColor(color);
+    }
+
+    public void setLineWidth(float width) {
+        brush.setStrokeWidth(width);
+    }
+
+    public void clear() {
+
+        ispainted = false;
+        path.reset();
+        postInvalidate();
+
+    }
+
+    private boolean ispainted = false;
+
+    public boolean checkCanSave() {
+
+        return ispainted;
+    }
+
+    public Bitmap getDrawBitmap() {
+
+//        setDrawingCacheEnabled(true);
+//        buildDrawingCache();
+//        Bitmap b = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
+//        Canvas c = new Canvas(b);
+//        draw(c);
+//        Bitmap bitmap = b;
+
+
+        setDrawingCacheEnabled(true);
+        buildDrawingCache();
+        Bitmap bitmap = getDrawingCache();
+
+        // 裁剪绘图区域
+        String path = Utils.cacheTmpImage(bitmap);
+
+        int width = getWidth();
+        int height = getHeight();
+
+        // 裁剪区域,默认原图
+        Rect cropRect = new Rect(0, 0, width, height);
+
+        try {
+            final Matrix outputMatrix = new Matrix();//用于最图图片的精确缩放
+            InputStream inputStream = new FileInputStream(path);
+            final BitmapFactory.Options ops = new BitmapFactory.Options();
+            BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(inputStream, false);
+
+            cropRect.left = (int) (minX - lineWidth * 0.5);
+            cropRect.top = (int) (minY - lineWidth * 0.5);
+            cropRect.right = (int) (maxX + lineWidth * 0.5);
+            cropRect.bottom = (int) (maxY + lineWidth * 0.5);
+
+            final Bitmap source = decoder.decodeRegion(cropRect, ops);
+            return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), outputMatrix, false);
+
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return bitmap;
+
+    }
+
+}

+ 191 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/BundleItemDialog.java

@@ -0,0 +1,191 @@
+package com.example.commoneditorlib;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.StyleRes;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.usai.redant.redantmobile.R;
+
+import org.json.JSONObject;
+
+import java.util.List;
+
+
+public class BundleItemDialog extends Dialog {
+
+    public Context mCtx;
+    private ListView item_list;
+    public BundleItemDialog(@NonNull Context context) {
+        super(context);
+        mCtx = context;
+    }
+
+    public BundleItemDialog(@NonNull Context context, @StyleRes int themeResId) {
+        super(context, themeResId);
+        mCtx = context;
+    }
+
+    protected BundleItemDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) {
+        super(context, cancelable, cancelListener);
+        mCtx = context;
+    }
+
+    private JSONObject items_json;
+    public BundleItemDialog setItems(String items) {
+
+        if (items != null || !items.isEmpty()) {
+
+            try {
+
+                items_json = new JSONObject(items);
+
+                if (item_list != null) {
+                    item_list.setAdapter(new Adapter());
+                }
+
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+
+        }
+
+        return this;
+    }
+
+    public static class Builder {
+
+        public  BundleItemDialog build(Context context) {
+            final BundleItemDialog dialog = new BundleItemDialog(context, R.style.AppTheme);
+            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+            View layout = inflater.inflate(R.layout.activity_bundle_model,null);
+            dialog.addContentView(layout, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+
+            dialog.item_list = (ListView) layout.findViewById(R.id.bundle_list_view);
+
+            return dialog;
+        }
+
+    }
+
+    public class Adapter extends BaseAdapter {
+
+        /**
+         * How many items are in the data set represented by this Adapter.
+         *
+         * @return Count of items.
+         */
+        @Override
+        public int getCount() {
+            if (items_json != null) {
+                int count = items_json.optInt("count");
+                return count;
+            }
+            return 0;
+        }
+
+        /**
+         * Get the data item associated with the specified position in the data set.
+         *
+         * @param position Position of the item whose data we want within the adapter's
+         *                 data set.
+         * @return The data at the specified position.
+         */
+        @Override
+        public Object getItem(int position) {
+            if (items_json != null) {
+                return items_json.optJSONObject("item_" + position);
+            }
+            return null;
+        }
+
+        /**
+         * Get the row id associated with the specified position in the list.
+         *
+         * @param position The position of the item within the adapter's data set whose row id we want.
+         * @return The id of the item at the specified position.
+         */
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        /**
+         * Get a View that displays the data at the specified position in the data set. You can either
+         * create a View manually or inflate it from an XML layout file. When the View is inflated, the
+         * parent View (GridView, ListView...) will apply default layout parameters unless you use
+         * {@link LayoutInflater#inflate(int, ViewGroup, boolean)}
+         * to specify a root view and to prevent attachment to the root.
+         *
+         * @param position    The position of the item within the adapter's data set of the item whose view
+         *                    we want.
+         * @param convertView The old view to reuse, if possible. Note: You should check that this view
+         *                    is non-null and of an appropriate type before using. If it is not possible to convert
+         *                    this view to display the correct data, this method can create a new view.
+         *                    Heterogeneous lists can specify their number of view types, so that this View is
+         *                    always of the right type (see {@link #getViewTypeCount()} and
+         *                    {@link #getItemViewType(int)}).
+         * @param parent      The parent that this view will eventually be attached to
+         * @return A View corresponding to the data at the specified position.
+         */
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+
+            BundleItemHolder holder;
+
+            if (convertView == null) {
+
+                convertView = LayoutInflater.from(mCtx).inflate(R.layout.bundle_item_cell,null);
+                holder = new BundleItemHolder(convertView);
+
+            } else {
+                holder = (BundleItemHolder) convertView.getTag();
+            }
+
+            JSONObject item_json = (JSONObject) getItem(position);
+            if (item_json != null) {
+                holder.name_tv.setText(item_json.optString("model"));
+                if (item_json.optString("unit_price").equals("No Price")) {
+                    holder.up_tv.setText("No Price");
+                } else {
+                    holder.up_tv.setText(String.format("$ %.2f",Float.valueOf(item_json.optString("unit_price"))));
+                }
+                holder.qty_tv.setText(item_json.optString("modulus"));
+
+                holder.desc_tv.setText(item_json.optString("description"));
+            }
+
+
+            return convertView;
+        }
+
+        public class BundleItemHolder {
+
+            public TextView name_tv;
+            public TextView desc_tv;
+            public TextView qty_tv;
+            public TextView up_tv;
+
+            public BundleItemHolder(View cell) {
+                name_tv = (TextView) cell.findViewById(R.id.model_name_tv);
+                desc_tv = (TextView) cell.findViewById(R.id.model_desc_tv);
+                qty_tv = (TextView) cell.findViewById(R.id.model_qty_tv);
+                up_tv = (TextView) cell.findViewById(R.id.model_unit_price_tv);
+                cell.setTag(this);
+            }
+
+        }
+    }
+
+
+
+}

+ 161 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/BundleModelActivity.java

@@ -0,0 +1,161 @@
+package com.example.commoneditorlib;
+
+import android.content.Context;
+import android.content.Intent;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+
+import com.usai.redant.redantmobile.R;
+
+import org.json.JSONObject;
+
+public class BundleModelActivity extends AppCompatActivity {
+
+
+    private JSONObject items_json;
+    private ListView item_list;
+    private Context mCtx = this;
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_bundle_model);
+
+        setTitle("Bundle");
+        item_list = (ListView) findViewById(R.id.bundle_list_view);
+
+        Intent intent = getIntent();
+        String items = intent.getStringExtra("bundle_items");
+        if (items != null || !items.isEmpty()) {
+            try {
+
+                items_json = new JSONObject(items);
+
+                if (item_list != null) {
+                    item_list.setAdapter(new Adapter());
+                }
+
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+    }
+
+
+    public class Adapter extends BaseAdapter {
+
+        /**
+         * How many items are in the data set represented by this Adapter.
+         *
+         * @return Count of items.
+         */
+        @Override
+        public int getCount() {
+            if (items_json != null) {
+                int count = items_json.optInt("count");
+                return count;
+            }
+            return 0;
+        }
+
+        /**
+         * Get the data item associated with the specified position in the data set.
+         *
+         * @param position Position of the item whose data we want within the adapter's
+         *                 data set.
+         * @return The data at the specified position.
+         */
+        @Override
+        public Object getItem(int position) {
+            if (items_json != null) {
+                return items_json.optJSONObject("item_" + position);
+            }
+            return null;
+        }
+
+        /**
+         * Get the row id associated with the specified position in the list.
+         *
+         * @param position The position of the item within the adapter's data set whose row id we want.
+         * @return The id of the item at the specified position.
+         */
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        /**
+         * Get a View that displays the data at the specified position in the data set. You can either
+         * create a View manually or inflate it from an XML layout file. When the View is inflated, the
+         * parent View (GridView, ListView...) will apply default layout parameters unless you use
+         * {@link LayoutInflater#inflate(int, ViewGroup, boolean)}
+         * to specify a root view and to prevent attachment to the root.
+         *
+         * @param position    The position of the item within the adapter's data set of the item whose view
+         *                    we want.
+         * @param convertView The old view to reuse, if possible. Note: You should check that this view
+         *                    is non-null and of an appropriate type before using. If it is not possible to convert
+         *                    this view to display the correct data, this method can create a new view.
+         *                    Heterogeneous lists can specify their number of view types, so that this View is
+         *                    always of the right type (see {@link #getViewTypeCount()} and
+         *                    {@link #getItemViewType(int)}).
+         * @param parent      The parent that this view will eventually be attached to
+         * @return A View corresponding to the data at the specified position.
+         */
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+
+            BundleItemHolder holder;
+
+            if (convertView == null) {
+
+                convertView = LayoutInflater.from(mCtx).inflate(R.layout.bundle_item_cell,null);
+                holder = new BundleItemHolder(convertView);
+
+            } else {
+                holder = (BundleItemHolder) convertView.getTag();
+            }
+
+            JSONObject item_json = (JSONObject) getItem(position);
+            if (item_json != null) {
+                holder.name_tv.setText(item_json.optString("model"));
+                if (item_json.optString("unit_price").equals("No Price")) {
+                    holder.up_tv.setText("No Price");
+                } else {
+                    holder.up_tv.setText(String.format("$ %.2f",Float.valueOf(item_json.optString("unit_price"))));
+                }
+                holder.qty_tv.setText(item_json.optString("modulus"));
+
+                holder.desc_tv.setText(item_json.optString("description"));
+            }
+
+
+            return convertView;
+        }
+
+        public class BundleItemHolder {
+
+            public TextView name_tv;
+            public TextView desc_tv;
+            public TextView qty_tv;
+            public TextView up_tv;
+
+            public BundleItemHolder(View cell) {
+                name_tv = (TextView) cell.findViewById(R.id.model_name_tv);
+                desc_tv = (TextView) cell.findViewById(R.id.model_desc_tv);
+                qty_tv = (TextView) cell.findViewById(R.id.model_qty_tv);
+                up_tv = (TextView) cell.findViewById(R.id.model_unit_price_tv);
+                cell.setTag(this);
+            }
+
+        }
+    }
+
+}

+ 27 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorActionCellHolder.java

@@ -0,0 +1,27 @@
+package com.example.commoneditorlib.CommonEditor;
+
+
+import android.content.Context;
+import android.view.View;
+import android.widget.TextView;
+
+
+import com.usai.redant.redantmobile.R;
+
+import org.json.JSONObject;
+
+public class CommonEditorActionCellHolder extends CommonEditorCellHolder {
+
+    public TextView action_lb;
+    public String action_code;
+
+    public CommonEditorActionCellHolder(Context context,View view) {
+        super(context,view);
+        action_lb = (TextView) view.findViewById(R.id.action_cell_lb);
+    }
+
+    @Override
+    public void setItem(JSONObject item_json, boolean readonly, View view) {
+        super.setItem(item_json, readonly, view);
+    }
+}

+ 161 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorAutoCompleteAdapter.java

@@ -0,0 +1,161 @@
+package com.example.commoneditorlib.CommonEditor;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.BaseAdapter;
+import android.widget.Filter;
+import android.widget.Filterable;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by macmini1 on 2017/12/18.
+ */
+
+public class CommonEditorAutoCompleteAdapter extends ArrayAdapter implements Filterable {
+
+    private Context context;
+    private List<String> list = new ArrayList<>();
+    private int resourceId, textViewId;
+
+    public CommonEditorAutoCompleteAdapter(Context context, int resourceId, int textViewId) {
+        super(context,resourceId,textViewId);
+        this.context = context;
+        this.resourceId = resourceId;
+        this.textViewId = textViewId;
+    }
+
+    private String[] arr;
+    public void addObjects(String[] arr) {
+        this.arr = arr;
+        addAll((Object[]) arr);
+    }
+
+    @Override
+    public void clear() {
+        arr = null;
+        super.clear();
+    }
+
+    @Override
+    public Filter getFilter() {
+        Filter filter = new Filter() {
+            /**
+             * 在后台线程执行,定义过滤算法
+             * @param constraint :就是你在输入框输入的字符串
+             * @return 符合条件的数据结果,会在下面的publishResults方法中将数据传给list
+             */
+            @Override
+            protected FilterResults performFiltering(CharSequence constraint) {
+                FilterResults results = new FilterResults();
+
+                int count = getCount();
+                if (constraint == null || constraint.length() == 0 || count == 0) {
+                    //
+                    results.values = null;
+                    results.count = 0;
+                } else {
+                    //这个newList是实际搜索出的结果集合,实际上是将该newList的数据赋给了list
+                    List<String> newList = new ArrayList<>();
+
+                    for (int i = 0; i < count; i++) {
+                        String s = (String) getItem(i);
+                        //包含就添加到newList中
+                        if (s.contains(constraint.toString().trim())) {
+                            newList.add(s);
+                        }
+                    }
+
+                    //将newList传给results
+                    results.values = newList;
+                    results.count = newList.size();
+                    newList = null;
+                }
+                return results;
+            }
+
+            /**
+             * 本方法在UI线程执行,用于更新自动完成列表
+             * @param constraint
+             * @param results
+             */
+            @Override
+            protected void publishResults(CharSequence constraint, FilterResults results) {
+
+                Log.d("Auto Complete Adapter", "publishResults: " + results.count);
+
+                if (results != null && results.count > 0) {//有符合过滤规则的数据
+                    list.clear();
+                    list.addAll((List<String>) results.values);
+                    notifyDataSetChanged();
+                } else {//没有符合过滤规则的数据
+                    clear();
+                    notifyDataSetInvalidated();
+                }
+            }
+
+            /**
+             * 将符合条件的数据转换为你想要的方式,一般无需实现
+             * 控制用户点击提示时要填充至输入框的文本内容。
+             */
+            @Override
+            public CharSequence convertResultToString(Object resultValue) {
+                return super.convertResultToString(resultValue);
+                //假如这里写 return "啊哈哈";
+                //那么,无论你点击哪个条目,出现在输入框的永远是"啊哈哈"这几个字。
+            }
+        };
+        return filter;
+    }
+
+    @Override
+    public int getCount() {
+
+        if (arr != null) {
+            return arr.length;
+        } else {
+            return 0;
+        }
+    }
+
+    /**
+     * 这里必须返回list.get(position),否则点击条目后输入框显示的是position,而非该position的数据
+     *
+     * @param position
+     * @return
+     */
+    @Override
+    public Object getItem(int position) {
+        return arr[position];
+    }
+    @Override
+    public long getItemId(int position) {
+        return position;
+    }
+    @Override
+    public View getView(final int position, View convertView, ViewGroup parent) {
+        TvViewHolder holder;
+        if (convertView == null) {
+            convertView = View.inflate(context, resourceId, null);
+            holder = new TvViewHolder();
+            holder.tv = (TextView) convertView.findViewById(textViewId);
+            convertView.setTag(holder);
+        } else {
+            holder = (TvViewHolder) convertView.getTag();
+        }
+        //注意这里不要为convertView添加点击事件,默认是点击后:①下拉窗收起;
+        //②点击的条目数据会显示在搜索框中;③光标定位到字符串末位。
+        //如果自己添加点击事件,就要首先实现上面的①、②、③。
+
+        holder.tv.setText((String) getItem(position));
+        return convertView;
+    }
+    class TvViewHolder {
+        TextView tv;
+    }
+}

+ 36 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorCellHolder.java

@@ -0,0 +1,36 @@
+package com.example.commoneditorlib.CommonEditor;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.TextView;
+
+
+//import com.usai.redant.redantmobile.R;
+
+import com.example.commoneditorlib.R;
+
+import org.json.JSONObject;
+
+
+public class CommonEditorCellHolder {
+
+    public Context mCtx;
+    public TextView startMark;
+    public int group;
+    public int child;
+
+    public CommonEditorCellHolder(Context context,View view) {
+        mCtx = context;
+        startMark = (TextView) view.findViewById(R.id.start_mark);
+        view.setTag(this);
+        if (startMark != null) {
+            startMark.setVisibility(View.INVISIBLE);
+        }
+    }
+
+    public void setItem(JSONObject item_json,boolean readonly,View view) {
+
+    }
+
+
+}

+ 82 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorDateRangeCellHolder.java

@@ -0,0 +1,82 @@
+package com.example.commoneditorlib.CommonEditor;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.usai.redant.CommonEditor.CommonEditorActivity;
+import com.usai.redant.CommonEditor.DatePickerActivity;
+import com.usai.redant.redantmobile.R;
+
+import org.json.JSONObject;
+
+/**
+ * Created by macmini1 on 2017/12/13.
+ */
+
+public class CommonEditorDateRangeCellHolder extends CommonEditorCellHolder {
+
+    public TextView title_lb;
+    public Button min_btn;
+    public Button max_btn;
+    public Button reset_btn;
+    public DateButtonClickListener clickListener;
+
+    public CommonEditorDateRangeCellHolder(Context context, View view) {
+        super(context, view);
+
+        title_lb = view.findViewById(R.id.range_title_tv);
+        min_btn = view.findViewById(R.id.range_minimum_btn);
+        max_btn = view.findViewById(R.id.range_maximum_btn);
+        reset_btn = view.findViewById(R.id.range_reset_btn);
+
+        clickListener = new DateButtonClickListener();
+        min_btn.setOnClickListener(clickListener);
+        max_btn.setOnClickListener(clickListener);
+
+        reset_btn.setOnClickListener(new ResetClickListener());
+
+    }
+
+    private class ResetClickListener implements View.OnClickListener {
+
+        @Override
+        public void onClick(View view) {
+            ((CommonEditorActivity)mCtx).commonEditorRangeDidChange("","",group,child);
+        }
+    }
+
+
+
+    @Override
+    public void setItem(JSONObject item_json, boolean readonly, View view) {
+        super.setItem(item_json, readonly, view);
+    }
+
+    public class DateButtonClickListener implements View.OnClickListener {
+
+        @Override
+        public void onClick(View view) {
+
+            Intent intent = new Intent(mCtx, DatePickerActivity.class);
+
+            intent.putExtra("group",group);
+            intent.putExtra("child",child);
+
+            if (view.equals(min_btn)) {
+                intent.putExtra("value","min");
+            } else {
+                intent.putExtra("value","max");
+            }
+
+            intent.putExtra("min",min_btn.getText().toString());
+            intent.putExtra("max",max_btn.getText().toString());
+
+            ((Activity)mCtx).startActivityForResult(intent,14);
+
+        }
+    }
+}

+ 36 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorEditAutoCompleteCellHolder.java

@@ -0,0 +1,36 @@
+package com.example.commoneditorlib.CommonEditor;
+
+import android.content.Context;
+
+import android.view.View;
+import android.widget.AutoCompleteTextView;
+
+import android.widget.TextView;
+
+import com.usai.redant.redantmobile.R;
+
+import org.json.JSONObject;
+
+
+
+public class CommonEditorEditAutoCompleteCellHolder extends CommonEditorEditCellHolder {
+
+//    public TextView name_lb;
+    public AutoCompleteTextView text_field;
+    public CommonEditorAutoCompleteAdapter autoCompleteAdapter;
+    public String thread_identifier;
+
+
+    public CommonEditorEditAutoCompleteCellHolder(Context context, View view) {
+        super(context,view);
+
+        name_lb = (TextView) view.findViewById(R.id.name_lb);
+        text_field = (AutoCompleteTextView) view.findViewById(R.id.textField);
+
+    }
+
+    @Override
+    public void setItem(JSONObject item_json, boolean readonly, View view) {
+        super.setItem(item_json, readonly, view);
+    }
+}

+ 32 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorEditCellHolder.java

@@ -0,0 +1,32 @@
+package com.example.commoneditorlib.CommonEditor;
+
+import android.content.Context;
+import android.text.TextWatcher;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.TextView;
+
+
+import com.usai.redant.redantmobile.R;
+
+import org.json.JSONObject;
+
+
+public class CommonEditorEditCellHolder extends CommonEditorCellHolder {
+
+    public TextView name_lb;
+    public EditText text_field;
+    public TextWatcher textWatcher;
+
+    public CommonEditorEditCellHolder(Context context, View view) {
+        super(context,view);
+        name_lb = (TextView) view.findViewById(R.id.name_lb);
+        text_field = (EditText) view.findViewById(R.id.textField);
+
+    }
+
+    @Override
+    public void setItem(JSONObject item_json, boolean readonly, View view) {
+        super.setItem(item_json, readonly, view);
+    }
+}

+ 33 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorEnumCellHolder.java

@@ -0,0 +1,33 @@
+package com.example.commoneditorlib.CommonEditor;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.TextView;
+
+
+import com.usai.redant.redantmobile.R;
+
+import org.json.JSONObject;
+
+/**
+ * Created by macmini1 on 2017/8/16.
+ */
+
+public class CommonEditorEnumCellHolder extends CommonEditorCellHolder {
+
+    public TextView title_lb;
+    public TextView value_lb;
+
+    public CommonEditorEnumCellHolder(Context context, View view) {
+        super(context,view);
+
+        title_lb = (TextView) view.findViewById(R.id.enum_title_lb);
+        value_lb = (TextView) view.findViewById(R.id.enum_value_lb);
+
+    }
+
+    @Override
+    public void setItem(JSONObject item_json, boolean readonly, View view) {
+        super.setItem(item_json, readonly, view);
+    }
+}

+ 125 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorImageCellHolder.java

@@ -0,0 +1,125 @@
+package com.example.commoneditorlib.CommonEditor;
+
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.TextView;
+
+
+import com.usai.redant.CommonEditor.ImageUploadActivity;
+import com.usai.redant.CommonEditor.ImageViewActivity;
+import com.usai.redant.redantmobile.R;
+
+import org.json.JSONObject;
+
+
+public class CommonEditorImageCellHolder extends CommonEditorCellHolder{
+
+    public TextView title_lb;
+    public TextView desc_lb;
+    public ImageButton img_btn_0;
+    public ImageButton img_btn_1;
+    public ImageButton img_btn_2;
+    public boolean editable;
+
+
+    public CommonEditorImageCellHolder(Context context, View view) {
+        super(context, view);
+
+        title_lb = (TextView) view.findViewById(R.id.img_cell_title_lb);
+        desc_lb = (TextView) view.findViewById(R.id.img_cell_desc_lb);
+
+        img_btn_0 = (ImageButton) view.findViewById(R.id.img_btn_0);
+        img_btn_1 = (ImageButton) view.findViewById(R.id.img_btn_1);
+        img_btn_2 = (ImageButton) view.findViewById(R.id.img_btn_2);
+
+        img_btn_0.setTag(0);
+        img_btn_1.setTag(1);
+        img_btn_2.setTag(2);
+
+        img_btn_0.setOnClickListener(clickListener);
+        img_btn_1.setOnClickListener(clickListener);
+        img_btn_2.setOnClickListener(clickListener);
+
+    }
+
+    private String path0;
+    public void setImage0(String path,Bitmap bitmap) {
+        img_btn_0.setImageBitmap(bitmap);
+        path0 = path;
+    }
+
+    private String path1;
+    public void setImage1(String path,Bitmap bitmap) {
+        img_btn_1.setImageBitmap(bitmap);
+        path1 = path;
+    }
+
+    private String path2;
+    public void setImage2(String path,Bitmap bitmap) {
+        img_btn_2.setImageBitmap(bitmap);
+        path2 = path;
+    }
+
+    @Override
+    public void setItem(JSONObject item_json, boolean readonly, View view) {
+        super.setItem(item_json, readonly, view);
+    }
+
+    private View.OnClickListener clickListener = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            ImageButton btn = (ImageButton)v;
+            int btn_tag = (int)btn.getTag()/*Integer.valueOf((String)btn.getTag())*/;
+
+            int UPLOAD_IMAGE_CODE = 1;
+
+            if (editable) {
+                // 上传Image
+
+                Intent intent = new Intent(mCtx,ImageUploadActivity.class);
+                intent.putExtra("group",group);
+                intent.putExtra("child",child);
+                intent.putExtra("btn",btn_tag);
+
+                ((Activity)mCtx).startActivityForResult(intent,UPLOAD_IMAGE_CODE);
+
+            } else {
+                // 查看Image
+
+                Intent intent = new Intent(mCtx,ImageViewActivity.class);
+                if (btn_tag == 0) {
+                    if (path0 == null || path0.isEmpty()) {
+                        intent = null;
+                    } else {
+                        intent.putExtra("data", path0);
+                    }
+                }
+                if (btn_tag == 1) {
+                    if (path1 == null || path1.isEmpty()) {
+                        intent = null;
+                    } else {
+                        intent.putExtra("data", path1);
+                    }
+                }
+                if (btn_tag == 2) {
+                    if (path2 == null || path2.isEmpty()) {
+                        intent = null;
+                    } else {
+                        intent.putExtra("data", path2);
+                    }
+                }
+
+
+                if (intent != null) {
+                    ((Activity)mCtx).startActivity(intent);
+                }
+
+            }
+        }
+    };
+}

+ 34 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorLabelCellHolder.java

@@ -0,0 +1,34 @@
+package com.example.commoneditorlib.CommonEditor;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.TextView;
+
+
+import com.usai.redant.redantmobile.R;
+
+import org.json.JSONObject;
+
+/**
+ * Created by macmini1 on 2017/8/16.
+ */
+
+public class CommonEditorLabelCellHolder extends CommonEditorCellHolder {
+
+
+    public TextView title_lb;
+    public TextView value_lb;
+
+    public CommonEditorLabelCellHolder(Context context, View view) {
+        super(context,view);
+
+        title_lb = (TextView) view.findViewById(R.id.cell_title_lb);
+        value_lb = (TextView) view.findViewById(R.id.cell_value_lb);
+
+    }
+
+    @Override
+    public void setItem(JSONObject item_json, boolean readonly, View view) {
+        super.setItem(item_json, readonly, view);
+    }
+}

+ 69 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorModelCellHolder.java

@@ -0,0 +1,69 @@
+package com.example.commoneditorlib.CommonEditor;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.TextView;
+
+
+import com.usai.redant.CommonEditor.BundleModelActivity;
+import com.usai.redant.redantmobile.R;
+
+import org.json.JSONObject;
+
+/**
+ * Created by macmini1 on 2017/8/16.
+ */
+
+public class CommonEditorModelCellHolder extends CommonEditorCellHolder {
+
+    public ImageButton model_img_btn;
+    public TextView desc_lb;
+    public TextView master_pack_lb;
+    public TextView old_price_lb;
+    public TextView discount_lb;
+    public TextView unit_price_lb;
+    public TextView count_lb;
+    public TextView bundle_btn;
+    public TextView total_price_lb;
+
+    public JSONObject bundle_item;
+
+    public CommonEditorModelCellHolder(Context context, View view) {
+        super(context, view);
+        model_img_btn = (ImageButton) view.findViewById(R.id.model_img_view);
+        desc_lb = (TextView) view.findViewById(R.id.model_desc_lb);
+        master_pack_lb = (TextView) view.findViewById(R.id.model_master_pack_lb);
+        old_price_lb = (TextView) view.findViewById(R.id.model_old_price_lb);
+        discount_lb = (TextView) view.findViewById(R.id.model_discount_lb);
+        unit_price_lb = (TextView) view.findViewById(R.id.model_unit_price_lb);
+        count_lb = (TextView) view.findViewById(R.id.model_count_lb);
+        bundle_btn = (TextView) view.findViewById(R.id.model_bundle_btn);
+        total_price_lb = (TextView) view.findViewById(R.id.model_total_price_lb);
+
+        bundle_btn.setOnClickListener(bundleClickListener);
+
+    }
+
+    @Override
+    public void setItem(JSONObject item_json, boolean readonly, View view) {
+        super.setItem(item_json, readonly, view);
+    }
+
+    private View.OnClickListener bundleClickListener = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            if (bundle_item != null) {
+                Intent intent = new Intent(mCtx,BundleModelActivity.class);
+                intent.putExtra("bundle_items",bundle_item.toString());
+                ((Activity)mCtx).startActivity(intent);
+
+//                BundleItemDialog dialog = new BundleItemDialog.Builder().build(mCtx);
+//                dialog.setItems(bundle_item.toString());
+//                dialog.show();
+            }
+        }
+    };
+}

+ 31 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorMultipleActionCellHolder.java

@@ -0,0 +1,31 @@
+package com.example.commoneditorlib.CommonEditor;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.Button;
+
+
+import com.usai.redant.redantmobile.R;
+
+import org.json.JSONObject;
+
+/**
+ * Created by macmini1 on 2017/8/16.
+ */
+
+public class CommonEditorMultipleActionCellHolder extends CommonEditorCellHolder {
+
+    public Button btn0,btn1,btn2,btn3;
+    public CommonEditorMultipleActionCellHolder(Context context, View view) {
+        super(context, view);
+        btn0 = (Button) view.findViewById(R.id.btn_0);
+        btn1 = (Button) view.findViewById(R.id.btn_1);
+        btn2 = (Button) view.findViewById(R.id.btn_2);
+        btn3 = (Button) view.findViewById(R.id.btn_3);
+    }
+
+    @Override
+    public void setItem(JSONObject item_json, boolean readonly, View view) {
+        super.setItem(item_json, readonly, view);
+    }
+}

+ 195 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorRangeCellHolder.java

@@ -0,0 +1,195 @@
+package com.example.commoneditorlib.CommonEditor;
+
+import android.content.Context;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import com.usai.redant.CommonEditor.CommonEditorActivity;
+import com.usai.redant.redantmobile.R;
+
+import org.json.JSONObject;
+
+/**
+ * Created by macmini1 on 2017/12/13.
+ */
+
+public class CommonEditorRangeCellHolder extends CommonEditorCellHolder {
+
+    public TextView title_lb;
+    public EditText min_et;
+    public EditText max_et;
+    public Button reset_btn;
+
+    public TextWatcher minTextChangeListener;
+
+    public TextWatcher maxTextChangeListener;
+
+    boolean processValues(String min_str, String max_str) {
+        float min = 0;
+        float max = Float.MAX_VALUE;
+
+        if (min_str != null && !min_str.isEmpty()) {
+            min = Float.valueOf(min_str);
+        }
+        if (max_str != null && !max_str.isEmpty()) {
+            max = Float.valueOf(max_str);
+        }
+
+        if (max < min) {
+
+            return false;
+        }
+        ((CommonEditorActivity)mCtx).commonEditorRangeDidChange(min_str,max_str,group,child);
+
+        return true;
+    }
+
+    public void clearTextWather() {
+        min_et.removeTextChangedListener(minTextChangeListener);
+        minTextChangeListener = null;
+
+        max_et.removeTextChangedListener(maxTextChangeListener);
+        maxTextChangeListener = null;
+    }
+
+    public void resetTextWather() {
+
+        minTextChangeListener = new TextWatcher() {
+
+            String origin_text;
+            String string;
+            int start_position;
+            int change_length; // 修改原文长度
+            int new_string_length;
+
+            @Override
+            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+                origin_text = s.toString();
+                start_position = start;
+                change_length = count;
+                new_string_length = after;
+
+            }
+
+            @Override
+            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+
+            }
+
+            @Override
+            public void afterTextChanged(Editable s) {
+
+                /**
+                 * 文本处理
+                 * */
+                if (new_string_length == 0) {
+                    string = "";
+                } else {
+                    string = s.toString().substring(start_position,start_position + new_string_length);
+                }
+
+                if (change_length == 0) { // 新加内容
+
+                } else { // 替换原文或删除原文
+
+                }
+
+                /**
+                 * 业务逻辑
+                 */
+                String max_str = max_et.getText().toString();
+                String min_str = min_et.getText().toString();
+
+                if (!processValues(min_str,max_str)) {
+                    min_et.setText(origin_text);
+                }
+
+            }
+        };
+
+        maxTextChangeListener  = new TextWatcher() {
+
+            String origin_text;
+            String string;
+            int start_position;
+            int change_length; // 修改原文长度
+            int new_string_length;
+
+            @Override
+            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+                origin_text = s.toString();
+                start_position = start;
+                change_length = count;
+                new_string_length = after;
+
+            }
+
+            @Override
+            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+
+            }
+
+            @Override
+            public void afterTextChanged(Editable s) {
+
+                /**
+                 * 文本处理
+                 * */
+                if (new_string_length == 0) {
+                    string = "";
+                } else {
+                    string = s.toString().substring(start_position,start_position + new_string_length);
+                }
+
+                if (change_length == 0) { // 新加内容
+
+                } else { // 替换原文或删除原文
+
+                }
+
+                /**
+                 * 业务逻辑
+                 */
+                String max_str = max_et.getText().toString();
+                String min_str = min_et.getText().toString();
+
+                if (!processValues(min_str,max_str)) {
+                    min_et.setText(origin_text);
+                }
+
+            }
+        };
+
+    }
+
+    private class ResetClickListener implements View.OnClickListener {
+
+        @Override
+        public void onClick(View view) {
+            ((CommonEditorActivity)mCtx).commonEditorRangeDidChange("","",group,child);
+        }
+    }
+
+
+    public CommonEditorRangeCellHolder(Context context, View view) {
+        super(context, view);
+
+        title_lb = view.findViewById(R.id.range_title_tv);
+        min_et = view.findViewById(R.id.range_minimum_et);
+        max_et = view.findViewById(R.id.range_maximum_et);
+        reset_btn = view.findViewById(R.id.range_reset_btn);
+
+        reset_btn.setOnClickListener(new ResetClickListener());
+    }
+
+    @Override
+    public void setItem(JSONObject item_json, boolean readonly, View view) {
+        super.setItem(item_json, readonly, view);
+    }
+}

+ 69 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorSectionHeaderHolder.java

@@ -0,0 +1,69 @@
+package com.example.commoneditorlib.CommonEditor;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.TextView;
+
+import com.usai.redant.redantmobile.R;
+
+import org.json.JSONObject;
+
+
+
+public class CommonEditorSectionHeaderHolder extends CommonEditorCellHolder {
+
+    public TextView title_lb;
+    public TextView control_btn;
+    public Boolean show;
+
+
+    public CommonEditorSectionHeaderHolder(Context context, View view) {
+        super(context, view);
+
+
+        title_lb = (TextView) view.findViewById(R.id.title_lb);
+        control_btn = (TextView) view.findViewById(R.id.header_control_btn);
+        setShow(true);
+        hideControlBtn(true);
+//
+//        control_btn.setOnClickListener(new View.OnClickListener() {
+//            @Override
+//            public void onClick(View v) {
+//                setShow(!show);
+//                if (sectionShow != null) {
+//                    sectionShow.sectionShow(group,show);
+//                }
+//            }
+//        });
+    }
+
+
+    public void setShow(boolean show) {
+        this.show = show;
+
+        if (show == true) {
+            control_btn.setText("Hide");
+        } else {
+            control_btn.setText("Show");
+        }
+
+    }
+
+    public void hideControlBtn(boolean hide) {
+        if (hide == true) {
+            control_btn.setVisibility(View.INVISIBLE);
+        } else {
+            control_btn.setVisibility(View.VISIBLE);
+        }
+    }
+
+    public void clickSectionHeader(boolean expand) {
+        setShow(expand);
+    }
+
+
+    @Override
+    public void setItem(JSONObject item_json, boolean readonly, View view) {
+        super.setItem(item_json, readonly, view);
+    }
+}

+ 30 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorSignatureCellHolder.java

@@ -0,0 +1,30 @@
+package com.example.commoneditorlib.CommonEditor;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.usai.redant.redantmobile.R;
+
+import org.json.JSONObject;
+
+/**
+ * Created by macmini1 on 2017/8/16.
+ */
+
+public class CommonEditorSignatureCellHolder extends CommonEditorCellHolder {
+
+    public TextView title_lb;
+    public ImageView signature_iv;
+    public CommonEditorSignatureCellHolder(Context context, View view) {
+        super(context, view);
+        title_lb = (TextView) view.findViewById(R.id.signature_title_lb);
+        signature_iv = (ImageView) view.findViewById(R.id.signature_image_view);
+    }
+
+    @Override
+    public void setItem(JSONObject item_json, boolean readonly, View view) {
+        super.setItem(item_json, readonly, view);
+    }
+}

+ 32 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorSwitchCellHolder.java

@@ -0,0 +1,32 @@
+package com.example.commoneditorlib.CommonEditor;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.Switch;
+import android.widget.TextView;
+
+
+import com.usai.redant.redantmobile.R;
+
+import org.json.JSONObject;
+
+/**
+ * Created by macmini1 on 2017/8/16.
+ */
+
+public class CommonEditorSwitchCellHolder extends CommonEditorCellHolder {
+
+    public TextView title_lb;
+    public Switch aSwitch;
+
+    public CommonEditorSwitchCellHolder(Context context, View view) {
+        super(context, view);
+        title_lb = (TextView) view.findViewById(R.id.switch_title_lb);
+        aSwitch = (Switch) view.findViewById(R.id.switch_cell_switch);
+    }
+
+    @Override
+    public void setItem(JSONObject item_json, boolean readonly, View view) {
+        super.setItem(item_json, readonly, view);
+    }
+}

+ 44 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditor/CommonEditorTextViewCellHolder.java

@@ -0,0 +1,44 @@
+package com.example.commoneditorlib.CommonEditor;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.text.method.TextKeyListener;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.inputmethod.EditorInfo;
+import android.widget.EditText;
+import android.widget.TextView;
+
+
+import com.usai.redant.redantmobile.R;
+
+import org.json.JSONObject;
+
+import static android.view.Gravity.CENTER_VERTICAL;
+import static android.view.Gravity.END;
+import static android.view.Gravity.START;
+
+/**
+ * Created by macmini1 on 2017/8/16.
+ */
+
+public class CommonEditorTextViewCellHolder extends CommonEditorCellHolder {
+
+    public TextView title_lb;
+    public EditText text_view;
+    public CommonEditorTextViewCellHolder(Context context, View view) {
+        super(context, view);
+
+        title_lb = (TextView) view.findViewById(R.id.name_lb);
+        text_view = (EditText) view.findViewById(R.id.text_view);
+    }
+
+    @Override
+    public void setItem(JSONObject item_json,boolean readonly,View view) {
+        super.setItem(item_json,readonly,view);
+
+
+    }
+}

+ 4776 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CommonEditorActivity.java

@@ -0,0 +1,4776 @@
+package com.example.commoneditorlib;
+
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.InputFilter;
+import android.text.InputType;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.EditorInfo;
+import android.widget.AbsListView;
+import android.widget.ArrayAdapter;
+import android.widget.AutoCompleteTextView;
+import android.widget.BaseExpandableListAdapter;
+import android.widget.Button;
+import android.widget.CompoundButton;
+import android.widget.EditText;
+import android.widget.ExpandableListView;
+import android.widget.Switch;
+
+
+import com.usai.redant.CommonEditor.CommonEditor.CommonEditorActionCellHolder;
+import com.usai.redant.CommonEditor.CommonEditor.CommonEditorAutoCompleteAdapter;
+import com.usai.redant.CommonEditor.CommonEditor.CommonEditorCellHolder;
+import com.usai.redant.CommonEditor.CommonEditor.CommonEditorDateRangeCellHolder;
+import com.usai.redant.CommonEditor.CommonEditor.CommonEditorEditAutoCompleteCellHolder;
+import com.usai.redant.CommonEditor.CommonEditor.CommonEditorEditCellHolder;
+import com.usai.redant.CommonEditor.CommonEditor.CommonEditorEnumCellHolder;
+import com.usai.redant.CommonEditor.CommonEditor.CommonEditorImageCellHolder;
+import com.usai.redant.CommonEditor.CommonEditor.CommonEditorLabelCellHolder;
+import com.usai.redant.CommonEditor.CommonEditor.CommonEditorModelCellHolder;
+import com.usai.redant.CommonEditor.CommonEditor.CommonEditorMultipleActionCellHolder;
+import com.usai.redant.CommonEditor.CommonEditor.CommonEditorRangeCellHolder;
+import com.usai.redant.CommonEditor.CommonEditor.CommonEditorSectionHeaderHolder;
+import com.usai.redant.CommonEditor.CommonEditor.CommonEditorSignatureCellHolder;
+import com.usai.redant.CommonEditor.CommonEditor.CommonEditorSwitchCellHolder;
+import com.usai.redant.CommonEditor.CommonEditor.CommonEditorTextViewCellHolder;
+import com.usai.redant.CommonEditor.EnumSelectAndSort.EnumSelectAndSortActivity;
+import com.usai.redant.redantmobile.R;
+import com.usai.redant.util.Network;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static android.view.Gravity.CENTER_VERTICAL;
+import static android.view.Gravity.LEFT;
+import static android.view.Gravity.RIGHT;
+import static android.view.Gravity.TOP;
+
+
+
+public class CommonEditorActivity extends AppCompatActivity implements View.OnLayoutChangeListener{
+
+
+    public ExpandAdapter adapter;
+    public String service_url;
+
+    public boolean hasChildView;
+    public ExpandableListView listView;
+    public View rootView;
+
+    /**Child Activity Override*/
+    public void download_success() {
+
+    }
+
+    public void request_fill() {
+
+    }
+
+    public JSONObject request_editor(String request_url,Bundle params) {
+        return null;
+    }
+
+    public static class subitem_data {
+        public JSONObject params;
+        public JSONArray missingfields;
+    }
+
+    public ProgressDialog showProgressAlert(String title,String msg) {
+        ProgressDialog pd = new ProgressDialog(this);
+        pd.setTitle(title);
+        pd.setMessage(msg);
+        /**
+         * false,表示 ProgressDialog 是不能通过 Back 键取消
+         * 数据加载完成后必须要调用 ProgressDialog 的 dismiss() 方法来关闭对话框
+         * */
+        pd.setCancelable(false);
+        pd.show();
+
+        return pd;
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.action_bar_menu,menu);
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+
+        if (item.getItemId() == R.id.save_item) {
+            JSONObject obj = check_cancomit(true);
+            Log.d("Check Can Commit", "onOptionsItemSelected: ");
+        }
+
+        return true;
+    }
+
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+
+        if (content_data_control != null) {
+            outState.putString("control_content",content_data_control.toString());
+        }
+        if (content_data_download != null) {
+            outState.putString("download_content",content_data_download.toString());
+        }
+
+        if (service_url != null) {
+            outState.putString("request_url",service_url);
+        }
+
+        if (getTitle() != null) {
+            outState.putString("title",getTitle().toString());
+        }
+
+        outState.putInt("url_type",url_type);
+        outState.putBundle("params",selfParams);
+    }
+
+    public static Intent build(Context context,Class cls,String title,int URLType,String requestURL,Bundle params) {
+
+        if (context == null || cls == null) {
+            return null;
+        }
+
+        Intent intent = new Intent(context,cls);
+
+        intent.putExtra("url_type",URLType);
+
+        if (requestURL != null) {
+            intent.putExtra("request_url",requestURL);
+        }
+
+        if (params != null) {
+            intent.putExtra("params",params);
+        }
+
+
+        if (title != null) {
+            intent.putExtra("title",title);
+        }
+
+        return intent;
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+
+        if (!hasChildView) {
+            setContentView(R.layout.activity_common_editor);
+
+//            rootView = findViewById(R.id.root_layout);
+            listView = (ExpandableListView)findViewById(R.id.list_view);
+        }
+
+        rootView = getWindow().getDecorView().findViewById(android.R.id.content);
+
+        if (listView == null) {
+            return;
+        }
+
+        adapter = new ExpandAdapter(this);
+
+        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
+            @Override
+            public void onScrollStateChanged(AbsListView view, int scrollState) {
+                // 编辑状态下滑动,去掉焦点
+                if (lastEditText != null) {
+                    lastEditText.clearFocus();
+                }
+            }
+
+            @Override
+            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
+
+            }
+        });
+
+        listView.setGroupIndicator(null);
+
+        listView.setOnChildClickListener(new ListChildViewClickListener());
+
+        listView.setAdapter(adapter);
+
+
+        if (savedInstanceState != null) {
+            String control_str = savedInstanceState.getString("control_content");
+            String download_str = savedInstanceState.getString("download_content");
+            try {
+                if (control_str != null || !control_str.isEmpty()) {
+                    content_data_control = new JSONArray(control_str);
+                }
+                if (download_str != null || !download_str.isEmpty()) {
+                    content_data_download = new JSONObject(download_str);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+                content_data_control = null;
+                content_data_download = null;
+            }
+
+            service_url = savedInstanceState.getString("request_url");
+            url_type = savedInstanceState.getInt("url_type");
+            selfParams = savedInstanceState.getBundle("params");
+//            String title = savedInstanceState.getString("title");
+//            setTitle(title);
+
+        } else {
+            service_url = getIntent().getStringExtra("request_url");
+            url_type = getIntent().getIntExtra("url_type",URL_REMOTE);
+//            String title = getIntent().getStringExtra("title");
+//            setTitle(title);
+
+            Bundle params = getIntent().getBundleExtra("params");
+            if (params != null) {
+                selfParams = params;
+            }
+
+
+
+            final ProgressDialog pd = showProgressAlert("Loading","Please wait");
+            new Thread(new Runnable() {
+                @Override
+                public void run() {
+
+                    if (url_type == URL_REMOTE) {
+                        final JSONObject obj = request_editor(service_url,selfParams);
+
+
+                        runOnUiThread(new Runnable() {
+                            @Override
+                            public void run() {
+
+                                pd.dismiss();
+
+                                if (obj != null) {
+
+                                    int result = obj.optInt("result");
+                                    if (result == 2) {
+
+                                        content_data_download = copyDirtyTo(content_data_download,obj);
+                                        content_data_control = translateChange(content_data_download,changed_data);
+
+
+                                        download_success();
+                                        defaulExpandSections();
+                                        adapter.notifyDataSetChanged();
+
+                                    } else {
+                                        Utils.message_alert(mCtx,"Warning","Error");
+                                    }
+
+                                } else {
+                                    Utils.message_alert(mCtx,"Warning","Error");
+                                }
+
+                            }
+                        });
+
+                    } else {
+
+                        try {
+
+                            InputStreamReader isr = new InputStreamReader(getAssets().open(service_url + ".json"),"UTF-8");
+                            BufferedReader br = new BufferedReader(isr);
+                            String line;
+                            StringBuilder builder = new StringBuilder();
+                            while((line = br.readLine()) != null){
+                                builder.append(line);
+                            }
+                            br.close();
+                            isr.close();
+                            content_data_download = new JSONObject(builder.toString());//builder读取了JSON中的数据。
+
+                            request_fill();
+
+                            content_data_control = translateChange(content_data_download,changed_data);
+
+                            runOnUiThread(new Runnable() {
+                                @Override
+                                public void run() {
+                                    pd.dismiss();
+                                    adapter.notifyDataSetChanged();
+                                }
+                            });
+
+
+                        } catch (Exception e) {
+                            runOnUiThread(new Runnable() {
+                                @Override
+                                public void run() {
+                                    pd.dismiss();
+                                }
+                            });
+                            e.printStackTrace();
+                        }
+
+                    }
+
+                }
+            }).start();
+        }
+
+        String title = selfParams.getString("title");
+        setTitle(title);
+
+    }
+
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        if (rootView != null) {
+            rootView.addOnLayoutChangeListener(this);
+        }
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+        if (lastEditText != null) {
+            lastEditText.clearFocus();
+        }
+
+    }
+
+    @Override
+    public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
+
+        if(oldBottom != 0 && bottom != 0 && oldBottom > bottom){
+
+            Log.d("Keyboard", "show: ");
+
+        }else if(oldBottom != 0 && bottom != 0 && oldBottom < bottom){
+
+            endEditting();
+            Log.d("Keyboard", "hide: ");
+        }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+
+        if (data == null || resultCode != RESULT_OK) {
+            return;
+        }
+
+        // upload image
+        if (requestCode == 1) {
+            int group = data.getIntExtra("group",0);
+            int child = data.getIntExtra("child",0);
+            int btn = data.getIntExtra("btn",0);
+            String url_down = data.getStringExtra("url_down");
+            String url_up = data.getStringExtra("url_up");
+            String path = data.getStringExtra("path");
+            Utils.cacheLocalImageToURL(path,url_up); // 将图片移动到缓存目录
+            // 对应更新数据,然刷新该行
+            imgIsChanged(url_down,url_up,group,child,btn,url_up);
+        }
+
+        // addr editor
+        if (requestCode == 2) {
+            String value_str = data.getStringExtra(AddressEditorActivity.RETURN_VALUE);
+            JSONObject value = null;
+            if (value_str != null) {
+                try {
+                    value = new JSONObject(value_str);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    return;
+                }
+            }
+            int group = data.getIntExtra(AddressEditorActivity.GROUP,0);
+            int child = data.getIntExtra(AddressEditorActivity.CHILD,0);
+            handle_action_return(value,group,child,ACTION_SAVE_DATA);
+        }
+
+        // credit card editor
+        if (requestCode == 3) {
+            String value_str = data.getStringExtra(CreditCardEditorActivity.RETURN_VALUE);
+            JSONObject value = null;
+            if (value_str != null) {
+                try {
+                    value = new JSONObject(value_str);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    return;
+                }
+            }
+            int group = data.getIntExtra(CreditCardEditorActivity.GROUP,0);
+            int child = data.getIntExtra(CreditCardEditorActivity.CHILD,0);
+            handle_action_return(value,group,child,ACTION_SAVE_DATA);
+        }
+
+        // contact list
+        if (requestCode == 4 || requestCode == 5 || requestCode == 6 || requestCode == 7 || requestCode == 8 || requestCode == 9) {
+            String value_str = data.getStringExtra(ContactListActivity.RETURN_VALUE);
+            JSONObject value = null;
+            if (value_str != null) {
+                try {
+                    value = new JSONObject(value_str);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    return;
+                }
+            }
+            int group = data.getIntExtra(ContactListActivity.GROUP,0);
+            int child = data.getIntExtra(ContactListActivity.CHILD,0);
+            handle_action_return(value,group,child,ACTION_FILL_SECTION);
+        }
+
+        // enum select
+        if (requestCode == 10) {
+
+            String cadedate_str = data.getStringExtra(EnumSlectActivity.CADEDATE);
+            if (cadedate_str == null || cadedate_str.isEmpty()) {
+                return;
+            }
+            try {
+                JSONObject cadedate = new JSONObject(cadedate_str);
+                int group = data.getIntExtra(EnumSlectActivity.GROUP_POSITION,0);
+                int child = data.getIntExtra(EnumSlectActivity.CHILD_POSITION,0);
+
+                setEnumValue(cadedate,group,child);
+
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+
+        }
+
+        // date picker
+        if (requestCode == 11) {
+
+        }
+
+        // month picker
+        if (requestCode == 12) {
+
+            String date_str = data.getStringExtra("value");
+            int group = data.getIntExtra("group",0);
+            int child = data.getIntExtra("child",0);
+            MPValueChanged(date_str,group,child);
+
+        }
+
+        // signature
+        if (requestCode == 13) {
+
+            int group = data.getIntExtra("group",0);
+            int child = data.getIntExtra("child",0);
+            String url_down = data.getStringExtra("url_down"); // avalue
+            String url_up = data.getStringExtra("url_up"); // value
+            String path = data.getStringExtra("path");
+
+            Utils.cacheLocalImageToURL(path,url_down);
+
+            signatureIsChanged(url_down,url_up,group,child);
+        }
+
+        // date range
+        if (requestCode == 14) {
+            int group = data.getIntExtra("group",0);
+            int child = data.getIntExtra("child",0);
+            String min = data.getStringExtra("min");
+            String max = data.getStringExtra("max");
+
+            String min_components[] = min.split("/");
+            String max_components[] = max.split("/");
+
+            if (min_components.length == max_components.length) {
+
+                int min_year = Integer.valueOf(min_components[2]);
+                int min_month = Integer.valueOf(min_components[0]);
+                int min_day = Integer.valueOf(min_components[1]);
+
+                int max_year = Integer.valueOf(max_components[2]);
+                int max_month = Integer.valueOf(max_components[0]);
+                int max_day = Integer.valueOf(max_components[1]);
+
+                if (min_year > max_year) {
+                    showWarningAlert("minimum can't larger than maximum");
+                    return;
+                } else if (min_year == max_year) {
+
+                    if (min_month > max_month) {
+                        showWarningAlert("minimum can't larger than maximum");
+                        return;
+                    } else if (min_month == max_month) {
+
+                        if (min_day > max_day) {
+                            showWarningAlert("minimum can't larger than maximum");
+                            return;
+                        }
+
+                    }
+
+                }
+
+
+            }
+
+            commonEditorRangeDidChange(min,max,group,child);
+        }
+
+    }
+
+    public void showWarningAlert(String msg) {
+
+        new AlertDialog.Builder(mCtx)
+                .setTitle("Warning")
+                .setMessage(msg)
+                .show();
+
+    }
+
+    public void signatureIsChanged(String url_down,String url_up,int group,int child) {
+
+        JSONArray section = content_data_control.optJSONArray(group);
+        JSONObject item_json = section.optJSONObject(child);
+
+        try {
+
+            item_json.put("avalue",url_down);
+            item_json.put("value",url_up);
+            item_json.put("dirty","true");
+
+            JSONObject section_json = content_data_download.optJSONObject("section_" + group);
+            section_json.put("item_" + child,item_json);
+
+            content_data_download.put("section_" + group, section_json);
+            content_data_control = translateChange(content_data_download,changed_data);
+
+            adapter.notifyDataSetChanged();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    public void handle_action_return(JSONObject value,int group,int child,int action_code) {
+        if (value == null || value.length() == 0) {
+            return;
+        }
+
+        JSONObject section_json = null;
+        JSONObject item_json = content_data_control.optJSONArray(group).optJSONObject(child);
+
+        boolean is_subaction = value.optBoolean("is_subaction");
+        int subaction_tag = value.optInt("subaction_tag");
+        value.remove("is_subaction");
+        value.remove("subaction_tag");
+
+        if (is_subaction) {
+
+            JSONObject sub_action = item_json.optJSONObject("item_" + subaction_tag);
+            int refresh = sub_action.optInt("refresh");
+            String refresh_trigger = sub_action.optString("name");
+            JSONObject restore_json = sub_action.optJSONObject("restore");
+
+            String subid = sub_action.optString("subid");
+
+            String required = sub_action.optString("required");
+            /** Warning
+             *   get cell
+             *
+             * */
+            if (required.equals("true") && value.length() == 0) {
+                // cell red shadow
+            } else {
+                // cell clear shadow
+            }
+
+            if (value.length() != 0) {
+
+                if (action_code == ACTION_SAVE_DATA) {
+
+                    try {
+                        sub_action.put("data",value);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                    if (subid == null || subid.isEmpty()) {
+                        try {
+
+                            sub_action.put("dirty","true");
+                            section_json = content_data_download.optJSONObject("section_" + group);
+                            int count = 0;
+                            count = section_json.optInt("count");
+                            for (int i = 0; i < count; i++) {
+
+                                JSONObject olditem = section_json.optJSONObject("item_" + i);
+                                if (olditem.optString("name").equals(sub_action.optString("name"))) {
+                                    item_json.put("item_" + value.optInt("subaction_tag"),sub_action);
+                                    section_json.put("item_" + i,item_json);
+                                }
+
+                            } // for
+
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+
+                        // subid == null
+                    } else {
+
+                        String[] idarr = subid.split("_");
+                        int section = Integer.valueOf(idarr[0]);
+                        int item = Integer.valueOf(idarr[1]);
+
+                        section_json = content_data_download.optJSONObject("section_" + section);
+                        JSONObject olditem = section_json.optJSONObject("item_" + item);
+                        sub_action = enum_subitem_changed(olditem,idarr,sub_action,2);
+
+                        try {
+
+                            sub_action.put("dirty","true");
+                            item_json.put("item_" + value.optInt("subaction_tag"),sub_action);
+                            section_json.put("item_" + item,item_json);
+
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+
+                    } // else
+
+                } else if (action_code == ACTION_FILL_SECTION) {
+                    if (subid == null || subid.isEmpty()) {
+
+                        JSONObject jsonmap = sub_action.optJSONObject("key_map");
+                        section_json = content_data_download.optJSONObject("section_" + group);
+                        int icount = section_json .optInt("count");
+                        for (int ic = 0; ic < icount; ic++) {
+                            JSONObject modify_item = section_json.optJSONObject("item_" + ic);
+                            String valuefrom = jsonmap.optString(modify_item.optString("name"));
+                            String valuestr = value.optString(valuefrom);
+                            if (valuestr != null) {
+                                try {
+
+                                    modify_item.put("value",valuestr);
+                                    modify_item.put("dirty","true");
+                                    section_json.put("item_" + ic,modify_item);
+
+                                } catch (Exception e) {
+                                    e.printStackTrace();
+                                }
+                            }
+                        }
+
+                        // subid == null
+                    } else {
+
+                        String[] idarr = subid.split("_");
+                        int section = Integer.valueOf(idarr[0]);
+                        int item = Integer.valueOf(idarr[1]);
+                        JSONObject jsonmap = sub_action.optJSONObject("key_map");
+
+                        section_json = content_data_download.optJSONObject("section_" + section);
+                        JSONObject olditem = section_json.optJSONObject("item_" + item);
+                        JSONObject olditem_sub_action = olditem.optJSONObject("item_" + subaction_tag);
+
+                        olditem_sub_action = fill_switch_subitem_subid_mapping(olditem,null,value,jsonmap);
+
+                        try {
+
+                            olditem_sub_action.put("dirty","true");
+                            olditem.put("item_" + value.optInt("subaction_tag"),olditem_sub_action);
+                            section_json.put("item_" + item,olditem);
+
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+                    }
+                }
+
+                try {
+                    content_data_download.put("section_" + group,section_json);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+
+            } // value.length != 0
+
+            content_data_control = translateChange(content_data_download,changed_data);
+
+            if (refresh == 1) {
+
+                if (restore_json != null) {
+                    int rc = restore_json.optInt("count");
+                    for (int ir = 0; ir < rc; ir++) {
+                        String name = restore_json.optString("item_" + ir);
+                        int section_count = content_data_download.optInt("section_count");
+                        for (int i = 0; i< section_count; i++) {
+                            JSONObject sectionjson = content_data_download.optJSONObject("section_" + i);
+                            int item_count = sectionjson.optInt("count");
+                            try {
+                                for (int j = 0; j < item_count; j++) {
+                                    JSONObject itemjson = sectionjson.optJSONObject("item_" + j);
+                                    if (itemjson.optString("name").equals(name)) {
+                                        itemjson.remove("dirty");
+                                        sectionjson.put("item_" + j,itemjson);
+                                    }
+                                }
+                                content_data_download.put("section_" + i,sectionjson);
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                            }
+                        }
+                    }
+                }
+
+                refresh(refresh_trigger);
+                return;
+            }
+            adapter.notifyDataSetChanged();
+
+            // is_subaction
+        } else {
+            int refresh = item_json.optInt("refresh");
+            String refresh_trigger = item_json.optString("name");
+            JSONObject restore_json = item_json.optJSONObject("restore");
+
+            String subid = item_json.optString("subid");
+            String required = item_json.optString("required");
+
+            /** Warning
+             *
+             * get cell
+             * */
+            if (required.equals("true") && value.length() == 0) {
+                // cell red shadow
+            } else {
+                // cell clear shadow
+            }
+
+            if (value.length() != 0) {
+                if (action_code == ACTION_SAVE_DATA) {
+
+                    try {
+                        item_json.put("data",value);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+
+                    if (subid == null || subid.isEmpty()) {
+                        try {
+                            item_json.put("dirty","true");
+                            section_json = content_data_download.optJSONObject("section_" + group);
+                            int count = 0;
+                            count = section_json.optInt("count");
+                            for (int i = 0; i < count; i++) {
+                                JSONObject olditem = section_json.optJSONObject("item_" + i);
+                                if (olditem.optString("name").equals(item_json.optString("name"))) {
+                                    section_json.put("item_" + i,item_json);
+                                }
+                            }
+
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+
+                    } else {
+                        String[] idarr = subid.split("_");
+                        int section = Integer.valueOf(idarr[0]);
+                        int item = Integer.valueOf(idarr[1]);
+
+                        section_json = content_data_download.optJSONObject("section_" + section);
+                        JSONObject olditem = section_json.optJSONObject("item_" + item);
+                        item_json = enum_subitem_changed(olditem,idarr,item_json,2);
+                        try {
+                            item_json.put("dirty","true");
+                            section_json.put("item_" + item,item_json);
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+                    }
+
+
+                } else if (action_code == ACTION_FILL_SECTION) {
+
+                    if (subid == null || subid.isEmpty()) {
+
+                        JSONObject jsonmap = item_json.optJSONObject("key_map");
+                        section_json = content_data_download.optJSONObject("section_" + group);
+                        int icount = section_json.optInt("count");
+                        for (int ic = 0; ic < icount; ic++) {
+                            JSONObject modify_item = section_json.optJSONObject("item_" + ic);
+                            String valuefrom = jsonmap.optString(modify_item.optString("name"));
+                            String valuestr = value.optString(valuefrom);
+
+                            if (valuestr != null) {
+                                try {
+                                    modify_item.put("value",valuestr);
+                                    modify_item.put("dirty","true");
+                                    section_json.put("item_" + ic,modify_item);
+                                } catch (Exception e) {
+                                    e.printStackTrace();
+                                }
+                            }
+                        }
+
+                    } else {
+
+                        String[] idarr = subid.split("_");
+                        int section = Integer.valueOf(idarr[0]);
+                        int item = Integer.valueOf(idarr[1]);
+                        JSONObject jsonmap = item_json.optJSONObject("key_map");
+
+                        section_json = content_data_download.optJSONObject("section_" + section);
+                        JSONObject olditem = section_json.optJSONObject("item_" + item);
+
+                        olditem = fill_switch_subitem_subid_mapping(olditem,null,value,jsonmap);
+
+                        try {
+                            olditem.put("dirty","true");
+                            section_json.put("item_" + item,olditem);
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+
+                    }
+
+                }
+
+                try {
+                    content_data_download.put("section_" + group,section_json);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+
+            content_data_control = translateChange(content_data_download,changed_data);
+
+            if (refresh != 1) {
+
+                if (restore_json != null) {
+                    int rc = restore_json.optInt("count");
+                    for (int ir = 0; ir < rc; ir++) {
+                        String name = restore_json.optString("item_" + ir);
+                        int section_count = content_data_download.optInt("section_count");
+                        for (int i = 0; i < section_count; i++) {
+                            JSONObject sectionjson = content_data_download.optJSONObject("section_" + i);
+                            int item_count = sectionjson.optInt("count");
+                            try {
+                                for (int j = 0; j < item_count; j++) {
+                                    JSONObject itemjson = sectionjson.optJSONObject("item_" + j);
+                                    if (itemjson.optString("name").equals(name)) {
+                                        itemjson.remove("dirty");
+                                        sectionjson.put("item_" + j,itemjson);
+                                    }
+                                }
+                                content_data_download.put("section_" + i,sectionjson);
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                            }
+                        }
+
+                    }
+                }
+
+                refresh(refresh_trigger);
+                return;
+            }
+
+            adapter.notifyDataSetChanged();
+        }
+
+    }
+
+    public JSONObject enum_subitem_changed(JSONObject item,String[] subid,JSONObject value,int step) {
+
+        int index = Integer.valueOf(subid[step]);
+        JSONObject cadedate = item.optJSONObject("cadedate");
+        JSONObject subitem = item.optJSONObject("sub_item");
+        if (cadedate != null) {
+            JSONObject valjson = cadedate.optJSONObject("val_" + index);
+            valjson = enum_subitem_changed(valjson,subid,value,step+1);
+
+            try {
+                cadedate.put("val_" + index,valjson);
+                item.put("cadedate",cadedate);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            return item;
+
+        } else if (subitem != null) {
+
+            JSONObject itemjson = subitem.optJSONObject("item_" + index);
+            if (step == subid.length - 1) {
+                itemjson = value;
+            } else {
+                itemjson = enum_subitem_changed(itemjson,subid,value,step + 1);
+            }
+
+            try {
+
+                subitem.put("item_" + index,itemjson);
+                item.put("sub_item",subitem);
+
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            return item;
+        }
+
+        return null;
+    }
+
+
+    JSONObject changed_data;
+
+    public JSONObject copyDirtyTo(JSONObject dirty, JSONObject to) {
+
+        if (dirty == null) {
+            return to;
+        }
+
+        int section_count = dirty.optInt("section_count");
+
+        try {
+            for(int i=0;i<section_count;i++)
+            {
+                JSONObject sectionjson = dirty.optJSONObject("section_" + i);
+                JSONObject to_sectionjson = to.optJSONObject("section_" + i);
+                int item_count = sectionjson.optInt("count");
+                for(int j=0;j<item_count;j++)
+                {
+                    JSONObject itemjson = sectionjson.optJSONObject("item_" + j);
+
+                    if(itemjson.optString("dirty").equals("true"))
+                    {
+                        to_sectionjson.put("item_" + j ,itemjson);
+                    }
+
+                }
+                to.put("section_" + i,to_sectionjson);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return to;
+    }
+
+    public JSONArray translateChange(JSONObject obj, JSONObject change_data) {
+
+        if (obj == null)
+            return null;
+
+        JSONArray retarray = new JSONArray();
+
+        int section_count = obj.optInt("section_count");
+        for (int i = 0; i < section_count; i++) {
+            JSONArray sectionarr = new JSONArray();
+
+            JSONObject sectionjson = obj.optJSONObject("section_" + i);
+            int item_count = sectionjson.optInt("count");
+            for(int j=0;j<item_count;j++)
+            {
+                JSONObject itemjson=sectionjson.optJSONObject("item_" + j);
+
+                sectionarr.put(itemjson);
+
+                addSubItemToParent(itemjson,sectionarr,i + "_" + j);
+
+            }
+
+        retarray.put(sectionarr);
+        }
+
+        Log.e("Content Data Control", "translateChange: ");
+        return retarray;
+    }
+
+    public JSONArray addSubItemToParent(JSONObject itemjson,JSONArray sectionarr,String parent) {
+
+        try {
+
+            String control_type = itemjson.optString("control");
+            boolean single_select = itemjson.optBoolean("single_select");
+            if (control_type.equals("enum") && single_select) {
+
+                JSONObject cadedatejson = itemjson.optJSONObject("cadedate");
+                int cade_count = cadedatejson.optInt("count");
+                for (int k = 0; k < cade_count; k++) {
+                    JSONObject valjson = cadedatejson.optJSONObject("val_" + k);
+                    int check = valjson.optInt("check");
+                    JSONObject subjson = valjson.optJSONObject("sub_item");
+                    boolean active = valjson.optBoolean("active");
+                    active = false;
+                    if (check == 1 && subjson != null && !active) {
+                        int sub_count = subjson.optInt("count");
+                        for (int l = 0; l < sub_count; l++) {
+                            JSONObject addjson = subjson.optJSONObject("item_" + l);
+                            String subself = parent + "_" + k + "_" + l;
+                            addjson.put("subid",subself);
+                            sectionarr.put(addjson);
+                            addSubItemToParent(addjson,sectionarr,subself);
+
+                        }
+                        valjson.put("active",true);
+                        cadedatejson.put("val_" + k,valjson);
+                    }
+                }
+
+            } else if (control_type.equals("switch")) {
+
+                String value = itemjson.optString("value");
+                JSONObject subjson = null;
+                if (value.equals("true")) {
+                    JSONObject true_obj = itemjson.optJSONObject("true");
+                    if (true_obj != null) {
+                        subjson = true_obj.optJSONObject("sub_item");
+                    }
+                } else {
+                    JSONObject false_obj = itemjson.optJSONObject("false");
+                    if (false_obj != null) {
+                        subjson = false_obj.optJSONObject("sub_item");
+                    }
+                }
+
+                if (subjson != null) {
+                    int sub_count = subjson.optInt("count");
+                    for (int l = 0; l < sub_count; l++) {
+                        JSONObject addjson = subjson.optJSONObject("item_" + l);
+                        String subself = parent + "_" + l;
+                        addjson.put("subid",subself);
+                        sectionarr.put(addjson);
+                        addSubItemToParent(addjson,sectionarr,subself);
+                    }
+                }
+
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return sectionarr;
+    }
+
+    public void defaulExpandSections() {
+        int groupCount = 0;
+        if (content_data_control != null) {
+            groupCount = content_data_control.length();
+        } else {
+            groupCount = 0;
+        }
+
+        if (groupCount <= 0) {
+            return;
+        }
+
+        for (int i = 0; i < groupCount; i++) {
+            JSONObject section_json = content_data_download.optJSONObject("section_" + i);
+            boolean hide = section_json.optBoolean("hide");
+            if (hide) {
+                listView.collapseGroup(i); // 默认关闭
+            } else {
+                listView.expandGroup(i); // 默认展开
+            }
+        }
+
+    }
+
+    public int url_type = URL_REMOTE;
+    public void refresh(String trigger) {
+
+        if (lastEditText != null) {
+            endEditting();
+        }
+
+        final ProgressDialog pd = showProgressAlert("Loading","Please wait");
+
+        if (url_type == URL_REMOTE) {
+
+            if (trigger != null) {
+                try {
+                    selfParams.putString("refresh_trigger",trigger);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+            new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    JSONObject refresh_params = get_refresh_param();
+                    Iterator<String> iterator = refresh_params.keys();
+                    while (iterator.hasNext()) {
+                        String key = iterator.next();
+                        String obj_str = "" + refresh_params.optString(key);
+                        try {
+                            selfParams.putString(key,obj_str);
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+                    }
+
+                    final JSONObject editor_json = request_editor(service_url,selfParams);
+
+                    runOnUiThread(new Runnable() {
+                        @Override
+                        public void run() {
+                            pd.dismiss();
+                            if (editor_json == null) {
+                                Utils.message_alert(mCtx,"Warning","net error");
+                                adapter.notifyDataSetChanged();
+                                return;
+                            }
+                            if (Integer.valueOf(editor_json.optString("result")) == 2) {
+                                content_data_download = copyDirtyTo(content_data_download,editor_json);
+                                content_data_control = translateChange(content_data_download,changed_data);
+
+                                download_success();
+                                adapter.notifyDataSetChanged();
+
+                            } else {
+                                Utils.message_alert(mCtx,"Warning",editor_json.optString("err_msg"));
+                            }
+                        }
+                    });
+                }
+            }).start();
+
+
+        } // url remote
+        else {
+
+            try {
+
+                InputStreamReader isr = new InputStreamReader(getAssets().open(service_url + ".json"),"UTF-8");
+                BufferedReader br = new BufferedReader(isr);
+                String line;
+                StringBuilder builder = new StringBuilder();
+                while((line = br.readLine()) != null){
+                    builder.append(line);
+                }
+                br.close();
+                isr.close();
+                content_data_download = new JSONObject(builder.toString());//builder读取了JSON中的数据。
+
+                request_fill();
+
+                content_data_control = translateChange(content_data_download,changed_data);
+                adapter.notifyDataSetChanged();
+                pd.dismiss();
+            } catch (Exception e) {
+                e.printStackTrace();
+                pd.dismiss();
+            }
+
+        }
+    }
+
+    public Bundle selfParams = new Bundle();
+    public JSONObject get_refresh_param() {
+        try {
+            JSONObject params = new JSONObject();
+            JSONObject param_names = content_data_download.optJSONObject("up_params");
+            int param_count = param_names.optInt("count");
+            for (int pc = 0; pc < param_count; pc++) {
+                String param_name = param_names.optString("val_" + pc);
+                String param_val = getValue(param_name);
+                selfParams.putString(param_name,param_val);
+            }
+            return params;
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public  subitem_data subitem_param_addto_alert(JSONObject itemjson,JSONObject upparam,boolean alert) {
+
+        try {
+
+            subitem_data data = new subitem_data();
+
+            JSONArray fields = new JSONArray();
+            String control_type = itemjson.optString("control");
+            boolean single_select = itemjson.optBoolean("single_select");
+            if (control_type.equals("enum") && single_select) {
+
+                JSONObject cadedatejson = itemjson.optJSONObject("cadedate");
+                int cade_count = cadedatejson.optInt("count");
+
+                for (int k = 0; k < cade_count; k++) {
+                    JSONObject valjson  = cadedatejson.optJSONObject("val_" + k);
+                    int check = valjson.optInt("check");
+
+                    JSONObject subjson = valjson.optJSONObject("sub_item");
+                    boolean active = valjson.optBoolean("active");
+                    if (check == 1 && subjson != null && !active) {
+
+                        int sub_count = subjson.optInt("count");
+                        for (int l = 0; l < sub_count; l++) {
+
+                            JSONObject addjson = subjson.optJSONObject("item_" + l);
+                            String required = addjson.optString("required");
+                            String key = addjson.optString("name");
+                            if (key == null || key.isEmpty()) {
+                                continue;
+                            } //
+                            if (addjson.optString("control").equals("enum")) {
+                                String add_single_select = addjson.optString("single_select");
+                                if (add_single_select.equals("true")) {
+
+                                    JSONObject cadejson = addjson.optJSONObject("cadedate");
+                                    int count = cadejson.optInt("count");
+                                    boolean setvalue = false;
+                                    for (int cc = 0; cc < count; cc++) {
+                                        JSONObject cade_valjson = cadejson.optJSONObject("val_" + cc);
+                                        if (Integer.valueOf(cade_valjson.optString("check")) == 1) {
+                                            upparam.put(addjson.optString("name"),cade_valjson.optString("value_id"));
+                                            setvalue = true;
+                                            break;
+                                        } // check == 1
+
+                                    } // for cc
+
+                                    if (addjson.optString("required").equals("true") && setvalue == false) {
+                                        cancommit = false;
+
+                                        String mfield = String.format("%d. %s is missing",fields.length() + 1,addjson.optString("aname"));
+
+                                        fields.put(mfield);
+
+                                        IndexPath indexPath = get_indexpath1(addjson.optString("name"));
+                                        if (alert) {
+                                            listView.expandGroup(indexPath.section);
+                                        }
+                                        if (fields.length() == 1) {
+                                            first_miss_pos = indexPath;
+                                        }
+
+                                    }
+
+
+                                } else {
+                                    // not support multiple selection
+                                }
+
+                            } // addjson control enum
+                            else if (addjson.optString("control").equals("action")) {
+
+                                JSONObject action_data = addjson.optJSONObject("data");
+                                int section_count = action_data.optInt("section_count");
+
+                                if (required.equals("true") && action_data != null) {
+
+                                    cancommit = false;
+                                    String mfield = String.format("%d. %@ is missing",fields.length() + 1,addjson.optString("aname"));
+                                    fields.put(mfield);
+
+                                    IndexPath indexPath = get_indexpath1(addjson.optString("name"));
+                                    if (alert) {
+                                        listView.expandGroup(indexPath.section);
+                                    }
+                                    if (fields.length() == 1) {
+                                        first_miss_pos = indexPath;
+                                    }
+
+                                } // required true && action_data
+
+                                for (int i = 0; i < section_count; i++) {
+
+                                    JSONObject sectionjson = action_data.optJSONObject("section_" + i);
+                                    int item_count = sectionjson.optInt("count");
+                                    for (int j = 0; j < item_count; j++) {
+                                        JSONObject itemjson_j = sectionjson.optJSONObject("item_" + j);
+                                        String key_j = itemjson_j.optString("name");
+
+                                        if (key_j == null || key_j.isEmpty()) {
+                                            continue;
+                                        }
+
+                                        if (itemjson_j.optString("control").equals("enum")) {
+
+                                            String single_select_j = itemjson_j.optString("single_select");
+                                            if (single_select_j.equals("true")) {
+
+                                                JSONObject cadejson = itemjson_j.optJSONObject("cadedate");
+                                                int count = cadejson.optInt("count");
+                                                boolean setvalue = false;
+                                                for (int cc = 0; cc < count; cc++) {
+                                                    JSONObject valjson_cc = cadejson.optJSONObject("val_" + cc);
+                                                    if (valjson_cc.optInt("check") == 1) {
+                                                        upparam.put(itemjson_j.optString("name"),valjson_cc.optString("value_id"));
+                                                        setvalue = true;
+                                                        break;
+                                                    } // check
+                                                }
+
+                                                if (itemjson_j.optString("required").equals("true") && setvalue == false) {
+                                                    cancommit = false;
+                                                    String mfield = String.format("%d. %@ is missing",fields.length() + 1,itemjson_j.optString("aname"));
+                                                    fields.put(mfield);
+
+                                                    IndexPath indexPath = get_indexpath1(addjson.optString("name"));
+                                                    if (alert) {
+                                                        listView.expandGroup(indexPath.section);
+                                                    }
+                                                    if (fields.length() == 1) {
+                                                        first_miss_pos = indexPath;
+                                                    }
+                                                }
+
+                                            } // single select true
+                                            else {
+                                                // not support multiple selection
+                                            }
+
+                                        } // enum
+                                        else {
+
+                                            if (itemjson_j.optString("value") != null && !itemjson_j.optString("value").equals("")) {
+                                                upparam.put(itemjson_j.optString("name"),itemjson_j.optString("value"));
+                                            } else {
+
+                                                if (itemjson_j.optString("required").equals("true")) {
+                                                    cancommit = false;
+                                                    String mfield = String.format("%d. %@ is missing",fields.length() + 1,itemjson_j.optString("aname"));
+                                                    fields.put(mfield);
+
+                                                    IndexPath indexPath = get_indexpath1(addjson.optString("name"));
+                                                    if (alert) {
+                                                        listView.expandGroup(indexPath.section);
+                                                    }
+                                                    if (fields.length() == 1) {
+                                                        first_miss_pos = indexPath;
+                                                    }
+                                                }
+
+                                            } // else
+
+                                        } // else
+
+                                        subitem_data data1 = subitem_param_addto_alert(itemjson_j,upparam,alert);
+                                        upparam = data1.params;
+                                        for (int fl = 0; fl < data1.missingfields.length(); fl++) {
+                                            fields.put(data1.missingfields.opt(fl));
+                                        }
+
+                                    } // for j
+
+                                } // for i
+
+                            } // addjson control action
+                            else {
+                                if (addjson.optString("value") != null && !addjson.optString("value").isEmpty()) {
+                                    upparam.put(key,addjson.optString("value"));
+                                } else {
+                                    if (addjson.optString("required").equals("true")) {
+                                        cancommit = false;
+                                        String mfield = String.format("%d. %@ is missing",fields.length() + 1,addjson.optString("aname"));
+                                        fields.put(mfield);
+
+                                        IndexPath indexPath = get_indexpath1(addjson.optString("name"));
+                                        if (alert) {
+                                            listView.expandGroup(indexPath.section);
+                                        }
+                                        if (fields.length() == 1) {
+                                            first_miss_pos = indexPath;
+                                        }
+                                    }
+                                }
+                            }
+                            subitem_data data2 = subitem_param_addto_alert(addjson,upparam,alert);
+                            upparam = data2.params;
+                            for (int fl = 0; fl < data2.missingfields.length(); fl++) {
+                                fields.put(data2.missingfields.opt(fl));
+                            }
+
+                        } // for l
+
+                    } // check == 1 && subjson != null && !active
+
+                } // for k
+
+            } // enum single select
+
+            data.params = upparam;
+            data.missingfields = fields;
+
+            return data;
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public static class IndexPath {
+        public int section;
+        public int row;
+    }
+
+    public IndexPath first_miss_pos;
+
+    public IndexPath get_indexpath1(String name) {
+        if (first_miss_pos != null) {
+            return first_miss_pos;
+        }
+
+        for (int i = 0; i < content_data_control.length();i++) {
+            JSONArray items = content_data_control.optJSONArray(i);
+            for (int j = 0; j < items.length(); j++) {
+                JSONObject item = items.optJSONObject(j);
+                String item_name = item.optString("name");
+                if (item_name.equals(name)) {
+                    IndexPath indexPath = new IndexPath();
+                    indexPath.section = i;
+                    indexPath.row = j;
+                    return indexPath;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    public JSONObject check_cancomit(boolean alert) {
+        first_miss_pos = null;
+        cancommit =  true;
+
+        try {
+
+            JSONArray fields = new JSONArray();
+            JSONObject upparams = new JSONObject();
+
+            int section_count = content_data_control.length();
+            for (int i = 0; i < section_count; i++) {
+
+                JSONArray sectionjson = content_data_control.optJSONArray(i);
+                int item_count = sectionjson.length();
+                for (int j = 0; j < item_count; j++) {
+                    JSONObject itemjson = sectionjson.optJSONObject(j);
+                    String key = itemjson.optString("name");
+                    if (key == null || key.length() == 0) {
+                        continue;
+                    }
+
+                    if (itemjson.optString("control").equals("enum")) {
+                        String single_select = itemjson.optString("single_select");
+                        if (single_select.equals("true")) {
+                            JSONObject cadejson = itemjson.optJSONObject("cadedate");
+                            int count = cadejson.optInt("count");
+                            boolean setvalue = false;
+                            for (int cc = 0; cc < count; cc++) {
+                                JSONObject valjson = cadejson.optJSONObject("val_" + cc);
+                                if (valjson.optInt("check") == 1) {
+                                    upparams.put(itemjson.optString("name"),valjson.optString("value_id"));
+                                    setvalue = true;
+                                    break;
+                                }
+                            } // for cc
+
+                            if (itemjson.optString("required").equals("true") && setvalue == false) {
+                                cancommit = false;
+                                String mfield = String.format("%d. %s is missing",fields.length() + 1,itemjson.optString("aname"));
+
+                                fields.put(mfield);
+
+                                IndexPath indexPath = get_indexpath1(itemjson.optString("name"));
+                                if (alert) {
+                                    listView.expandGroup(indexPath.section);
+                                }
+                                if (fields.length() == 1) {
+                                    first_miss_pos = indexPath;
+                                }
+                            }
+
+                        } // single select true
+                        else { // multiple selection
+
+                            JSONArray checked = new JSONArray();
+                            JSONObject cadejson = itemjson.optJSONObject("cadedate");
+                            int count = cadejson.optInt("count");
+                            for (int cc = 0; cc < count; cc++) {
+                                JSONObject valjson = cadejson.optJSONObject("val_" + cc);
+                                if (valjson.optInt("check") == 1) {
+                                    checked.put(valjson.optString("value_id"));
+                                } // check == 1
+                            } // for cc
+                            if (itemjson.optString("required").equals("true") && checked.length() == 0) {
+
+                                cancommit = false;
+                                String mfield = String.format("%d. %s is missing",fields.length() + 1,itemjson.optString("aname"));
+
+                                fields.put(mfield);
+
+                                IndexPath indexPath = get_indexpath1(itemjson.optString("name"));
+                                if (alert) {
+                                    listView.expandGroup(indexPath.section);
+                                }
+                                if (fields.length() == 1) {
+                                    first_miss_pos = indexPath;
+                                }
+
+                            } // required && checked.length == 0
+                            else {
+                                String string = checked.join(",");
+                                upparams.put(itemjson.optString("name"),string);
+                            }
+
+                        }
+
+                    } // enum
+                    else if (itemjson.optString("control").equals("action")) {
+
+                        if (itemjson.optString("required").equals("true") && itemjson.opt("data") == null) {
+                            cancommit = false;
+                            String mfield = String.format("%d. %s is missing",fields.length() + 1,itemjson.optString("aname"));
+
+                            fields.put(mfield);
+
+                            IndexPath indexPath = get_indexpath1(itemjson.optString("name"));
+                            if (alert) {
+                                listView.expandGroup(indexPath.section);
+                            }
+                            if (fields.length() == 1) {
+                                first_miss_pos = indexPath;
+                            }
+
+                        }
+
+                    } // action
+                    else if (itemjson.optString("control").equals("signature")) {
+
+                        if (itemjson.optString("required").equals("true") && itemjson.opt("value") == null) {
+                            cancommit = false;
+                            String mfield = String.format("%d. %s is missing",fields.length() + 1,itemjson.optString("aname"));
+
+                            fields.put(mfield);
+
+                            IndexPath indexPath = get_indexpath1(itemjson.optString("name"));
+                            if (alert) {
+                                listView.expandGroup(indexPath.section);
+                            }
+                            if (fields.length() == 1) {
+                                first_miss_pos = indexPath;
+                            }
+                        }
+
+                    } // signature
+                    else if (itemjson.optString("control").equals("switch")) {
+
+                        String valuestr = itemjson.optString("value");
+                        upparams.put(itemjson.optString("name"),valuestr);
+
+                        String value = itemjson.optString("value");
+                        JSONObject boolitem = null;
+                        JSONObject subjson = null;
+                        if (value.equals("true")) {
+                            boolitem = itemjson.optJSONObject("true");
+                        } else {
+                            boolitem = itemjson.optJSONObject("false");
+                        }
+                        if (boolitem != null) {
+                            subjson = boolitem.optJSONObject("sub_item");
+                        }
+                        if (subjson != null) {
+
+                            int sub_count = subjson.optInt("count");
+                            for (int l = 0; l < sub_count; l++) {
+                                JSONObject modify_item = subjson.optJSONObject("item_" + l);
+                                if (modify_item.optString("value") != null && !modify_item.optString("value").isEmpty()) {
+                                    upparams.put(modify_item.optString("name"),modify_item.optString("value"));
+                                }
+                                else {
+                                    if (modify_item.optString("required").equals("true")) {
+                                        cancommit = false;
+                                        String mfield = String.format("%d. %s is missing",fields.length() + 1,itemjson.optString("aname"));
+
+                                        fields.put(mfield);
+
+                                        IndexPath indexPath = get_indexpath1(modify_item.optString("name"));
+                                        if (alert) {
+                                            listView.expandGroup(indexPath.section);
+                                        }
+                                        if (fields.length() == 1) {
+                                            first_miss_pos = indexPath;
+                                        }
+                                    }
+                                }
+                            }
+
+                        } // subjson != null
+
+                    } // switch
+                    else if (itemjson.optString("control").equals("img")) {
+
+                        if (itemjson.optString("avalue") != null && !itemjson.optString("avalue").isEmpty()) {
+                            upparams.put(itemjson.optString("name"),itemjson.optString("avalue"));
+                        } else {
+                            if (itemjson.optString("required").equals("true")) {
+                                cancommit = false;
+                                String mfield = String.format("%d. %s is missing",fields.length() + 1,itemjson.optString("aname"));
+
+                                fields.put(mfield);
+
+                                IndexPath indexPath = get_indexpath1(itemjson.optString("name"));
+                                if (alert) {
+                                    listView.expandGroup(indexPath.section);
+                                }
+                                if (fields.length() == 1) {
+                                    first_miss_pos = indexPath;
+                                }
+                            }
+                        }
+
+                    } // img
+                    else if (itemjson.optString("control").equals("edit")) {
+
+                        int min_length = itemjson.optInt("min_length");
+                        String check_len_val = itemjson.optString("value");
+                        if (check_len_val.length() < min_length) {
+                            cancommit = false;
+                            String mfield = String.format("%d. %s is too short",fields.length() + 1,itemjson.optString("aname"));
+                            if (check_len_val.length() == 0 && itemjson.optString("required").equals("true")) {
+                                mfield = String.format("%d. %s is missing",fields.length() + 1,itemjson.optString("aname"));
+                            }
+                            fields.put(mfield);
+
+                            IndexPath indexPath = get_indexpath1(itemjson.optString("name"));
+                            if (alert) {
+                                listView.expandGroup(indexPath.section);
+                            }
+                            if (fields.length() == 1) {
+                                first_miss_pos = indexPath;
+                            }
+
+                        } // < min_length
+                        else if (itemjson.optString("value") != null && !itemjson.optString("value").isEmpty()) {
+                            upparams.put(itemjson.optString("name"),itemjson.optString("value"));
+                        }
+                        else {
+                            if (itemjson.optString("required").equals("true")) {
+                                cancommit = false;
+                                String mfield = String.format("%d. %s is missing",fields.length() + 1,itemjson.optString("aname"));
+
+                                fields.put(mfield);
+
+                                IndexPath indexPath = get_indexpath1(itemjson.optString("name"));
+                                if (alert) {
+                                    listView.expandGroup(indexPath.section);
+                                }
+                                if (fields.length() == 1) {
+                                    first_miss_pos = indexPath;
+                                }
+                            }
+                        }
+
+                    } // edit
+                    else if (itemjson.optString("control").equals("range")) {
+
+                        String min_str = itemjson.optString("min_value","");
+                        String max_str = itemjson.optString("max_value","");
+
+                        String required = itemjson.optString("required");
+                        if (required != null && required.equals("true") && (min_str.length() < 1 && max_str.length() < 1)) {
+                            cancommit = false;
+                            String mfield = itemjson.optString("aname") + " is missing";
+                            fields.put(mfield);
+                        } else {
+                            JSONObject range_obj = new JSONObject();
+                            range_obj.put("min",min_str);
+                            range_obj.put("max",max_str);
+                            upparams.put(itemjson.optString("name"),range_obj.toString());
+                        }
+
+                    } // range
+                    else {
+
+                        if (itemjson.optString("value") != null && !itemjson.optString("value").isEmpty()) {
+                            upparams.put(itemjson.optString("name"),itemjson.optString("value"));
+                        } else {
+                            if (itemjson.optString("required").equals("true")) {
+                                cancommit = false;
+                                String mfield = String.format("%d. %s is missing",fields.length() + 1,itemjson.optString("aname"));
+
+                                fields.put(mfield);
+
+                                IndexPath indexPath = get_indexpath1(itemjson.optString("name"));
+                                if (alert) {
+                                    listView.expandGroup(indexPath.section);
+                                }
+                                if (fields.length() == 1) {
+                                    first_miss_pos = indexPath;
+                                }
+                            }
+                        }
+
+                    }
+
+                } // for j
+
+            } // for i
+
+            if (cancommit == false && alert) {
+
+                String missfields = fields.join("\n");
+                String msg = missfields;
+
+                new AlertDialog.Builder(mCtx)
+                        .setTitle("Warning")
+                        .setMessage(msg)
+                        .setPositiveButton("OK",null)
+                        .show();
+
+                content_data_control = translateChange(content_data_download,changed_data);
+                adapter.notifyDataSetChanged();
+                listView.setSelectedChild(first_miss_pos.section,first_miss_pos.row,true);
+                return upparams;
+
+
+            } else {
+                cancommit = true;
+            }
+            return upparams;
+
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+
+    public static int COMMON_EDITOR_CELL_TYPE_ACTION = 0;
+    public static int COMMON_EDITOR_CELL_TYPE_EDIT = 1;
+    public static int COMMON_EDITOR_CELL_TYPE_ENUM = 2;
+    public static int COMMON_EDITOR_CELL_TYPE_IMAGE = 3;
+    public static int COMMON_EDITOR_CELL_TYPE_LABLE = 4;
+    public static int COMMON_EDITOR_CELL_TYPE_MODEL = 5;
+    public static int COMMON_EDITOR_CELL_TYPE_MULTIPLE_ACTION = 6;
+    public static int COMMON_EDITOR_CELL_TYPE_SIGNATURE = 7;
+    public static int COMMON_EDITOR_CELL_TYPE_SWITCH = 8;
+    public static int COMMON_EDITOR_CELL_TYPE_TEXT_VIEW = 9;
+    public static int COMMON_EDITOR_CELL_TYPE_SECTION_HEADER = 10;
+    public static int COMMON_EDITOR_CELL_TYPE_RANGE = 11;
+    public static int COMMON_EDITOR_CELL_TYPE_DATE_RANGE = 12;
+    public static int COMMON_EDITOR_CELL_TYPE_AUTO_COMPLETE = 13;
+
+    /**
+     * ExpandListView Adapter
+     * */
+    public JSONArray content_data_control;
+    public JSONObject content_data_download;
+
+    public class ExpandAdapter extends BaseExpandableListAdapter {
+
+        private Context mCtx;
+
+        public ExpandAdapter(Context ctx) {
+            mCtx = ctx;
+        }
+
+        @Override
+        public int getGroupCount() {
+           if (content_data_control != null) {
+               return content_data_control.length();
+           } else {
+               return 0;
+           }
+        }
+
+        @Override
+        public int getChildrenCount(int groupPosition) {
+            if (content_data_download == null) {
+                return 0;
+            }
+            JSONObject section_json = content_data_download.optJSONObject("section_" + groupPosition);
+            boolean hide = section_json.optBoolean("hide");
+            if (hide) {
+                return 0;
+            } else {
+                JSONArray section = content_data_control.optJSONArray(groupPosition);
+                return section.length();
+            }
+        }
+
+        @Override
+        public Object getGroup(int groupPosition) {
+            if (content_data_control == null) {
+                return null;
+            }
+            JSONArray section = content_data_control.optJSONArray(groupPosition);
+            return section;
+        }
+
+        @Override
+        public Object getChild(int groupPosition, int childPosition) {
+            if (content_data_control == null) {
+                return null;
+            }
+            JSONArray section = content_data_control.optJSONArray(groupPosition);
+            JSONObject item = section.optJSONObject(childPosition);
+            return item;
+        }
+
+        @Override
+        public long getGroupId(int groupPosition) {
+            return groupPosition;
+        }
+
+        @Override
+        public long getChildId(int groupPosition, int childPosition) {
+            return groupPosition * 1000 + childPosition;
+        }
+
+        @Override
+        public boolean hasStableIds() {
+            return true;
+        }
+
+        @Override
+        public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
+
+            JSONObject section_json = content_data_download.optJSONObject("section_" + groupPosition);
+
+            CommonEditorSectionHeaderHolder holder;
+            if (convertView == null) {
+                convertView = LayoutInflater.from(mCtx).inflate(R.layout.common_editor_section_header,null);
+                holder = new CommonEditorSectionHeaderHolder(mCtx,convertView);
+            } else {
+                holder = (CommonEditorSectionHeaderHolder)convertView.getTag();
+            }
+            setUpSectionHeaderCellHolder(holder,convertView,section_json,groupPosition,-1);
+            holder.clickSectionHeader(isExpanded);
+
+
+            return convertView;
+        }
+
+        @Override
+        public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
+
+            JSONObject item_json = (JSONObject) getChild(groupPosition,childPosition);
+            String control = null;
+            boolean readonly = false;
+            try {
+
+                control = item_json.getString("control");
+
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+
+
+            CommonEditorCellHolder holder;
+            if (convertView == null) {
+
+                if (control != null) {
+                    if (control.equals("text_view")) {
+                        convertView = LayoutInflater.from(mCtx).inflate(R.layout.common_editor_text_view_cell_small,null);
+                        holder = new CommonEditorTextViewCellHolder(mCtx,convertView);
+                        setUpTextViewCellHolder((CommonEditorTextViewCellHolder) holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    } else if (control.equals("img")) {
+                        convertView = LayoutInflater.from(mCtx).inflate(R.layout.common_editor_image_cell_small,null);
+                        holder = new CommonEditorImageCellHolder(mCtx,convertView);
+                        setUpImageCellHolder((CommonEditorImageCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    } else if (control.equals("edit")) {
+                        String autoComplete = item_json.optString("autocomplete");
+                        if (autoComplete != null && autoComplete.equals("true")) {
+                            convertView = LayoutInflater.from(mCtx).inflate(R.layout.common_editor_edit_auto_complete_cell_small,null);
+                            holder = new CommonEditorEditAutoCompleteCellHolder(mCtx,convertView);
+                            setUpEditAutoCompleteCellHolder((CommonEditorEditAutoCompleteCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+                        } else {
+                            convertView = LayoutInflater.from(mCtx).inflate(R.layout.common_editor_edit_cell_small,null);
+                            holder = new CommonEditorEditCellHolder(mCtx,convertView);
+                            setUpEditCellHolder((CommonEditorEditCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+                        }
+
+                    } else if (control.equals("text")) {
+                        convertView = LayoutInflater.from(mCtx).inflate(R.layout.common_editor_label_cell_small,null);
+                        holder = new CommonEditorLabelCellHolder(mCtx,convertView);
+                        setUpLabelCellHolder((CommonEditorLabelCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    } else if (control.equals("action")) {
+                        convertView = LayoutInflater.from(mCtx).inflate(R.layout.common_editor_action_cell,null);
+                        holder = new CommonEditorActionCellHolder(mCtx,convertView);
+                        setUpActionCellHolder((CommonEditorActionCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    } else if (control.equals("multi_action")) {
+                        convertView = LayoutInflater.from(mCtx).inflate(R.layout.common_editor_multiple_action_cell,null);
+                        holder = new CommonEditorMultipleActionCellHolder(mCtx,convertView);
+                        setUpMultipleActionCellHolder((CommonEditorMultipleActionCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    } else if (control.equals("switch")) {
+                        convertView = LayoutInflater.from(mCtx).inflate(R.layout.common_editor_switch_cell_small,null);
+                        holder = new CommonEditorSwitchCellHolder(mCtx,convertView);
+                        setUpSwitchCellHolder((CommonEditorSwitchCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    } else if (control.equals("enum")) {
+                        convertView = LayoutInflater.from(mCtx).inflate(R.layout.common_editor_enum_cell_small,null);
+                        holder = new CommonEditorEnumCellHolder(mCtx,convertView);
+                        setUpEnumCellHolder((CommonEditorEnumCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    } else if (control.equals("model")) {
+                        convertView = LayoutInflater.from(mCtx).inflate(R.layout.common_editor_model_cell,null);
+                        holder = new CommonEditorModelCellHolder(mCtx,convertView);
+                        setUpModelCellHolder((CommonEditorModelCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    } else if (control.equals("datepicker")) {
+                        convertView = LayoutInflater.from(mCtx).inflate(R.layout.common_editor_enum_cell_small,null);
+                        holder = new CommonEditorEnumCellHolder(mCtx,convertView);
+                        setUpDatePickerCellHolder((CommonEditorEnumCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    } else if (control.equals("monthpicker")) {
+                        convertView = LayoutInflater.from(mCtx).inflate(R.layout.common_editor_enum_cell_small,null);
+                        holder = new CommonEditorEnumCellHolder(mCtx,convertView);
+                        setUpMonthPickerCellHolder((CommonEditorEnumCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    } else if (control.equals("signature")) {
+                        convertView = LayoutInflater.from(mCtx).inflate(R.layout.common_editor_signature_cell_small,null);
+                        holder = new CommonEditorSignatureCellHolder(mCtx,convertView);
+                        setUpSignatureCellHolder((CommonEditorSignatureCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    }  else if (control.equals("range")) {
+
+                        String type = item_json.optString("type");
+                        if (type != null && type.equals("date")) {
+                            convertView = LayoutInflater.from(mCtx).inflate(R.layout.common_editor_date_range_cell,null);
+                            holder = new CommonEditorDateRangeCellHolder(mCtx,convertView);
+                            setUpDateRangeCellHolder((CommonEditorDateRangeCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+                        } else {
+                            convertView = LayoutInflater.from(mCtx).inflate(R.layout.common_editor_range_cell,null);
+                            holder = new CommonEditorRangeCellHolder(mCtx,convertView);
+                            setUpRangeCellHolder((CommonEditorRangeCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+                        }
+
+
+
+                    } else {
+                        convertView = LayoutInflater.from(mCtx).inflate(R.layout.common_editor_edit_cell_small,null);
+                        holder = new CommonEditorEditCellHolder(mCtx,convertView);
+                        setUpEditCellHolder((CommonEditorEditCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    }
+                } else {
+                    convertView = LayoutInflater.from(mCtx).inflate(R.layout.common_editor_edit_cell_small,null);
+                    holder = new CommonEditorEditCellHolder(mCtx,convertView);
+                    setUpEditCellHolder((CommonEditorEditCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+                }
+
+            } else {
+
+                if (control != null) {
+                    if (control.equals("text_view")) {
+                        holder = (CommonEditorTextViewCellHolder)convertView.getTag();
+                        setUpTextViewCellHolder((CommonEditorTextViewCellHolder) holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    } else if (control.equals("img")) {
+                        holder = (CommonEditorImageCellHolder)convertView.getTag();
+                        setUpImageCellHolder((CommonEditorImageCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    } else if (control.equals("edit")) {
+
+                        String autoComplete = item_json.optString("autocomplete");
+                        if (autoComplete != null && autoComplete.equals("true")) {
+                            holder = (CommonEditorEditAutoCompleteCellHolder)convertView.getTag();
+                            setUpEditAutoCompleteCellHolder((CommonEditorEditAutoCompleteCellHolder) holder,convertView,item_json,readonly,groupPosition,childPosition);
+                        } else {
+                            holder = (CommonEditorEditCellHolder)convertView.getTag();
+                            setUpEditCellHolder((CommonEditorEditCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+                        }
+
+
+                    } else if (control.equals("text")) {
+                        holder = (CommonEditorLabelCellHolder)convertView.getTag();
+                        setUpLabelCellHolder((CommonEditorLabelCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    } else if (control.equals("action")) {
+                        holder = (CommonEditorActionCellHolder)convertView.getTag();
+                        setUpActionCellHolder((CommonEditorActionCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    } else if (control.equals("multi_action")) {
+                        holder = (CommonEditorMultipleActionCellHolder)convertView.getTag();
+                        setUpMultipleActionCellHolder((CommonEditorMultipleActionCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    } else if (control.equals("switch")) {
+                        holder = (CommonEditorSwitchCellHolder)convertView.getTag();
+                        setUpSwitchCellHolder((CommonEditorSwitchCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    } else if (control.equals("enum")) {
+                        holder = (CommonEditorEnumCellHolder)convertView.getTag();
+                        setUpEnumCellHolder((CommonEditorEnumCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    } else if (control.equals("model")) {
+                        holder = (CommonEditorModelCellHolder)convertView.getTag();
+                        setUpModelCellHolder((CommonEditorModelCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    } else if (control.equals("datepicker")) {
+                        holder = (CommonEditorEnumCellHolder)convertView.getTag();
+                        setUpDatePickerCellHolder((CommonEditorEnumCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    } else if (control.equals("monthpicker")) {
+                        holder = (CommonEditorEnumCellHolder)convertView.getTag();
+                        setUpMonthPickerCellHolder((CommonEditorEnumCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    } else if (control.equals("signature")) {
+                        holder = (CommonEditorSignatureCellHolder)convertView.getTag();
+                        setUpSignatureCellHolder((CommonEditorSignatureCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    }  else if (control.equals("range")) {
+
+                        String type = item_json.optString("type");
+                        if (type != null && type.equals("date")) {
+                            holder = (CommonEditorDateRangeCellHolder)convertView.getTag();
+                            setUpDateRangeCellHolder((CommonEditorDateRangeCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+                        } else {
+                            holder = (CommonEditorRangeCellHolder)convertView.getTag();
+                            setUpRangeCellHolder((CommonEditorRangeCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+                        }
+
+
+                    }  else {
+                        holder = (CommonEditorEditCellHolder)convertView.getTag();
+                        setUpEditCellHolder((CommonEditorEditCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                    }
+                } else {
+                    holder = (CommonEditorEditCellHolder)convertView.getTag();
+                    setUpEditCellHolder((CommonEditorEditCellHolder)holder,convertView,item_json,readonly,groupPosition,childPosition);
+
+                }
+
+            }
+
+            return convertView;
+        }
+
+        @Override
+        public boolean isChildSelectable(int groupPosition, int childPosition) {
+            return true;
+        }
+
+        @Override
+        public int getChildTypeCount() {
+
+            return 14;
+        }
+
+        @Override
+        public int getChildType(int groupPosition, int childPosition) {
+            JSONObject item_json = (JSONObject) getChild(groupPosition,childPosition);
+            String control;
+            try {
+                control = item_json.getString("control");
+
+            } catch (Exception e) {
+                e.printStackTrace();
+                return COMMON_EDITOR_CELL_TYPE_EDIT;
+            }
+
+            if (control != null) {
+                if (control.equals("text_view")) {
+                    return COMMON_EDITOR_CELL_TYPE_TEXT_VIEW;
+                } else if (control.equals("img")) {
+                    return COMMON_EDITOR_CELL_TYPE_IMAGE;
+                } else if (control.equals("edit")) {
+                    String autoComplete = item_json.optString("autocomplete");
+                    if (autoComplete != null && autoComplete.equals("true")) {
+                        return COMMON_EDITOR_CELL_TYPE_AUTO_COMPLETE;
+                    } else {
+                        return COMMON_EDITOR_CELL_TYPE_EDIT;
+                    }
+                } else if (control.equals("text")) {
+                    return COMMON_EDITOR_CELL_TYPE_LABLE;
+                } else if (control.equals("action")) {
+                    return COMMON_EDITOR_CELL_TYPE_ACTION;
+                } else if (control.equals("multi_action")) {
+                    return COMMON_EDITOR_CELL_TYPE_MULTIPLE_ACTION;
+                } else if (control.equals("switch")) {
+                    return COMMON_EDITOR_CELL_TYPE_SWITCH;
+                } else if (control.equals("enum")) {
+                    return COMMON_EDITOR_CELL_TYPE_ENUM;
+                } else if (control.equals("model")) {
+                    return COMMON_EDITOR_CELL_TYPE_MODEL;
+                } else if (control.equals("datepicker")) {
+                    return COMMON_EDITOR_CELL_TYPE_ENUM;
+                } else if (control.equals("monthpicker")) {
+                    return COMMON_EDITOR_CELL_TYPE_ENUM;
+                } else if (control.equals("signature")) {
+                    return COMMON_EDITOR_CELL_TYPE_SIGNATURE;
+                } else if (control.equals("header")){
+                    return COMMON_EDITOR_CELL_TYPE_SECTION_HEADER;
+                } else if (control.equals("range")){
+                    String type = item_json.optString("type");
+                    if (type != null && type.equals("date")) {
+                        return COMMON_EDITOR_CELL_TYPE_DATE_RANGE;
+                    } else {
+                        return COMMON_EDITOR_CELL_TYPE_RANGE;
+                    }
+
+                } else {
+                    return COMMON_EDITOR_CELL_TYPE_EDIT;
+                }
+            } else {
+                return COMMON_EDITOR_CELL_TYPE_EDIT;
+            }
+        }
+    }
+
+    public class ListChildViewClickListener implements ExpandableListView.OnChildClickListener {
+
+        String requesturl = null;
+        @Override
+        public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
+            try {
+
+                Intent intent = null;
+                int request_code = -1;
+
+                boolean readonly = content_data_download.optBoolean("readonly");
+
+                JSONObject item_json = content_data_control.optJSONArray(groupPosition).optJSONObject(childPosition);
+                String control = item_json.optString("control");
+                if (control.equals("enum")) {
+                    int disable = item_json.optInt("disable");
+                    if (disable == 1 || readonly) {
+                        return false;
+                    }
+                    JSONObject cadedate_json = item_json.optJSONObject("cadedate");
+                    String single_select = item_json.optString("single_select");
+                    String title = item_json.optString("aname");
+                    int max_select = item_json.optInt("max");
+                    boolean singleSelect = single_select.toLowerCase().equals("true");
+                    String cadedate_str = cadedate_json.toString();
+                    intent = new EnumSlectActivity.Builder().build(mCtx,title,max_select,groupPosition,childPosition,cadedate_str,singleSelect,true);
+                    boolean sort = item_json.getBoolean("sort");
+                    if (sort) {
+                        intent = new EnumSelectAndSortActivity.Builder().build(mCtx,title,max_select,groupPosition,childPosition,cadedate_str,singleSelect,true);
+                    }
+                    request_code = 10;
+
+                } // enum
+                else if (control.equals("action")) {
+
+                    String value = item_json.optString("value");
+                    if (value.equals("new_addr")) {
+                        AddressEditorActivity.Builder builder = new AddressEditorActivity.Builder();
+                        intent = builder.build(mCtx,URL_REMOTE,requesturl,null,null,groupPosition,childPosition);
+                        request_code = 2;
+
+                    } // new addr
+                    else if (value.equals("credit_card")) {
+
+                        JSONObject data = item_json.optJSONObject("data");
+                        int url_type;
+                        JSONObject download_data;
+                        if (data != null) {
+                            download_data = data;
+                            url_type = URL_NONE;
+                            requesturl = null;
+                        } else {
+                            download_data = null;
+                            url_type = URL_REMOTE;
+                            requesturl = "";
+                        }
+                        intent = new CreditCardEditorActivity.Builder().build(mCtx,url_type,requesturl,Application.order_code,null,null,download_data,groupPosition,childPosition);
+                        request_code = 3;
+                    }
+                    else if (value.equals("Sales_Order_Freight_Bill_To")) {
+
+                        request_code = 4;
+                        intent = new ContactListActivity.Builder().build(mCtx,null,null,value,true,groupPosition,childPosition);
+
+                    }
+                    else if (value.equals("Sales_Order_Ship_From")) {
+
+                        request_code = 5;
+                        intent = new ContactListActivity.Builder().build(mCtx,null,null,value,true,groupPosition,childPosition);
+
+                    }
+                    else if (value.equals("Sales_Order_Customer")) {
+
+                        request_code = 6;
+                        intent = new ContactListActivity.Builder().build(mCtx,null,null,value,true,groupPosition,childPosition);
+
+                    }
+                    else if (value.equals("Sales_Order_Merchandise_Bill_To")) {
+
+                        request_code = 7;
+                        intent = new ContactListActivity.Builder().build(mCtx,null,null,value,true,groupPosition,childPosition);
+
+                    }
+                    else if (value.equals("Contact_Return_To")) {
+
+                        request_code = 8;
+                        intent = new ContactListActivity.Builder().build(mCtx,null,null,value,true,groupPosition,childPosition);
+
+                    }
+                    else if (value.equals("Sales_Order_Ship_To")) {
+
+                        request_code = 9;
+                        intent = new ContactListActivity.Builder().build(mCtx,null,null,value,true,groupPosition,childPosition);
+                    }
+
+                } // action
+                else if (control.equals("datepicker")) {
+
+                    request_code = 11;
+
+                    String value = item_json.optString("value");
+                    String type = item_json.optString("type");
+
+                    SimpleDateFormat dateFormatter = new SimpleDateFormat();
+                    int pickerMode = 0;
+                    if (type.toLowerCase().equals("date")) {
+                        pickerMode = 0; // Date
+                        dateFormatter.applyPattern("yyyy/MM/dd");
+                    }
+                    else if (type.toLowerCase().equals("time")) {
+                        pickerMode = 1; // time
+                        dateFormatter.applyPattern("HH:mm:ss");
+                    }
+                    else {
+                        pickerMode = 2; // date and time
+                        dateFormatter.applyPattern("yyyy/MM/dd HH:mm:ss");
+                    }
+
+                    Date date = dateFormatter.parse(value);
+                    intent = new DatePickerActivity.Builder().build(mCtx,date,dateFormatter,pickerMode,value,groupPosition,childPosition);
+
+
+                } // date picker
+                else if (control.equals("monthpicker")) {
+
+                    request_code = 12;
+                    String value = item_json.optString("value");
+                    if (value == null || value.isEmpty()) {
+                        value = "1/2017";
+                    }
+
+
+                    intent = new MonthPickerActivity.Builder().build(mCtx,value,groupPosition,childPosition);
+
+                } // month picker
+                else if (control.equals("signature")) {
+
+                    request_code = 13;
+                    intent = new SignatureActivity.Builder().build(mCtx,groupPosition,childPosition);
+
+                }
+
+                if (intent != null) {
+                    startActivityForResult(intent,request_code);
+                }
+
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            return false;
+        }
+    }
+
+    public boolean cancommit = false;
+
+
+    public void setUpTextViewCellHolder(CommonEditorTextViewCellHolder holder, View cell, JSONObject item_json, boolean readonly, int group, int child) {
+        String control = null;
+        String required = null;
+        String title = null;
+        String value = null;
+        String align = "";
+        int capital = 0;
+        int disable = 0;
+
+        // 重用时先保存
+        if (holder.text_view.getText().length() > 0) {
+            editTextEndEditing(holder.text_view,false,holder.group,holder.child);
+        }
+
+        holder.group = group;
+        holder.child = child;
+        holder.title_lb.setText(null);
+        holder.text_view.setText(null);
+
+        try {
+            control = item_json.optString("control");
+            required = item_json.optString("required");
+            title = item_json.optString("aname");
+            value = item_json.optString("value");
+            align = item_json.optString("align");
+            capital = item_json.optInt("capital");
+            disable = item_json.optInt("disable");
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        if (align.equals("right")) {
+            holder.text_view.setGravity(TOP | RIGHT);
+        } else {
+            holder.text_view.setGravity(TOP | LEFT);
+        }
+
+        /**设置大写模式*/
+        switch (capital) {
+            case 1: {
+                holder.text_view.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
+            }
+            break;
+            case 2: {
+                holder.text_view.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE  | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES);
+            }
+            break;
+            case 3: {
+                holder.text_view.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE  | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS);
+            }
+            break;
+            default: {
+                holder.text_view.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE  | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
+            }
+            break;
+        }
+
+        if (disable == 1 || readonly) {
+            holder.text_view.setEnabled(false);
+            holder.text_view.setTextColor(Color.LTGRAY);
+        } else {
+            holder.text_view.setEnabled(true);
+            holder.text_view.setTextColor(Color.BLACK);
+        }
+
+        holder.title_lb.setText(title);
+
+        holder.text_view.setTag(group + "_" + child + "_" + "TextView");
+        holder.text_view.setText(value);
+        holder.text_view.addTextChangedListener(new TextViewTextWatcher(mCtx,holder.text_view,group,child));
+        holder.text_view.setOnFocusChangeListener(new EditTextFocusListener(mCtx,holder.text_view,group,child));
+
+
+        if (required.equals("true")) {
+            holder.startMark.setVisibility(View.VISIBLE);
+        } else {
+            holder.startMark.setVisibility(View.INVISIBLE);
+        }
+
+        if (cancommit == false && required.equals("true") && (value == null || value.length() == 0)) {
+            // 阴影 red
+            holder.title_lb.setBackground(getResources().getDrawable(R.drawable.red_border));
+        } else {
+            // 无阴影
+            holder.title_lb.setBackground(null);
+        }
+
+    }
+
+    public void setUpImageCellHolder(CommonEditorImageCellHolder holder, View cell, JSONObject item_json, boolean readonly, int group, int child) {
+
+        String title = null;
+        String value = null;
+        String img_url_0 = null;
+        String img_url_1 = null;
+        String img_url_2 = null;
+        String img_url_up_0 = null;
+        String img_url_up_1 = null;
+        String img_url_up_2 = null;
+        int disable = 0;
+
+        holder.group = group;
+        holder.child = child;
+        holder.title_lb.setText(null);
+        holder.desc_lb.setText(null);
+        holder.img_btn_0.setImageBitmap(null);
+        holder.img_btn_1.setImageBitmap(null);
+        holder.img_btn_2.setImageBitmap(null);
+
+//        LinearLayout.LayoutParams layoutParams0 = (LinearLayout.LayoutParams)holder.img_btn_0.getLayoutParams();
+//        layoutParams0.height = layoutParams0.width;
+//        holder.img_btn_0.setLayoutParams(layoutParams0);
+//
+//        LinearLayout.LayoutParams layoutParams1 = (LinearLayout.LayoutParams)holder.img_btn_1.getLayoutParams();
+//        layoutParams1.height = layoutParams1.width;
+//        holder.img_btn_1.setLayoutParams(layoutParams1);
+//
+//        LinearLayout.LayoutParams layoutParams2 = (LinearLayout.LayoutParams)holder.img_btn_2.getLayoutParams();
+//        layoutParams2.height = layoutParams2.width;
+//        holder.img_btn_2.setLayoutParams(layoutParams2);
+
+        try {
+
+            title = item_json.optString("aname");
+            value = item_json.optString("value");
+            disable = item_json.optInt("disable");
+            img_url_0 = item_json.optString("img_url_0");
+            img_url_up_0 = item_json.optString("img_url_aname_0");
+            img_url_1 = item_json.optString("img_url_1");
+            img_url_up_1 = item_json.optString("img_url_aname_1");
+            img_url_2 = item_json.optString("img_url_2");
+            img_url_up_2 = item_json.optString("img_url_aname_2");
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        if (disable == 1 || readonly) {
+            holder.editable = false;
+        } else {
+            holder.editable = true;
+        }
+
+        holder.title_lb.setText(title);
+        holder.desc_lb.setText(value);
+
+        Bitmap placeHolder = BitmapFactory.decodeResource(getResources(),R.drawable.not_found);
+        if (img_url_0 != null && !img_url_0.isEmpty()) {
+            Bitmap bmp0 = Utils.loadCacheImage(img_url_up_0,placeHolder);
+            if (bmp0 != null) {
+                holder.setImage0(img_url_up_0,bmp0);
+            } else {
+                // 异步记载数据
+                loadImageForPosition(group,child,0,img_url_up_0);
+            }
+        }
+
+        if (img_url_1 != null && !img_url_1.isEmpty()) {
+            Bitmap bmp1 = Utils.loadCacheImage(img_url_up_1,placeHolder);
+            if (bmp1 != null) {
+                holder.setImage1(img_url_up_1,bmp1);
+            } else {
+                // 异步记载数据
+                loadImageForPosition(group,child,1,img_url_up_1);
+            }
+        }
+
+        if (img_url_2 != null && !img_url_2.isEmpty()) {
+            Bitmap bmp2 = Utils.loadCacheImage(img_url_up_2,placeHolder);
+            if (bmp2 != null) {
+                holder.setImage2(img_url_up_2,bmp2);
+            } else {
+                // 异步记载数据
+                loadImageForPosition(group,child,2,img_url_up_2);
+            }
+        }
+
+    }
+
+    private void loadImageForPosition(int group, int child, int item_tag, final String path) {
+
+//        return;
+
+        if (path == null || path.isEmpty()) {
+            return;
+        }
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                HttpURLConnection cnn = null;
+                Bitmap bitmap = null;
+
+
+                try {
+
+                    bitmap = Utils.loadCacheImage(path,null);
+
+
+                    if (bitmap == null) {
+                        URL url = new URL(path);
+                        cnn = (HttpURLConnection)url.openConnection();
+                        cnn.setRequestMethod("GET");
+                        cnn.setUseCaches(false);
+                        cnn.setConnectTimeout(1500);
+                        cnn.setReadTimeout(1500);
+                        bitmap = BitmapFactory.decodeStream(cnn.getInputStream());
+                        if (bitmap == null) {
+                            // 缓存not found
+                            bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.not_found);
+                        }
+                    }
+
+
+                } catch (IOException e) {
+                    e.printStackTrace();
+
+                    bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.not_found);
+
+                } finally {
+                    if (cnn != null) {
+                        cnn.disconnect();
+                    }
+                    if (bitmap == null) {
+                        bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.not_found);
+                    }
+                    Utils.cacheImage(path,bitmap);
+                    // 更新数据,刷新行
+                    runOnUiThread(new Runnable() {
+                        @Override
+                        public void run() {
+                            adapter.notifyDataSetChanged();
+                        }
+                    });
+                }
+            }
+        }).start();
+    }
+
+    public void setUpEditCellHolder(final CommonEditorEditCellHolder holder, View cell, JSONObject item_json, boolean readonly, int group, int child) {
+        String title = null;
+        String value = null;
+        String align = null;
+        int capital = 0;
+        int disable = 0;
+        String keyboard = null;
+        String required = null;
+
+       if (holder.textWatcher != null) {
+           holder.text_field.removeTextChangedListener(holder.textWatcher);
+       }
+        // 重用时先保存
+        if (holder.text_field.getText().length() > 0) {
+            editTextEndEditing(holder.text_field,true,holder.group,holder.child);
+        }
+        holder.group = group;
+        holder.child = child;
+        holder.name_lb.setText(null);
+        holder.text_field.setText(null);
+
+        try {
+
+            required = item_json.optString("required");
+            title = item_json.optString("aname");
+            value = item_json.optString("value");
+            align = item_json.optString("align");
+            capital = item_json.optInt("capital");
+            disable = item_json.optInt("disable");
+            keyboard = item_json.optString("keyboard");
+
+            if (!keyboard.equals("number") && !keyboard.equals("int")) {
+                holder.text_field.setFilters(new InputFilter[]{});
+            } else {
+                int lenght = item_json.optInt("length");
+                holder.text_field.setFilters(new InputFilter[]{new InputFilter.LengthFilter(lenght)});
+            }
+
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        if (align != null && align.equals("right")) {
+            holder.text_field.setGravity(CENTER_VERTICAL | RIGHT);
+        } else {
+            holder.text_field.setGravity(CENTER_VERTICAL | LEFT);
+        }
+
+        int inputType = 0;
+        /**设置大写模式*/
+        switch (capital) {
+            case 1: {
+                inputType |= EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS;
+            }
+            break;
+            case 2: {
+                inputType |= EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES;
+            }
+            break;
+            case 3: {
+                inputType |= EditorInfo.TYPE_TEXT_FLAG_CAP_CHARACTERS;
+            }
+            break;
+            default: {
+                inputType |= EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS;
+            }
+            break;
+        }
+
+        if (keyboard != null) {
+            if (keyboard.equals("number")) {
+                inputType |= EditorInfo.TYPE_CLASS_NUMBER;
+            } else if (keyboard.equals("email")) {
+                inputType |= EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
+            } else if (keyboard.equals("phone")) {
+                inputType |= EditorInfo.TYPE_CLASS_PHONE;
+            } else {
+                inputType |= EditorInfo.TYPE_CLASS_TEXT;
+            }
+        }
+
+        holder.text_field.setInputType(inputType);
+
+        if (disable == 1 || readonly) {
+            holder.text_field.setEnabled(false);
+            holder.text_field.setTextColor(Color.LTGRAY);
+        } else {
+            holder.text_field.setEnabled(true);
+            holder.text_field.setTextColor(Color.BLACK);
+        }
+
+        holder.name_lb.setText(title);
+
+        holder.text_field.setTag(group + "_" + child + "_" + "TextFiled");
+        holder.text_field.setText(value);
+        if (holder.textWatcher == null) {
+            TextFieldTextWatcher textWatcher = new TextFieldTextWatcher(mCtx,holder.text_field,group,child);
+            holder.text_field.addTextChangedListener(textWatcher);
+            holder.textWatcher = textWatcher;
+        } else {
+            TextFieldTextWatcher textWatcher = (TextFieldTextWatcher)holder.textWatcher;
+            holder.text_field.addTextChangedListener(textWatcher);
+            textWatcher.group = group;
+            textWatcher.child = child;
+        }
+        holder.text_field.setOnFocusChangeListener(new EditTextFocusListener(mCtx,holder.text_field,group,child));
+
+
+
+
+        if (required != null && required.equals("true")) {
+            holder.startMark.setVisibility(View.VISIBLE);
+        } else {
+            holder.startMark.setVisibility(View.INVISIBLE);
+        }
+
+        if (cancommit == false && required != null && required.equals("true") && (value == null || value.length() == 0)) {
+            // 阴影 red
+            holder.name_lb.setBackground(getResources().getDrawable(R.drawable.red_border));
+        } else {
+            // 无阴影
+            holder.name_lb.setBackground(null);
+        }
+
+
+
+
+    }
+
+
+    public void setUpEditAutoCompleteCellHolder(final CommonEditorEditAutoCompleteCellHolder holder, View cell, JSONObject item_json, boolean readonly, int group, int child) {
+        setUpEditCellHolder(holder,cell,item_json,readonly,group,child);
+
+
+        holder.text_field.setThreshold(1);
+        if (holder.autoCompleteAdapter == null) {
+           int resourceId = R.layout.common_editor_auto_complete_list_cell;
+           int textViewId = R.id.auto_complete_value_tv;
+           CommonEditorAutoCompleteAdapter autoCompleteAdapter = new CommonEditorAutoCompleteAdapter(mCtx,resourceId, textViewId);
+           holder.text_field.setAdapter(autoCompleteAdapter);
+           holder.autoCompleteAdapter = autoCompleteAdapter;
+        } else {
+            ((CommonEditorAutoCompleteAdapter)holder.text_field.getAdapter()).clear();
+        }
+
+
+    }
+
+    private boolean can_see_price = true;
+    private boolean price_hidden = false;
+    public void setUpLabelCellHolder(CommonEditorLabelCellHolder holder, View cell, JSONObject item_json, boolean readonly, int group, int child) {
+
+        String title = null;
+        String value = null;
+        String align = null;
+        String color = null;
+        String type = null;
+
+        holder.group = group;
+        holder.child = child;
+        holder.title_lb.setText(null);
+        holder.value_lb.setText(null);
+
+        try {
+
+            title = item_json.optString("aname");
+            value = item_json.optString("value");
+            align = item_json.optString("align");
+            color = item_json.optString("color");
+            type = item_json.optString("type");
+
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        if (align.equals("right")) {
+            holder.value_lb.setGravity(CENTER_VERTICAL | RIGHT);
+        } else {
+            holder.value_lb.setGravity(CENTER_VERTICAL | LEFT);
+        }
+
+        if (type.equals("price")) {
+            if (can_see_price && price_hidden == false) {
+
+            } else {
+                value = null;
+            }
+        }
+
+        if (color.toLowerCase().equals("red")) {
+            holder.value_lb.setTextColor(Color.RED);
+        } else {
+            holder.value_lb.setTextColor(Color.BLACK);
+        }
+
+        holder.title_lb.setText(title);
+        holder.value_lb.setText(value);
+
+    }
+
+
+    public void setUpActionCellHolder(CommonEditorActionCellHolder holder, View cell, JSONObject item_json, boolean readonly, int group, int child) {
+
+        String title = null;
+        String value = null;
+        String required = null;
+        JSONObject data = null;
+
+        holder.group = group;
+        holder.child = child;
+        holder.action_lb.setText(null);
+
+        try {
+            title = item_json.optString("aname");
+            value = item_json.optString("value");
+            required = item_json.optString("required");
+            data = item_json.optJSONObject("data");
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        if (required.equals("true")) {
+            title = title + "*";
+        }
+
+        holder.action_lb.setText(title);
+        holder.action_code = value;
+
+        if (cancommit && required.equals("true") && data == null) {
+            // Shadow red
+        } else {
+            // no shadow
+        }
+
+    }
+
+    public void setUpMultipleActionCellHolder(CommonEditorMultipleActionCellHolder holder, View cell, JSONObject item_json, boolean readonly, int group, int child) {
+
+        int count = 0;
+
+        holder.group = group;
+        holder.child = child;
+
+        try {
+            count = item_json.optInt("count");
+            for (int i = 0; i < count; i++) {
+                JSONObject sub_action = item_json.optJSONObject("item_" + i);
+                String title = sub_action.optString("aname");
+                Button btn = null;
+                switch (i) {
+                    case 0: {
+                        btn = holder.btn0;
+                    }
+                    break;
+                    case 1: {
+                        btn = holder.btn1;
+                    }
+                    break;
+                    case 2: {
+                        btn = holder.btn2;
+                    }
+                    break;
+                    case 3: {
+                        btn = holder.btn3;
+                    }
+                    break;
+                }
+                if (btn != null) {
+                    btn.setText(title);
+                    btn.setOnClickListener(multipleActionClickListener);
+                    btn.setVisibility(View.VISIBLE);
+                    btn.setTag(group + "_" + child + "_" + i);
+                }
+            }
+            if (count < 4) {
+                holder.btn3.setVisibility(View.INVISIBLE);
+            }
+            if (count < 3) {
+                holder.btn2.setVisibility(View.INVISIBLE);
+            }
+            if (count < 2) {
+                holder.btn1.setVisibility(View.INVISIBLE);
+            }
+            if (count < 1) {
+                holder.btn0.setVisibility(View.INVISIBLE);
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    public void setUpSwitchCellHolder(CommonEditorSwitchCellHolder holder, View cell, JSONObject item_json, boolean readonly, int group, int child) {
+
+        String title = null;
+        String value = null;
+        String required = null;
+
+        holder.group = group;
+        holder.child = child;
+        holder.title_lb.setText(null);
+        holder.aSwitch.setTag(group + "_" + child + "_" + "switch");
+        try {
+
+            title = item_json.optString("aname");
+            value = item_json.optString("value");
+            required = item_json.optString("required");
+
+            holder.title_lb.setText(title);
+
+            if (required.equals("true")) {
+                holder.startMark.setVisibility(View.VISIBLE);
+            } else {
+                holder.startMark.setVisibility(View.INVISIBLE);
+            }
+
+
+            holder.aSwitch.setOnCheckedChangeListener(null);
+            if (value.toLowerCase().equals("true")) {
+                holder.aSwitch.setChecked(true);
+            } else {
+                holder.aSwitch.setChecked(false);
+            }
+            holder.aSwitch.setOnCheckedChangeListener(new SwitchCheckListener());
+
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    public void setUpEnumCellHolder(CommonEditorEnumCellHolder holder, View cell, JSONObject item_json, boolean readonly, int group, int child) {
+        String title = null;
+        String value = "";
+        JSONObject cadedate_json = null;
+        int disable = 0;
+        String align = null;
+        String required = null;
+
+        holder.group = group;
+        holder.child = child;
+        holder.title_lb.setText(null);
+        holder.value_lb.setText(null);
+
+        try {
+
+            title = item_json.optString("aname");
+            cadedate_json = item_json.optJSONObject("cadedate");
+            disable = item_json.optInt("disable");
+            align = item_json.optString("align");
+            required = item_json.optString("required");
+
+            if (disable == 1 && readonly) {
+                holder.value_lb.setTextColor(Color.LTGRAY);
+            } else {
+                holder.value_lb.setTextColor(Color.BLACK);
+            }
+
+            if (align != null && align.equals("right")) {
+                holder.value_lb.setGravity(CENTER_VERTICAL | RIGHT);
+            } else {
+                holder.value_lb.setGravity(CENTER_VERTICAL | LEFT);
+            }
+
+            int count = cadedate_json.optInt("count");
+            for (int i = 0; i < count; i++) {
+                JSONObject val_json = cadedate_json.optJSONObject("val_" + i);
+                if (val_json != null) {
+                    int check = val_json.optInt("check");
+                    if (check == 1) {
+                        value += val_json.getString("value") + " | ";
+                    }
+                }
+            }
+            if (value.length() > 1) {
+                value = value.substring(0,value.length() - 3);
+            }
+
+            holder.value_lb.setText(value);
+            holder.title_lb.setText(title);
+
+            if (required.equals("true")) {
+                holder.startMark.setVisibility(View.VISIBLE);
+            } else {
+                holder.startMark.setVisibility(View.INVISIBLE);
+            }
+
+
+            if (cancommit == false && required.equals("true") && (value == null || value.length() == 0)) {
+                // 阴影 red
+                holder.title_lb.setBackground(getResources().getDrawable(R.drawable.red_border));
+            } else {
+                // 无阴影
+                holder.title_lb.setBackground(null);
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    public void setUpModelCellHolder(CommonEditorModelCellHolder holder, View cell, JSONObject item_json, boolean readonly, int group, int child) {
+
+
+        holder.group = group;
+        holder.child = child;
+        holder.model_img_btn.setImageBitmap(null);
+        holder.desc_lb.setText(null);
+        holder.master_pack_lb.setText(null);
+        holder.old_price_lb.setText(null);
+        holder.discount_lb.setText(null);
+        holder.unit_price_lb.setText(null);
+        holder.discount_lb.setText(null);
+        holder.bundle_btn.setText(null);
+        holder.total_price_lb.setText(null);
+
+        try {
+            int count = item_json.optInt("count");
+            JSONObject combine_json = item_json.optJSONObject("combine");
+            holder.bundle_item = combine_json;
+            double dprice = 0.0f;
+            if (holder.bundle_item != null) {
+                int citem = 0;
+                int bcount = holder.bundle_item.optInt("count");
+                for (int bc = 0; bc < bcount; bc++) {
+                    JSONObject bitem = holder.bundle_item.optJSONObject("item_" + bc);
+                    int modulus = bitem.optInt("modulus");
+                    citem += modulus;
+                    double uprice = bitem.optDouble("unit_price");
+                    dprice += uprice * modulus;
+                }
+                if (citem == 1) {
+                    holder.bundle_btn.setText(String.format("%d bundle item with price of $ %.2f",citem,dprice));
+                } else {
+                    holder.bundle_btn.setText(String.format("%d bundle items with price of $ %.2f",citem,dprice));
+                }
+                holder.bundle_btn.setVisibility(View.VISIBLE);
+            } else {
+                holder.bundle_btn.setVisibility(View.INVISIBLE);
+            }
+
+            String availability = item_json.optString("quantity_available");
+            String available_str = "Available Now";
+            if (isNumber(availability) && Integer.valueOf(availability) > 0) {
+                available_str = String.format("Available: %s",availability);
+            } else {
+                available_str = "Available: In Production";
+            }
+            holder.count_lb.setText(available_str);
+
+            String img_url = item_json.optString("img_url");
+            String description = item_json.optString("description");
+            double unitprice = item_json.optDouble("unit_price");
+            int stockUom = item_json.optInt("stockUom");
+
+            double discount = 0.0;
+            String dis_str = item_json.optString("discount");
+            if (dis_str == null || dis_str.isEmpty()) {
+                discount = 0.0;
+            } else {
+                discount = Double.valueOf(dis_str);
+            }
+            String discount_str = String.format("%s%% off",floatFormat(discount));
+
+            String oldprice = String.format("%.2f",unitprice);
+            String new_unit_price = "";
+            if (dprice > 0) {
+                new_unit_price = String.format("%.2f+%.2f",unitprice* (1.0-discount/100),dprice);
+            } else {
+                new_unit_price = String.format("%.2f",unitprice* (1.0-discount/100));
+            }
+            String totalprice = String.format("%.2f",(unitprice* (1.0-discount/100)+dprice)*count);
+
+            if (can_see_price ==true && price_hidden == false) {
+
+            } else {
+                oldprice = null;
+                new_unit_price = null;
+                totalprice = null;
+            }
+
+            holder.discount_lb.setText(discount_str);
+            holder.old_price_lb.setText(oldprice);
+            holder.master_pack_lb.setText(String.format("Sold in QTY of:%d", stockUom));
+
+            boolean isfree = item_json.optBoolean("is_free");
+
+            if (isfree) {
+                holder.old_price_lb.setVisibility(View.VISIBLE);
+                holder.old_price_lb.setTextColor(Color.RED);
+                holder.old_price_lb.setText("Free");
+                holder.discount_lb.setVisibility(View.INVISIBLE);
+                // old_price_lb.hideline = true
+            } else {
+                holder.old_price_lb.setTextColor(Color.BLACK);
+                // old_price_lb.hideline = false
+                if (discount == 0) {
+                    holder.old_price_lb.setVisibility(View.INVISIBLE);
+                    holder.discount_lb.setVisibility(View.INVISIBLE);
+                } else {
+                    holder.old_price_lb.setVisibility(View.VISIBLE);
+                    holder.discount_lb.setVisibility(View.VISIBLE);
+                }
+            }
+
+            holder.desc_lb.setText(description);
+            holder.count_lb.setText(String.format("x %d",count));
+            holder.total_price_lb.setText(totalprice);
+            holder.unit_price_lb.setText(new_unit_price);
+
+            img_url = "http://img.gank.io/6ade6383-bc8e-40e4-9919-605901ad0ca5?imageView2/0/w/100";
+            Bitmap placeHolder = BitmapFactory.decodeResource(getResources(),R.drawable.not_found);
+            Bitmap bmp = Utils.loadCacheImage(img_url,placeHolder);
+            if (bmp != null) {
+                holder.model_img_btn.setImageBitmap(bmp);
+            } else {
+                // 异步记载数据
+                loadImageForPosition(group,child,0,img_url);
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+    /**
+     * 利用正则表达式判断字符串是否是数字
+     * @param str
+     * @return
+     */
+    public boolean isNumber(String str){
+        Pattern pattern = Pattern.compile("[0-9]*");
+        Matcher isNum = pattern.matcher(str);
+        if( !isNum.matches() ){
+            return false;
+        }
+        return true;
+    }
+
+    private String floatFormat(double value) {
+
+        if (Math.IEEEremainder(value, 1)==0)
+        {
+
+            return String.format("%.0f",value);
+
+        } else if (Math.IEEEremainder(value*10, 1)==0)
+        {
+
+            return String.format("%.1f",value);
+
+        }
+        else if (Math.IEEEremainder(value*100, 1)==0)
+        {
+
+            return String.format("%.2f",value);
+
+        }
+        else if (Math.IEEEremainder(value*1000, 1)==0)
+        {
+
+            return String.format("%.3f",value);
+
+        }
+        else
+        {
+
+            return String.format("%.4f",value);
+
+
+        }
+    }
+
+    public void setUpDatePickerCellHolder(CommonEditorEnumCellHolder holder, View cell, JSONObject item_json, boolean readonly, int group, int child) {
+
+        String title = item_json.optString("aname");
+        String value = item_json.optString("value");
+        String required = item_json.optString("required");
+
+        holder.group = group;
+        holder.child = child;
+        holder.title_lb.setText(title);
+        holder.value_lb.setText(value);
+
+        if (required.equals("true")) {
+            holder.startMark.setVisibility(View.VISIBLE);
+        } else {
+            holder.startMark.setVisibility(View.INVISIBLE);
+        }
+
+        if (cancommit == false && required.equals("true") && (value == null || value.length() == 0)) {
+            // red shadow
+        } else {
+            // no shadow
+        }
+
+    }
+
+    public void setUpMonthPickerCellHolder(CommonEditorEnumCellHolder holder, View cell, JSONObject item_json, boolean readonly, int group, int child) {
+
+        String title = item_json.optString("aname");
+        String value = item_json.optString("value");
+        String required = item_json.optString("required");
+
+        holder.group = group;
+        holder.child = child;
+        holder.title_lb.setText(title);
+        holder.value_lb.setText(value);
+
+        if (required.equals("true")) {
+            holder.startMark.setVisibility(View.VISIBLE);
+        } else {
+            holder.startMark.setVisibility(View.INVISIBLE);
+        }
+
+        if (cancommit == false && required.equals("true") && (value == null || value.length() == 0)) {
+            // red shadow
+        } else {
+            // no shadow
+        }
+
+    }
+
+    public void setUpSignatureCellHolder(CommonEditorSignatureCellHolder holder, View cell, JSONObject item_json, boolean readonly, int group, int child) {
+
+        String title = item_json.optString("aname");
+        String img_url = item_json.optString("avalue");
+        String required = item_json.optString("required");
+
+        holder.group = group;
+        holder.child = child;
+        holder.title_lb.setText(title);
+
+        if (required.equals("true")) {
+            holder.startMark.setVisibility(View.VISIBLE);
+        } else {
+            holder.startMark.setVisibility(View.INVISIBLE);
+        }
+        Bitmap placeHolder = BitmapFactory.decodeResource(getResources(),R.drawable.not_found);
+        if (img_url != null && !img_url.isEmpty()) {
+            Bitmap bmp = Utils.loadCacheImage(img_url,placeHolder);
+            if (bmp != null) {
+                holder.signature_iv.setImageBitmap(bmp);
+            } else {
+                // 异步记载数据
+                loadImageForPosition(group,child,2,img_url);
+            }
+        }
+    }
+
+    public void setUpSectionHeaderCellHolder(CommonEditorSectionHeaderHolder holder, View cell, JSONObject item_json, int group, int child) {
+        String title = item_json.optString("title");
+        boolean hide = item_json.optBoolean("hide");
+        boolean hideControlBtn = item_json.optBoolean("hideControlBtn");
+
+        holder.group = group;
+        holder.child = child;
+        holder.title_lb.setText(title);
+        holder.setShow(!hide);
+        holder.hideControlBtn(hideControlBtn);
+    }
+
+    public void setUpRangeCellHolder(CommonEditorRangeCellHolder holder, View cell, JSONObject item_json, boolean readonly, int group, int child) {
+
+        holder.clearTextWather();
+
+        String title = item_json.optString("aname");
+        holder.group = group;
+        holder.child = child;
+        holder.title_lb.setText(title);
+
+        String type = item_json.optString("type");
+        String keyboard = item_json.optString("keyboard");
+
+        int inputType = 0;
+        if (keyboard != null) {
+            if (keyboard.equals("number")) {
+                inputType = EditorInfo.TYPE_CLASS_NUMBER;
+            } else if (keyboard.equals("email")) {
+                inputType = EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
+            } else if (keyboard.equals("phone")) {
+                inputType = EditorInfo.TYPE_CLASS_PHONE;
+            } else {
+                inputType = EditorInfo.TYPE_CLASS_TEXT;
+            }
+        }
+
+        holder.min_et.setInputType(inputType);
+        holder.max_et.setInputType(inputType);
+
+        String min_str = item_json.optString("min_value");
+        String max_str = item_json.optString("max_value");
+
+        holder.min_et.setText(min_str);
+        holder.max_et.setText(max_str);
+
+//        if (disable == 1 || readonly) {
+//            holder.text_field.setEnabled(false);
+//            holder.text_field.setTextColor(Color.LTGRAY);
+//        } else {
+//            holder.text_field.setEnabled(true);
+//            holder.text_field.setTextColor(Color.BLACK);
+//        }
+
+
+        holder.resetTextWather();
+
+    }
+
+    public void setUpDateRangeCellHolder(CommonEditorDateRangeCellHolder holder, View cell, JSONObject item_json, boolean readonly, int group, int child) {
+
+        String title = item_json.optString("aname");
+        holder.group = group;
+        holder.child = child;
+        holder.title_lb.setText(title);
+
+//        String type = item_json.optString("type");
+
+        String min_str = item_json.optString("min_value");
+        String max_str = item_json.optString("max_value");
+
+        holder.min_btn.setText(min_str);
+        holder.max_btn.setText(max_str);
+
+    }
+
+    public void commonEditorRangeDidChange(String min, String max, int group, int child) {
+        String section_key = "section_" + group;
+        String item_key = "item_" + child;
+
+        try {
+            JSONObject section_json = content_data_download.getJSONObject(section_key);
+            JSONObject item_json = ((JSONArray)content_data_control.getJSONArray(group)).getJSONObject(child);
+
+            item_json.put("max_value",max);
+            item_json.put("min_value",min);
+
+            section_json.put(item_key,item_json);
+            content_data_download.put(section_key,section_json);
+            content_data_control = translateChange(content_data_download,changed_data);
+
+            adapter.notifyDataSetChanged();
+
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    public Context mCtx = this;
+
+    /**Month Picker*/
+    public void MPValueChanged(String value,int group,int child) {
+
+        try {
+
+            JSONObject section_json = null;
+            JSONObject item_json = content_data_control.optJSONArray(group).optJSONObject(child);
+
+            String subid = item_json.optString("subid");
+            item_json.put("value",value);
+            if (subid == null || subid.isEmpty()) {
+
+                section_json = content_data_download.optJSONObject("section_" + group);
+                int count = 0;
+                count = section_json.optInt("count");
+                for (int i = 0; i < count; i++) {
+                    JSONObject olditem = section_json.optJSONObject("item_" + i);
+                    if (olditem.optString("name").equals(item_json.optString("name"))) {
+                        section_json.put("item_" + i,item_json);
+                    }
+                }
+
+            } else {
+
+                String[] idarr = subid.split("_");
+                int section = Integer.valueOf(idarr[0]);
+                int item = Integer.valueOf(idarr[1]);
+
+                section_json = content_data_download.optJSONObject("section_" + section);
+                JSONObject olditem = section_json.optJSONObject("item_" + item);
+                String control_type = olditem.optString("control");
+
+                if (control_type.equals("enum")) {
+                    item_json = enum_subitem_changed(olditem,idarr,item_json,2);
+                } else if (control_type.equals("switch")){
+                    item_json = switch_subitem_changed(olditem,idarr,item_json,2);
+                }
+                item_json.put("dirty","true");
+                section_json.put("item_" + item,item_json);
+            }
+
+            content_data_download.put("section_" + group,section_json);
+            content_data_control = translateChange(content_data_download,changed_data);
+
+            adapter.notifyDataSetChanged();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    /**Image Change*/
+    public void imgIsChanged(String url_down, String url_up, int group, int child, int index, String url_index) {
+
+        try {
+
+            JSONObject section_json = null;
+            JSONObject item_json = content_data_control.optJSONArray(group).optJSONObject(child);
+            int refresh = item_json.optInt("refresh");
+            String refresh_trigger = item_json.optString("name");
+            String subid = item_json.optString("subid");
+            item_json.put("img_url_" + index,url_down);
+            item_json.put("avalue",url_up);
+            item_json.put("img_url_aname_" + index,url_index);
+            item_json.put("dirty","true");
+            if (subid == null || subid.isEmpty()) {
+
+                section_json = content_data_download.optJSONObject("section_" + group);
+                int count = 0;
+                count = section_json.optInt("count");
+                for (int i = 0; i < count; i++) {
+                    JSONObject olditem = section_json.optJSONObject("item_" + i);
+                    if (olditem.optString("name").equals(item_json.optString("name"))) {
+                        section_json.put("item_" + i,item_json);
+                    }
+                }
+
+            } else {
+
+                String[] idarr = subid.split("_");
+                int section = Integer.valueOf(idarr[0]);
+                int item = Integer.valueOf(idarr[1]);
+
+                section_json = content_data_download.optJSONObject("section_" + section);
+                JSONObject olditem = section_json.optJSONObject("item_" + item);
+                item_json = enum_subitem_changed(olditem,idarr,item_json,2);
+                section_json.put("item_" + item,item_json);
+
+            }
+
+            content_data_download.put("section_" + group,section_json);
+            content_data_control = translateChange(content_data_download,changed_data);
+
+            if (refresh == 1) {
+                refresh(refresh_trigger);
+            }
+
+            adapter.notifyDataSetChanged();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+
+    /**Switch Check Listener**/
+    public class SwitchCheckListener implements CompoundButton.OnCheckedChangeListener {
+
+        @Override
+        public void onCheckedChanged(CompoundButton v, boolean isChecked) {
+            Switch aSwitch = (Switch)v;
+
+            String[] tag_arr = ((String) v.getTag()).split("_");
+            int group =  Integer.valueOf(tag_arr[0]);
+            int child = Integer.valueOf(tag_arr[1]);
+
+            JSONObject section_json = null;
+            JSONObject item_json = content_data_control.optJSONArray(group).optJSONObject(child);
+
+            int refresh = item_json.optInt("refresh");
+            String refresh_trigger = item_json.optString("name");
+            String subid = item_json.optString("subid");
+            String check = "false";
+
+            if (isChecked) {
+                check = "true";
+            }
+
+            try {
+
+                item_json.put("dirty","true");
+                item_json.put("value",check);
+
+                if (subid == null || subid.isEmpty()) {
+                    section_json = content_data_download.optJSONObject("section_" + group);
+                    int count = 0;
+                    count = section_json.optInt("count");
+                    for (int i = 0; i < count; i++) {
+                        JSONObject olditem = section_json.optJSONObject("item_" + i);
+                        if (olditem.optString("name").equals(item_json.optString("name"))) {
+                            section_json.put("item_" + i,item_json);
+                        }
+                    }
+                } else {
+                    String[] idarr = subid.split("_");
+                    int section = Integer.valueOf(idarr[0]);
+                    int item = Integer.valueOf(idarr[1]);
+
+                    section_json = content_data_download.optJSONObject("section_" + section);
+                    JSONObject olditem = section_json.optJSONObject("item_" + item);
+                    item_json = enum_subitem_changed(olditem,idarr,item_json,2);
+                    item_json.put("dirty","true");
+                    section_json.put("item_" + item,item_json);
+                }
+
+                content_data_download.put("section_" + group,section_json);
+                content_data_control = translateChange(content_data_download,changed_data);
+
+                adapter.notifyDataSetChanged();
+
+                if (refresh == 1) {
+                    refresh(refresh_trigger);
+                }
+
+
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    public static int URL_REMOTE = 1;
+    public static int URL_LOCAL = 0;
+    public static int URL_NONE = 2;
+    public static int URL_RESTORE = 3;
+    // 如何处理commoneditor action 类型调用的返回值
+    static int ACTION_SAVE_DATA = 0;
+    static int ACTION_FILL_SECTION = 1;
+    /**Multiple Action**/
+    private View.OnClickListener multipleActionClickListener = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+
+            Button btn = (Button)v;
+            String tag = (String) btn.getTag();
+            String[] arr = tag.split("_");
+            int group = Integer.valueOf(arr[0]);
+            int child = Integer.valueOf(arr[1]);
+            int i = Integer.valueOf(arr[2]);
+
+            int refresh = 0;
+            JSONObject section_json = null;
+            JSONObject item_json = content_data_control.optJSONArray(group).optJSONObject(child);
+            String subid = item_json.optString("subid");
+            String refresh_trigger = item_json.optString("name");
+            JSONObject sub_action = item_json.optJSONObject("item_" + i);
+            String type = sub_action.optString("type");
+
+            if (type != null && type.equals("pull")) {
+
+                // end edit
+
+                refresh = sub_action.optInt("refresh");
+                JSONObject keymap = sub_action.optJSONObject("key_map");
+                JSONObject value = create_value_map(keymap);
+
+                if (subid == null || subid.isEmpty()) {
+                    JSONObject jsonmap = sub_action.optJSONObject("key_map");
+                    section_json = content_data_download.optJSONObject("section_" + group);
+                    int icount = section_json.optInt("count");
+                    for (int ic = 0; ic < icount; ic++) {
+                        JSONObject modity_item = section_json.optJSONObject("item_" + ic);
+                        String mapto = modity_item.optString("name");
+
+                        if (mapto.isEmpty()) {
+                            continue;
+                        }
+                        String valuefrom = jsonmap.optString(modity_item.optString("name"));
+                        if (valuefrom == null) {
+                            continue;
+                        }
+                        String valuestr = value.optString(valuefrom);
+
+                        try {
+                            if (valuestr.isEmpty()) {
+                                modity_item.put("value","");
+                            } else {
+                                modity_item.put("value",valuestr);
+                            }
+                            modity_item.put("dirty","true");
+                            section_json.put("item_" + ic,modity_item);
+
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+
+                    }
+                } else {
+                    String[] idarr = subid.split("_");
+                    int section = Integer.valueOf(idarr[0]);
+                    int item = Integer.valueOf(idarr[1]);
+
+                    JSONObject jsonmap = sub_action.optJSONObject("key_map");
+                    section_json = content_data_download.optJSONObject("section_" + section);
+                    JSONObject olditem = section_json.optJSONObject("item_" + item);
+
+                    String control_type = olditem.optString("control");
+                    if (control_type.equals("switch")) {
+                        olditem = fill_switch_subitem_subid_mapping(olditem,null,value,jsonmap);
+                    } else if (control_type.equals("enum")) {
+                        olditem = fill_enum_subitem_subid_mapping(olditem,null,value,jsonmap);
+                    } else {
+                        new AlertDialog.Builder(mCtx)
+                                .setMessage("not impl")
+                                .setPositiveButton("OK",null)
+                                .show();
+                    }
+                    try {
+                        olditem.put("dirty","true");
+                        section_json.put("item_" + item,olditem);
+
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+
+                }
+
+                try {
+
+                    content_data_download.put("section_" + group,section_json);
+                    content_data_control = translateChange(content_data_download,changed_data);
+
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+
+                if (refresh == 1) {
+                    refresh(refresh_trigger);
+                    return;
+                }
+                adapter.notifyDataSetChanged();
+
+            } else {
+                JSONObject itemjson = sub_action;
+                String value = itemjson.optString("value");
+                Intent intent = null;
+                String requesturl = null;
+                int request_code = -1;
+                if (value.equals("new_addr")) {
+
+                    AddressEditorActivity.Builder builder = new AddressEditorActivity.Builder(); // 创建内部类实例需要外部类的实例,或者声明内部类为static
+                    intent = builder.build(mCtx,URL_REMOTE,requesturl,"true",String.format("%d",i),group,child);
+                    request_code = 2;
+
+                } else if (value.equals("credit_card")) {
+
+                    request_code = 3;
+                    JSONObject data = item_json.optJSONObject("data");
+                    int url_type;
+                    JSONObject download_data;
+                    if (data != null) {
+                        download_data = data;
+                        url_type = URL_NONE;
+                        requesturl = null;
+                    } else {
+                        download_data = null;
+                        url_type = URL_REMOTE;
+                        requesturl = "";
+                    }
+                    intent = new CreditCardEditorActivity.Builder().build(mCtx,url_type,requesturl,Application.order_code,"true",String.format("%d",i),download_data,group,child);
+
+                } else if (value.equals("Sales_Order_Freight_Bill_To")) {
+
+                    request_code = 4;
+                    intent = new ContactListActivity.Builder().build(mCtx,"true",String.format("%d",i),value,true,group,child);
+
+                } else if (value.equals("Sales_Order_Ship_From")) {
+
+                    request_code = 5;
+                    intent = new ContactListActivity.Builder().build(mCtx,"true",String.format("%d",i),value,true,group,child);
+
+                } else if (value.equals("Sales_Order_Customer")) {
+
+                    request_code = 6;
+                    intent = new ContactListActivity.Builder().build(mCtx,"true",String.format("%d",i),value,true,group,child);
+
+                } else if (value.equals("Sales_Order_Merchandise_Bill_To")) {
+
+                    request_code = 7;
+                    intent = new ContactListActivity.Builder().build(mCtx,"true",String.format("%d",i),value,true,group,child);
+
+                } else if (value.equals("Contact_Return_To")) {
+
+                    request_code = 8;
+                    intent = new ContactListActivity.Builder().build(mCtx,"true",String.format("%d",i),value,true,group,child);
+
+                } else if (value.equals("Sales_Order_Ship_To")) {
+
+                    request_code = 9;
+                    intent = new ContactListActivity.Builder().build(mCtx,"true",String.format("%d",i),value,true,group,child);
+                }
+
+               if (intent != null) {
+                   startActivityForResult(intent,request_code);
+               }
+            }
+
+        }
+    };
+
+    public JSONObject fill_switch_subitem_subid_mapping(JSONObject switch_item,JSONArray subid,JSONObject source, JSONObject mapping) {
+
+        String value = switch_item.optString("value");
+        JSONObject boolitem = null;
+        JSONObject subjson = null;
+        if (value.equals("true")) {
+            boolitem = switch_item.optJSONObject("true");
+        } else {
+            boolitem = switch_item.optJSONObject("false");
+        }
+        subjson = boolitem.optJSONObject("sub_item");
+        if (subjson != null) {
+            int sub_count = subjson.optInt("count");
+            for (int l = 0; l <sub_count; l++) {
+                JSONObject modify_item = subjson.optJSONObject("item_" + l);
+                String mapto = modify_item.optString("name");
+                if (mapto == null || mapto.isEmpty()) {
+                    continue;
+                }
+                String valuefrom = mapping.optString(modify_item.optString("name"));
+                if (valuefrom == null) {
+                    continue;
+                }
+                String valuestr = source.optString(valuefrom);
+
+                try {
+                    if (valuestr.length() > 0) {
+                        modify_item.put("value",valuestr);
+                    } else {
+                        modify_item.put("value","");
+                    }
+
+                    modify_item.put("dirty","true");
+                    subjson.put("item_" + l,modify_item);
+
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+
+            try {
+                boolitem.put("sub_item",subjson);
+                if (value.equals("true")) {
+                    switch_item.put("true",boolitem);
+                } else {
+                    switch_item.put("false",boolitem);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        return switch_item;
+    }
+
+    public JSONObject fill_enum_subitem_subid_mapping(JSONObject enum_item,JSONArray subid,JSONObject source, JSONObject mapping) {
+
+        JSONObject cadedatejson = enum_item.optJSONObject("cadedate");
+        int count = cadedatejson.optInt("count");
+        for (int i = 0; i < count; i++) {
+            JSONObject val_json = cadedatejson.optJSONObject("val_" + i);
+            int check = val_json.optInt("check");
+            if (check == 1) {
+                JSONObject subjson = val_json.optJSONObject("sub_item");
+                if (subjson != null) {
+                    int sub_count = subjson.optInt("count");
+                    for (int l = 0; l < sub_count; l++) {
+                        JSONObject modify_item = subjson.optJSONObject("item_" + l);
+                        String control_type = modify_item.optString("control");
+                        if (control_type.equals("switch")) {
+                            modify_item = fill_switch_subitem_subid_mapping(modify_item,null,source,mapping);
+                        } else if (control_type.equals("enum")) {
+                            modify_item = fill_enum_subitem_subid_mapping(modify_item,null,source,mapping);
+                        } else {
+                            String mapto = modify_item.optString("name");
+                            if (mapto == null || mapto.isEmpty()) {
+                                continue;
+                            }
+                            String valuefrom = mapping.optString(modify_item.optString("name"));
+                            if (valuefrom == null) {
+                                continue;
+                            }
+                            String valuestr = source.optString(valuefrom);
+
+                            try {
+                                if (valuefrom != null && valuefrom.length() > 0) {
+                                    modify_item.put("value",valuestr);
+                                } else {
+                                    modify_item.put("value","");
+                                }
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                            }
+                        }
+                        try {
+                            modify_item.put("dirty","true");
+                            subjson.put("item_" + l,modify_item);
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+                    }
+                    try {
+                        val_json.put("sub_item",subjson);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+            try {
+                cadedatejson.put("val_" + i,val_json);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        try {
+            enum_item.put("cadedate",cadedatejson);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return enum_item;
+    }
+
+    public JSONObject create_value_map(JSONObject key_map) {
+        JSONObject ret = new JSONObject();
+
+        Iterator<String> keys = key_map.keys();
+        try {
+
+            while (keys.hasNext()) {
+                String key = keys.next();
+                String valuefrom = key_map.optString(key);
+                if (valuefrom != null && !valuefrom.isEmpty()) {
+                    String value = getValue(valuefrom);
+                    ret.put(valuefrom,value);
+                }
+            }
+            JSONObject customerinfo = create_customer_info_from_table();
+
+            String ext = create_customer_ext(customerinfo);
+            String first_name = customerinfo.optString("customer_first_name");
+            String last_name = customerinfo.optString("customer_last_name");
+            if (ext != null) {
+                ret.put("customer_contact_ext",ext);
+            }
+            if (first_name != null) {
+                ret.put("customer_first_name",first_name);
+            }
+            if (last_name != null) {
+                ret.put("customer_last_name",last_name);
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return ret;
+    }
+
+    public String getValue(String name) {
+
+        String ret = "";
+        int count = content_data_control.length();
+        for (int i = 0; i < count; i++) {
+            JSONArray items = content_data_control.optJSONArray(i);
+            for (int j = 0; j < items.length(); j++) {
+                JSONObject item = items.optJSONObject(j);
+                String item_name = item.optString("name");
+                if (item_name.equals(name)) {
+                    String control = item.optString("control");
+                    if (control.equals("enum")) {
+                        JSONObject cadedate = item.optJSONObject("cadedate");
+                        int cc = cadedate.optInt("count");
+                        for (int l = 0; l < cc; l++) {
+                            JSONObject val_json = cadedate.optJSONObject("val_" + l);
+                            if (val_json.optInt("check") == 1) {
+                                return val_json.optString("value_id");
+                            }
+                        }
+                    } else {
+                        return item.optString("value");
+                    }
+
+                }
+            }
+
+        }
+
+        return ret;
+    }
+
+    public JSONObject create_customer_info_from_table() {
+
+        JSONObject ret = Application.customerInfo;
+
+
+
+        try {
+
+            if (ret == null) {
+                ret = new JSONObject();
+            }
+
+            ret.put("customer_country",getValue("customer_country"));
+            ret.put("customer_phone",getValue("customer_phone"));
+            ret.put("customer_email",getValue("customer_email"));
+            ret.put("customer_name",getValue("customer_name"));
+            ret.put("customer_address4",getValue("customer_address4"));
+            ret.put("customer_address3",getValue("customer_address3"));
+            ret.put("customer_address2",getValue("customer_address2"));
+            ret.put("customer_address1",getValue("customer_address1"));
+            ret.put("customer_zipcode",getValue("customer_zipcode"));
+            ret.put("customer_city",getValue("customer_city"));
+            ret.put("customer_state",getValue("customer_state"));
+            ret.put("customer_cid",getValue("customer_cid"));
+            ret.put("customer_state",getValue("customer_state"));
+            ret.put("customer_contact",getValue("customer_contact"));
+            ret.put("customer_fax",getValue("customer_fax"));
+
+            String firstname = "";
+            String lastname = "";
+            String contact_name = getValue("customer_contact");
+            if (contact_name != null) {
+                String[] arr = contact_name.split(" ");
+                if (arr.length >= 1) {
+                    firstname = arr[0];
+                    if (arr.length > 1) {
+                        lastname = arr[1];
+                        int length = arr.length;
+                        if (length > 2) {
+                            for (int i = 2; i < length; i++) {
+                                lastname = lastname + " " + arr[i];
+                            }
+                        }
+                    }
+                }
+            }
+            ret.put("customer_first_name",firstname);
+            ret.put("customer_last_name",lastname);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+
+        return ret;
+    }
+
+    public String create_customer_ext(JSONObject customerinfo) {
+
+        String ret = null;
+        String customer_address1 = customerinfo.optString("customer_address1");
+        String customer_address2 = customerinfo.optString("customer_address2");
+        String customer_address3 = customerinfo.optString("customer_address3");
+        String customer_address4 = customerinfo.optString("customer_address4");
+
+        String addr_str = "";
+        if (customer_address1 != null && customer_address1.length() > 0) {
+            addr_str = addr_str + customer_address1 + "\r\n";
+        }
+        if (customer_address2 != null && customer_address2.length() > 0) {
+            addr_str = addr_str + customer_address2 + "\r\n";
+        }
+        if (customer_address3 != null && customer_address3.length() > 0) {
+            addr_str = addr_str + customer_address3 + "\r\n";
+        }
+        if (customer_address4 != null && customer_address4.length() > 0) {
+            addr_str = addr_str + customer_address4 + "\r\n";
+        }
+        if (addr_str.length() > 0) {
+            addr_str = addr_str.substring(0,addr_str.length() - 3);
+        }
+
+        String city = customerinfo.optString("customer_city");
+        String country = customerinfo.optString("customer_country");
+        String zipcode = customerinfo.optString("customer_zipcode");
+        String state = customerinfo.optString("customer_state");
+
+        String cty_str = "";
+        if (city != null && city.length() > 0) {
+            cty_str = cty_str + city + ", ";
+        }
+        if (state != null && state.length() > 0) {
+            cty_str = cty_str + state + ", ";
+        }
+        if (zipcode != null && zipcode.length() > 0) {
+            cty_str = cty_str + zipcode + ", ";
+        }
+        if (country != null && country.length() > 0) {
+            cty_str = cty_str + country + ", ";
+        }
+        if (cty_str.length() > 0) {
+            cty_str = cty_str.substring(0,cty_str.length() - 3);
+        }
+
+        String ext_str = "";
+        if (addr_str != null && addr_str.length() > 0) {
+            ext_str = ext_str + addr_str + "\r\n";
+        }
+        if (cty_str != null && cty_str.length() > 0) {
+            ext_str = ext_str + cty_str;
+        }
+
+        ret = ext_str;
+
+        return ret;
+    }
+
+    public void textFieldSetValue(String val,int group,int child) {
+
+        try {
+
+            JSONObject section_json = null;
+
+            val = val.trim();
+            JSONObject item_json = content_data_control.optJSONArray(group).optJSONObject(child);
+
+            String subid = item_json.optString("subid");
+            String refresh_trigger = item_json.optString("name");
+
+            item_json.put("dirty","true");
+            item_json.put("value",val);
+            if (item_json.optString("keyboard").equals("number")) {
+                float f = Float.valueOf(val);
+                item_json.put("value",String.format("%.2f",f));
+            }
+
+            if (subid == null || subid.isEmpty()) {
+
+                section_json = content_data_download.optJSONObject("section_" + group);
+                int count = 0;
+
+                count = section_json.optInt("count");
+                for (int i = 0; i < count; i++) {
+                    JSONObject olditem = section_json.optJSONObject("item_" + i);
+                    if (olditem.optString("name").equals(item_json.optString("name"))) {
+                        section_json.put("item_" + i,item_json);
+                    }
+                } // for
+
+                content_data_download.put("section_" + group,section_json);
+                content_data_control = translateChange(content_data_download,changed_data);
+
+                int refresh = item_json.optInt("refresh");
+                JSONObject restore_json = item_json.optJSONObject("restore");
+                boolean partial_refresh = item_json.optBoolean("partial_refresh");
+                if (refresh == 1) {
+
+                    if (restore_json != null) {
+                        int rc = restore_json.optInt("count");
+                        for (int ir = 0; ir < rc; ir++) {
+                            String name = restore_json.optString("item_" + ir);
+                            int section_count = content_data_download.optInt("section_count");
+                            for (int i = 0; i < section_count; i++) {
+                                JSONObject sectionjson = content_data_download.optJSONObject("section_" + i);
+                                int item_count = sectionjson.optInt("count");
+                                for (int j = 0; j < item_count; j++) {
+                                    JSONObject itemjson = sectionjson.optJSONObject("item_" + j);
+                                    if (itemjson.optString("name").equals(name)) {
+                                        itemjson.remove("dirty");
+                                        sectionjson.put("item_" + j,itemjson);
+                                    }
+                                }
+                                content_data_download.put("section_" + i,sectionjson);
+                            }
+                        }
+                    }
+                    refresh(refresh_trigger);
+
+                } // refresh == 1
+                else if (partial_refresh) {
+
+                    String name = item_json.optString("name");
+                    final String url = item_json.optString("data_interface");
+
+                    JSONObject params = new JSONObject();
+                    params.put(name,val);
+
+                    final ProgressDialog pd = Utils.waiting_alert(mCtx,"loading","please wait");
+                    final JSONObject final_params = params;
+                    new Thread(new Runnable() {
+                        @Override
+                        public void run() {
+                            final JSONObject editor_json = Network.commoneditor_partialrefresh(final_params,url);
+
+                            runOnUiThread(new Runnable() {
+                                @Override
+                                public void run() {
+
+                                    pd.dismiss();
+
+                                    if (Integer.valueOf(editor_json.optString("result")) == 2) {
+                                        int prcount = editor_json.optInt("count");
+                                        for (int ipr = 0; ipr < prcount; ipr++) {
+                                            JSONObject pr_item = editor_json.optJSONObject("item_" + ipr);
+                                            String name = pr_item.optString("name");
+                                            String value = pr_item.optString("value");
+                                            setValue(name,value);
+                                        }
+                                    } else {
+                                        Utils.message_alert(mCtx,"",editor_json.optString("err_msg"));
+                                    }
+
+                                }
+                            });
+                        }
+                    }).start();
+
+
+                } // partial refresh
+
+                lastEditText = null;
+                last_edit_group = -1;
+                last_edit_child = -1;
+
+                return;
+            } // subid == null
+            else
+            {
+
+                String[] idarr = subid.split("_");
+                int section = Integer.valueOf(idarr[0]);
+                int item = Integer.valueOf(idarr[1]);
+
+                section_json = content_data_download.optJSONObject("section_" + section);
+                JSONObject olditem = section_json.optJSONObject("item_" + item);
+
+                String control_type = olditem.optString("control");
+                JSONObject new_item = null;
+                item_json.put("dirty","true");
+                if (control_type.equals("enum")) {
+                    new_item = enum_subitem_changed(olditem,idarr,item_json,2);
+                } else if (control_type.equals("switch")) {
+                    new_item = switch_subitem_changed(olditem,idarr,item_json,2);
+                }
+                section_json.put("item_" + item,new_item);
+
+                content_data_download.put("section_" + group,section_json);
+                content_data_control = translateChange(content_data_download,changed_data);
+
+                int refresh = item_json.optInt("refresh");
+                JSONObject restore_json = item_json.optJSONObject("restore");
+                boolean partial_refresh = item_json.optBoolean("partial_refresh");
+                if (refresh == 1) {
+
+                    if (restore_json != null) {
+                        int rc = restore_json.optInt("count");
+                        for (int ir = 0; ir < rc; ir++) {
+                            String name = restore_json.optString("item_" + ir);
+                            int section_count = content_data_download.optInt("section_count");
+                            for (int i = 0; i < section_count; i++) {
+                                JSONObject sectionjson = content_data_download.optJSONObject("section_" + i);
+                                int item_count = sectionjson.optInt("count");
+                                for (int j = 0; j < item_count; j++) {
+                                    JSONObject itemjson = sectionjson.optJSONObject("item_" + j);
+                                    if (itemjson.optString("name").equals(name)) {
+                                        itemjson.remove("dirty");
+                                        sectionjson.put("item_" + j,itemjson);
+                                    }
+                                }
+                                content_data_download.put("section_" + i,sectionjson);
+                            }
+                        }
+                    }
+                    refresh(refresh_trigger);
+
+                } // refresh == 1
+                else if (partial_refresh) {
+
+                    String name = item_json.getString("name");
+                    final String url = item_json.optString("data_interface");
+
+                    JSONObject params = new JSONObject();
+                    params.put(name,val);
+                    final ProgressDialog pd = Utils.waiting_alert(mCtx,"loading","please wait");
+                    final JSONObject final_params = params;
+                    new Thread(new Runnable() {
+                        @Override
+                        public void run() {
+
+                            final JSONObject editor_json = Network.commoneditor_partialrefresh(final_params,url);
+
+                            runOnUiThread(new Runnable() {
+                                @Override
+                                public void run() {
+
+                                    pd.dismiss();
+
+                                    if (Integer.valueOf(editor_json.optString("result")) == 2) {
+                                        int prcount = editor_json.optInt("count");
+                                        for (int ipr = 0; ipr < prcount; ipr++) {
+                                            JSONObject pr_item = editor_json.optJSONObject("item_" + ipr);
+                                            String name = pr_item.optString("name");
+                                            String value = pr_item.optString("value");
+                                            setValue(name,value);
+                                        }
+                                    } else {
+                                        Utils.message_alert(mCtx,"",editor_json.optString("err_msg"));
+                                    }
+
+                                }
+                            });
+
+                        }
+                    }).start();
+
+
+                } // partial refresh
+
+
+                // fix crash when sub item value changed
+                adapter.notifyDataSetChanged();
+
+                lastEditText = null;
+                // lastedit_from = null
+                last_edit_group = -1;
+                last_edit_child = -1;
+
+                return;
+            }
+
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    public JSONObject switch_subitem_changed(JSONObject switch_item,String[] subid,JSONObject valuejson,int step) {
+
+        try {
+
+            int index = Integer.valueOf(subid[step]);
+            String value = switch_item.optString("value");
+
+            JSONObject boolitem = null;
+            JSONObject subjson = null;
+            if (value.equals("true")) {
+                boolitem = switch_item.optJSONObject("true");
+            } else {
+                boolitem = switch_item.optJSONObject("false");
+            }
+            subjson = boolitem.optJSONObject("sub_item");
+
+            if (subjson != null) {
+                JSONObject itemjson = subjson.optJSONObject("item_" + index);
+                if (step == subid.length - 1) {
+                    itemjson = valuejson;
+                }
+                subjson.put("item_" + index,itemjson);
+                boolitem.put("sub_item",subjson);
+
+                if (value.equals("true")) {
+                    switch_item.put("true",boolitem);
+                } else {
+                    switch_item.put("false",boolitem);
+                }
+
+                return switch_item;
+            }
+
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return null;
+
+    }
+
+    public void setEnumValue(JSONObject value, int group, int child) {
+
+        try {
+
+            JSONObject section_json = null;
+            JSONObject item_json = content_data_control.optJSONArray(group).optJSONObject(child);
+
+            int refresh = item_json.optInt("refresh");
+            String refresh_trigger = item_json.optString("name");
+            String subid = item_json.optString("subid");
+
+            item_json.put("cadedate",value);
+
+            if (subid == null || subid.isEmpty()) {
+                item_json.put("dirty","dirty");
+                section_json = content_data_download.optJSONObject("section_" + group);
+                int count = 0;
+                count = section_json.optInt("count");
+                for (int i = 0; i < count; i++) {
+                    JSONObject olditem = section_json.optJSONObject("item_" + i);
+                    if (olditem.optString("name").equals(item_json.optString("name"))) {
+                        section_json.put("item_" + i,item_json);
+                    }
+                }
+            } else {
+
+                String[] idarr = subid.split("_");
+                int section = Integer.valueOf(idarr[0]);
+                int item = Integer.valueOf(idarr[1]);
+
+                section_json = content_data_download.optJSONObject("section_" + section);
+                JSONObject olditem = section_json.optJSONObject("item_" + item);
+                item_json = enum_subitem_changed(olditem,idarr,item_json,2);
+                item_json.put("dirty","true");
+                section_json.put("item_" + item,item_json);
+
+            }
+
+            content_data_download.put("section_" + group,section_json);
+            content_data_control = translateChange(content_data_download,changed_data);
+
+            JSONObject restore_json = item_json.optJSONObject("restore");
+            if (refresh == 1) {
+                if (restore_json != null) {
+                    int rc = restore_json.optInt("count");
+                    for(int ir=0;ir<rc;ir++) {
+                        String name = restore_json.optString("item_" + ir);
+                        int section_count = content_data_download.optInt("section_count");
+
+                        for (int i = 0; i < section_count; i++) {
+                            JSONObject sectionjson = content_data_download.optJSONObject("section_" + i);
+                            int item_count = sectionjson.optInt("count");
+                            for (int j = 0; j < item_count; j++) {
+                                JSONObject itemjson = sectionjson.optJSONObject("item_" + j);
+                                if (itemjson.optString("name").equals(name)) {
+                                    itemjson.remove("dirty");
+                                    sectionjson.put("item_" + j,itemjson);
+                                }
+                            }
+                            content_data_download.put("section_" + i,sectionjson);
+                        }
+                    }
+                }
+                refresh(refresh_trigger);
+                return;
+            }
+            adapter.notifyDataSetChanged();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+
+
+    }
+
+    public void setValue(String key,String val) {
+
+
+        try {
+
+            for (int i = 0; i < content_data_control.length(); i++) {
+                JSONArray items = content_data_control.optJSONArray(i);
+                for (int j = 0; j < items.length(); j++) {
+                    JSONObject item = items.optJSONObject(j);
+                    String item_name = item.optString("name");
+                    int group = i;
+                    int child = j;
+                    if (item_name.equals(key)) {
+                        String control = item.optString("control");
+                        if (control.equals("enum")) {
+
+                            JSONObject cadedate = item.optJSONObject("cadedate");
+                            int cc = cadedate.optInt("count");
+                            for (int l = 0; l < cc; l++) {
+
+                                JSONObject val_json = cadedate.optJSONObject("val_" + l);
+                                if (val_json.optString("val_id").equals(val)) {
+                                    val_json.put("check",1);
+                                } else {
+                                    val_json.put("check",0);
+                                }
+                                cadedate.put("val_" + l,val_json);
+
+                            } // for
+
+                            setEnumValue(cadedate,group,child);
+
+                        }// enum
+                        else if (control.equals("edit")) {
+                            textFieldSetValue(val,group,child);
+                        } // edit
+                    } // key
+
+                }
+            }
+            adapter.notifyDataSetChanged();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    public JSONArray sync_loadCadidate(String keyword,JSONObject item_json) {
+
+        if (keyword == null || keyword.isEmpty()) {
+            return null;
+        }
+
+        Bundle params = new Bundle();
+        params.putString("query_id",selfParams.getString("query_id"));
+        params.putString("name",item_json.optString("name"));
+        params.putString("keyword",keyword);
+
+        JSONObject json = Network.queryAutoComplete(params);
+
+        if (json != null) {
+            return json.optJSONArray("cadedate");
+        } else {
+            return null;
+        }
+    }
+
+    /**Text Field Change*/
+    public class TextFieldTextWatcher implements TextWatcher {
+
+        Context mCtx;
+        int group;
+        int child;
+        EditText textView;
+        boolean autoComplete = false;
+
+        public TextFieldTextWatcher(Context ctx,EditText textView,int group,int child) {
+            this.mCtx = ctx;
+            this.textView = textView;
+            this.group = group;
+            this.child = child;
+
+        }
+
+        String origin_text;
+        String string;
+        int start_position;
+        int change_length; // 修改原文长度
+        int new_string_length;
+
+
+        /**
+         * s        改变前的内容
+         * start    增加内容前光标位置,删除内容后光标位置 (起始位置)
+         * count    选中s中的内容长度(发生改变的原内容长度),未选中为0
+         * after    新添加的内容长度,删除为0
+         * */
+        @Override
+        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+//            Log.d("TextChange", "before Text Changed: " + s + " Start: " + start + " Count: " + count + " After: " + after);
+
+            origin_text = s.toString();
+            start_position = start;
+            change_length = count;
+            new_string_length = after;
+
+        }
+
+        /**
+         * s        改变后的内容
+         * start    增加内容前光标位置,删除内容后光标位置 (起始位置)
+         * before   选中s中的内容长度(发生改变的原内容长度),未选中为0
+         * count    增加内容长度,删除内容为0
+         * */
+        @Override
+        public void onTextChanged(CharSequence s, int start, int before, int count) {
+//            Log.d("TextChange", "on Text Changed: " + s + " Start: " + start + " Before: " + before + " Count: " + count);
+        }
+
+        @Override
+        public void afterTextChanged(final Editable s) {
+
+            /**
+             * 文本处理
+             * */
+            if (new_string_length == 0) {
+                string = "";
+            } else {
+                string = s.toString().substring(start_position,start_position + new_string_length);
+            }
+
+            if (change_length == 0) { // 新加内容
+
+            } else { // 替换原文或删除原文
+
+            }
+
+            /**
+             * 业务逻辑
+             * */
+            final JSONObject item_json = content_data_control.optJSONArray(group).optJSONObject(child);
+            if (item_json == null) {
+                return;
+            }
+            String required = item_json.optString("required");
+
+            if (required.equals("true") && string.length() == 0 && (origin_text == null || origin_text.length() < 1)) {
+
+                // cell red shadow
+
+            } else {
+                // cell clear shadow
+            }
+
+            if (textView instanceof AutoCompleteTextView) {
+
+                final CommonEditorEditAutoCompleteCellHolder holder = (CommonEditorEditAutoCompleteCellHolder) ((View)textView.getParent().getParent()).getTag();
+
+                holder.autoCompleteAdapter.clear();
+
+                final String threadIdentifier = UUID.randomUUID().toString();
+                holder.thread_identifier = threadIdentifier;
+
+                new Thread(new Runnable() {
+                    @Override
+                    public void run() {
+
+                        // 延迟0.8s 请求
+                        try {
+
+                            Thread.sleep(800);
+
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+                        if (threadIdentifier.equals(holder.thread_identifier)) {
+
+                            if (s == null || s.toString().length() < 1) {
+
+                            } else  {
+
+                                // 请求
+                                JSONArray cadedate = sync_loadCadidate(s.toString(),item_json);
+
+                                List<String> list = new ArrayList<>();
+                                for (int i = 0; i < cadedate.length(); i++) {
+                                    JSONObject object = cadedate.optJSONObject(i);
+                                    if (object != null) {
+                                        String str = object.optString("value");
+                                        if (str != null || !str.isEmpty()) {
+                                            list.add(str);
+                                        }
+                                    }
+
+                                }
+
+                                if (threadIdentifier.equals(holder.thread_identifier)) {
+                                    final String[] arr = (String[]) list.toArray(new String[list.size()]);
+
+                                    runOnUiThread(new Runnable() {
+                                        @Override
+                                        public void run() {
+
+                                            holder.autoCompleteAdapter.addObjects(arr);
+                                        }
+                                    });
+                                }
+                            }
+
+                        }
+
+
+                    }
+                }).start();
+            }
+
+            String keyboard = item_json.optString("keyboard");
+            if (!keyboard.equals("number") && !keyboard.equals("int")) {
+
+                return;
+            }
+            String filterStr;
+            if (keyboard.equals("number")) {
+                filterStr = string.replaceAll("[^(0-9/.)]", "");
+            } else {
+                filterStr = string.replaceAll("[^(0-9)]", "");
+            }
+            boolean canChange = string.equals(filterStr);
+            int lenght = item_json.optInt("length");
+
+            // 长度控制在textView初始化时
+            if (lenght == 0) {
+
+                if (!canChange) {
+                    textView.setText(origin_text);
+                } else {
+
+                }
+
+            } else {
+                if (canChange) {
+
+                } else {
+                    textView.setText(origin_text);
+                }
+            }
+
+        }
+    }
+
+    /**EditText Focus Listener**/
+    public class EditTextFocusListener implements View.OnFocusChangeListener {
+
+        Context mCtx;
+        int group;
+        int child;
+        EditText et;
+        boolean is_text_field;
+
+        public EditTextFocusListener(Context ctx,EditText textView,int group,int child) {
+            this.mCtx = ctx;
+            this.et = textView;
+            this.group = group;
+            this.child = child;
+
+            String[] tag_arr = ((String) textView.getTag()).split("_");
+            String tag_identifier = tag_arr[2];
+            if (tag_identifier.equals("TextFiled")) {
+                is_text_field = true;
+            } else {
+                is_text_field = false;
+            }
+        }
+
+        @Override
+        public void onFocusChange(View v, boolean hasFocus) {
+
+            if (hasFocus) {
+
+                editTextBeginEditing(et,is_text_field,group,child);
+
+            } else {
+
+                editTextEndEditing(et,is_text_field,group,child);
+                endEditting();
+                lastEditText = null;
+                last_edit_group = -1;
+                last_edit_child = -1;
+            }
+
+
+        }
+    }
+
+    public EditText lastEditText;
+    public int last_edit_group;
+    public int last_edit_child;
+    public String last_edit_str;
+
+    public void endEditting() {
+        if (lastEditText != null) {
+            lastEditText.clearFocus(); // 辞去焦点
+            lastEditText = null;
+        }
+    }
+
+    public void editTextEndEditing(EditText et,boolean is_text_field,int group,int child) {
+        Log.d("Edit", "end editing");
+        if (is_text_field) {
+
+            JSONObject item_json = content_data_control.optJSONArray(group).optJSONObject(child);
+            if (item_json == null) {
+                return;
+            }
+            String fillText = item_json.optString("fill");
+
+            // 没有判断fillText empty会导致重复不断的调用focusChange,并且不能输入
+            if (fillText != null && et.getText().length() == 0 && !fillText.isEmpty()) {
+                et.setText(fillText);
+            }
+            textFieldSetValue(et.getText().toString(),group,child);
+
+        } else {
+
+            try {
+                JSONObject section_json = null;
+                JSONObject item_json = content_data_control.optJSONArray(group).optJSONObject(child);
+                String subid = item_json.optString("subid");
+                item_json.put("dirty","true");
+                item_json.put("value",et.getText().toString());
+                if (subid == null || subid.isEmpty()) {
+                    section_json = content_data_download.optJSONObject("section_" + group);
+                    int count = 0;
+                    count = section_json.optInt("count");
+                    for (int i = 0; i < count;i++) {
+                        JSONObject olditem = section_json.optJSONObject("item_" + i);
+                        if (olditem.optString("name").equals(item_json.optString("name"))) {
+                            section_json.put("item_" + i,item_json);
+                        }
+                    }
+                } else {
+                    String[] idarr = subid.split("_");
+                    int section = Integer.valueOf(idarr[0]);
+                    int item = Integer.valueOf(idarr[1]);
+
+                    section_json = content_data_download.optJSONObject("section_" + section);
+                    JSONObject olditem = section_json.optJSONObject("item_" + item);
+                    String control_type = olditem.optString("control");
+                    if (control_type.equals("enum")) {
+                        item_json = enum_subitem_changed(olditem,idarr,item_json,2);
+                    } else if (control_type.equals("switch")) {
+                        item_json = switch_subitem_changed(olditem,idarr,item_json,2);
+                    }
+                    item_json.put("dirty","true");
+                    section_json.put("item_" + item,item_json);
+
+                }
+
+                content_data_download.put("section_" + group, section_json);
+                content_data_control = translateChange(content_data_download,changed_data);
+
+
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+
+        }
+
+    }
+
+    public void editTextBeginEditing(EditText et,boolean is_text_field,int group,int child) {
+        Log.d("Edit", "begin editing");
+
+        lastEditText = et;
+        last_edit_group = group;
+        last_edit_child = child;
+
+        et.setSelection(et.getText().length());
+        if (is_text_field) {
+
+            JSONObject item_json = content_data_control.optJSONArray(group).optJSONObject(child);
+            String clear_str = item_json.optString("clear");
+            String et_str = et.getText().toString();
+            if (clear_str != null && !clear_str.isEmpty() && et_str != null && !et_str.isEmpty()) {
+                double clear_double = Double.valueOf(clear_str);
+                double et_double = Double.valueOf(et_str);
+                boolean clear = clear_double == et_double;
+                if (clear == true) {
+                    et.setText(null);
+                }
+            }
+
+
+        } else {
+            // Text View
+
+        }
+    }
+
+
+    /**Text View Change**/
+    public class TextViewTextWatcher implements TextWatcher {
+
+        Context mCtx;
+        int group;
+        int child;
+        EditText textView;
+
+        public TextViewTextWatcher(Context ctx,EditText textView,int group,int child) {
+            this.mCtx = ctx;
+            this.textView = textView;
+            this.group = group;
+            this.child = child;
+        }
+
+        String origin_text;
+        String string;
+        int start_position;
+        int change_length; // 修改原文长度
+        int new_string_length;
+
+        @Override
+        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+            origin_text = s.toString();
+            start_position = start;
+            change_length = count;
+            new_string_length = after;
+        }
+
+        @Override
+        public void onTextChanged(CharSequence s, int start, int before, int count) {
+
+        }
+
+        @Override
+        public void afterTextChanged(Editable s) {
+
+            /**
+             * 文本处理
+             * */
+            if (new_string_length == 0) {
+                string = "";
+            } else {
+                string = s.toString().substring(start_position,start_position + new_string_length);
+            }
+
+            if (change_length == 0) { // 新加内容
+
+            } else { // 替换原文或删除原文
+
+            }
+
+            /**
+             * 业务逻辑
+             * */
+
+            JSONObject item_json = content_data_control.optJSONArray(group).optJSONObject(child);
+            if (item_json == null) {
+                return;
+            }
+            String required = item_json.optString("required");
+            if (required.equals("true") && string.length() == 0 && (origin_text == null || origin_text.length() < 1)) {
+                // cell red shadow
+            } else {
+                // cell clear shadow
+            }
+
+        }
+    }
+}

+ 59 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/ContactListActivity.java

@@ -0,0 +1,59 @@
+package com.example.commoneditorlib;
+
+import android.content.Context;
+import android.content.Intent;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+
+import com.usai.redant.redantmobile.R;
+
+import org.json.JSONObject;
+
+import java.io.Serializable;
+
+public class ContactListActivity extends AppCompatActivity {
+
+
+    static String IS_SUBACTION = "is_subaction";
+    static String SUBACTION_TAG = "subaction_tag";
+    static String GROUP = "group";
+    static String CHILD = "child";
+    static String CONTACT_TYPE = "contact_type";
+    static String SHOW_NAV_BAR = "show_navigation_bar";
+    static String RETURN_VALUE = "return_value";
+
+
+    public static class Builder {
+
+        public Intent build(Context ctx, String is_subaction, String subaction_tag,String contact_type,boolean show_nav_bar,int group, int child) {
+            if (ctx == null) {
+                return null;
+            }
+
+            Intent intent = new Intent(ctx,CreditCardEditorActivity.class);
+
+            if (is_subaction != null) {
+                intent.putExtra(IS_SUBACTION,is_subaction);
+            }
+            if (subaction_tag != null) {
+                intent.putExtra(SUBACTION_TAG,subaction_tag);
+            }
+            if (contact_type != null) {
+                intent.putExtra(CONTACT_TYPE,contact_type);
+            }
+
+            intent.putExtra(SHOW_NAV_BAR,show_nav_bar);
+            intent.putExtra(GROUP,group);
+            intent.putExtra(CHILD,child);
+
+
+            return intent;
+        }
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_contact_list);
+    }
+}

+ 66 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/CreditCardEditorActivity.java

@@ -0,0 +1,66 @@
+package com.example.commoneditorlib;
+
+import android.content.Context;
+import android.content.Intent;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+
+import com.usai.redant.redantmobile.R;
+
+import org.json.JSONObject;
+
+import java.io.Serializable;
+
+public class CreditCardEditorActivity extends AppCompatActivity {
+
+
+    static String URL_TYPE = "url_type";
+    static String REQUEST_URL = "request_url";
+    static String IS_SUBACTION = "is_subaction";
+    static String SUBACTION_TAG = "subaction_tag";
+    static String GROUP = "group";
+    static String CHILD = "child";
+    static String ORDERCODE = "order_code";
+    static String DOWNLOADDATA = "download_data";
+    static String RETURN_VALUE = "return_value";
+
+    public static class Builder {
+
+        public Intent build(Context ctx, int url_type, String request_url, String order_code, String is_subaction, String subaction_tag, JSONObject download_data, int group, int child) {
+            if (ctx == null) {
+                return null;
+            }
+            Intent intent = new Intent(ctx,CreditCardEditorActivity.class);
+
+            intent.putExtra(URL_TYPE ,url_type);
+
+            if (request_url != null) {
+                intent.putExtra(REQUEST_URL,request_url);
+            }
+            if (is_subaction != null) {
+                intent.putExtra(IS_SUBACTION,is_subaction);
+            }
+            if (subaction_tag != null) {
+                intent.putExtra(SUBACTION_TAG,subaction_tag);
+            }
+            if (order_code != null) {
+                intent.putExtra(ORDERCODE,order_code);
+            }
+            if (download_data != null) {
+                intent.putExtra(DOWNLOADDATA,download_data.toString());
+            }
+
+            intent.putExtra(GROUP,group);
+            intent.putExtra(CHILD,child);
+
+
+            return intent;
+        }
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_credit_card_editor);
+    }
+}

+ 61 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/DatePickerActivity.java

@@ -0,0 +1,61 @@
+package com.example.commoneditorlib;
+
+import android.content.Context;
+import android.content.Intent;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.widget.DatePicker;
+
+import com.usai.redant.redantmobile.R;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class DatePickerActivity extends AppCompatActivity {
+
+    public static class Builder {
+        public Intent build(Context context, Date date, SimpleDateFormat formatter,int pickerMode,String time,int group,int child) {
+
+            if (context == null) {
+                return null;
+            }
+            Intent intent = new Intent(context,DatePickerActivity.class);
+
+            if (date != null) {
+
+            }
+            if (formatter != null) {
+
+            }
+            if (time != null) {
+
+            }
+
+            return intent;
+        }
+    }
+
+    private DatePicker datePicker;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_date_picker);
+
+        datePicker = (DatePicker) findViewById(R.id.date_picker);
+    }
+
+    @Override
+    public void finish() {
+
+        Intent intent = getIntent();
+        String select_date = datePicker.getMonth() + 1 + "/" + datePicker.getDayOfMonth() + "/" + datePicker.getYear();
+
+        String key = intent.getStringExtra("value");
+        intent.putExtra(key,select_date);
+
+        setResult(RESULT_OK,intent);
+
+        super.finish();
+    }
+}

+ 343 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/EnumSelectAndSort/DragListView.java

@@ -0,0 +1,343 @@
+package com.example.commoneditorlib.EnumSelectAndSort;
+
+//import com.usai.redant.redantmobile.R;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.PixelFormat;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.ListView;
+
+import com.example.commoneditorlib.R;
+
+public class DragListView extends ListView
+{
+
+	private ImageView dragImageView;// ����ק�����ʵ����һ��ImageView
+	private int dragSrcPosition;// ��ָ�϶���ԭʼ���б��е�λ��
+	private int dragPosition;// ��ָ�϶���ʱ�򣬵�ǰ�϶������б��е�λ��
+
+	private int dragPoint;// �ڵ�ǰ������е�λ��
+	private int dragOffset;// ��ǰ��ͼ����Ļ�ľ���(����ֻʹ����y������)
+
+	private WindowManager windowManager;// windows���ڿ�����
+	private WindowManager.LayoutParams windowParams;// ���ڿ�����ק�����ʾ�IJ���
+
+	private int scaledTouchSlop;// �жϻ�����һ������
+	private int upScrollBounce;// �϶���ʱ�򣬿�ʼ���Ϲ����ı߽�
+	private int downScrollBounce;// �϶���ʱ�򣬿�ʼ���¹����ı߽�
+
+	public boolean canDrag = true;
+
+	public DragListView(Context context) {
+		this(context,null);
+	}
+
+	public DragListView(Context context, AttributeSet attrs) {
+		this(context, attrs,0);
+	}
+
+	public DragListView(Context context, AttributeSet attrs, int defStyleAttr) {
+
+		super(context, attrs,defStyleAttr);
+		scaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+
+		this.setOnItemClickListener(mItemClickListenter);
+
+	}
+
+	private int lastClickId = -1;
+	private long lastClickTime;
+	private OnItemClickListener mItemClickListenter = new OnItemClickListener()
+	{
+		public void onItemClick(AdapterView<?> parent, View v, int pos, long id)
+		{
+			DragListAdapter adapter = (DragListAdapter) ((ListView) parent)
+					.getAdapter();
+
+			if (adapter.isEnabled(pos) == false)// return if item is a group key
+				return;
+
+			Object dclickitem = getAdapter().getItem(pos);
+
+			// �����˫��,1�����������ж�Ϊ˫��
+			if (pos == lastClickId
+					&& (Math.abs(lastClickTime - System.currentTimeMillis()) < 1000))
+			{
+				lastClickId = -1;
+				lastClickTime = 0;
+				if (pos < adapter.switchpos())
+				{
+					adapter.remove(dclickitem);
+					adapter.insert(dclickitem, adapter.getCount());
+				}
+				else
+				{
+					adapter.remove(dclickitem);
+					adapter.insert(dclickitem, 1);
+
+				}
+				adapter.notifyDataSetChanged();
+
+			}
+			else
+			{
+				lastClickId = pos;
+				lastClickTime = System.currentTimeMillis();
+			}
+		}
+	};
+
+	// ����touch�¼�����ʵ���Ǽ�һ�����
+	@Override
+	public boolean onInterceptTouchEvent(MotionEvent ev)
+	{
+		if (ev.getAction() == MotionEvent.ACTION_DOWN)
+		{
+			int x = (int) ev.getX();
+			int y = (int) ev.getY();
+
+			dragSrcPosition = dragPosition = pointToPosition(x, y);
+			if (dragPosition == AdapterView.INVALID_POSITION)
+			{
+				return super.onInterceptTouchEvent(ev);
+			}
+
+			ViewGroup itemView = (ViewGroup) getChildAt(dragPosition
+					- getFirstVisiblePosition());
+			dragPoint = y - itemView.getTop();
+			dragOffset = (int) (ev.getRawY() - y);
+
+			View dragger = itemView.findViewById(R.id.drag_list_item_image);
+			if (dragger != null && x > dragger.getLeft() - 20)
+			{
+				//
+				upScrollBounce = Math.min(y - scaledTouchSlop, getHeight() / 3);
+				downScrollBounce = Math.max(y + scaledTouchSlop,
+						getHeight() * 2 / 3);
+
+				itemView.setDrawingCacheEnabled(true);
+				Bitmap bm = Bitmap.createBitmap(itemView.getDrawingCache());
+				itemView.setDrawingCacheEnabled(false);// 清除缓存,否则后面会看到
+				startDrag(bm, y);
+			}
+			return false;
+		}
+		return super.onInterceptTouchEvent(ev);
+	}
+
+	private boolean moved = false;
+	/**
+	 * �����¼�
+	 */
+	@Override
+	public boolean onTouchEvent(MotionEvent ev)
+	{
+
+		if (!canDrag) {
+
+			return super.onTouchEvent(ev);
+		}
+
+		if (dragImageView != null && dragPosition != INVALID_POSITION)
+		{
+			int action = ev.getAction();
+			switch (action)
+			{
+			case MotionEvent.ACTION_UP:
+				if (moved) {
+					int upY = (int) ev.getY();
+					stopDrag();
+					onDrop(upY);
+					moved = false;
+				}
+				break;
+			case MotionEvent.ACTION_MOVE:
+				moved = true;
+				int moveY = (int) ev.getY();
+				onDrag(moveY);
+				break;
+			default:
+				break;
+			}
+			return true;
+		}
+		// Ҳ������ѡ�е�Ч��
+		return super.onTouchEvent(ev);
+	}
+
+	/**
+	 * ׼���϶�����ʼ���϶����ͼ��
+	 * 
+	 * @param bm
+	 * @param y
+	 */
+	public void startDrag(Bitmap bm, int y)
+	{
+		stopDrag();
+
+		windowParams = new WindowManager.LayoutParams();
+		windowParams.gravity = Gravity.TOP;
+		windowParams.x = 0;
+		windowParams.y = y - dragPoint + dragOffset;
+		windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
+		windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
+		windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+				| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+				| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
+				| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+		windowParams.format = PixelFormat.TRANSLUCENT;
+		windowParams.windowAnimations = 0;
+
+		ImageView imageView = new ImageView(getContext());
+		imageView.setImageBitmap(bm);
+		windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
+		windowManager.addView(imageView, windowParams);
+		dragImageView = imageView;
+	}
+
+	/**
+	 * ֹͣ�϶���ȥ���϶����ͷ��
+	 */
+	public void stopDrag()
+	{
+		if (dragImageView != null)
+		{
+			windowManager.removeView(dragImageView);
+			dragImageView = null;
+		}
+	}
+
+	/**
+	 * �϶�ִ�У���Move������ִ��
+	 * 
+	 * @param y
+	 */
+	public void onDrag(int y)
+	{
+		if (dragImageView != null)
+		{
+			windowParams.alpha = 0.8f;
+			windowParams.y = y - dragPoint + dragOffset;
+			windowManager.updateViewLayout(dragImageView, windowParams);
+		}
+		// Ϊ�˱��⻬�����ָ��ߵ�ʱ�򣬷���-1������
+		int tempPosition = pointToPosition(0, y);
+		if (tempPosition != INVALID_POSITION)
+		{
+			dragPosition = tempPosition;
+		}
+
+		// ����
+		int scrollHeight = 0;
+		if (y < upScrollBounce)
+		{
+			scrollHeight = 8;// �������Ϲ���8�����أ����������Ϲ����Ļ�
+		}
+		else
+			if (y > downScrollBounce)
+			{
+				scrollHeight = -8;// �������¹���8�����أ������������Ϲ����Ļ�
+			}
+
+		if (scrollHeight != 0)
+		{
+			// ����������setSelectionFromTop()
+			setSelectionFromTop(dragPosition,
+					getChildAt(dragPosition - getFirstVisiblePosition())
+							.getTop() + scrollHeight);
+		}
+	}
+
+	/**
+	 * �϶����µ�ʱ��
+	 * 
+	 * @param y
+	 */
+	public void onDrop(int y)
+	{
+
+		// Ϊ�˱��⻬�����ָ��ߵ�ʱ�򣬷���-1������
+		int tempPosition = pointToPosition(0, y);
+		if (tempPosition != INVALID_POSITION)
+		{
+			dragPosition = tempPosition;
+		}
+
+		// �����߽紦��
+		if (y < getChildAt(1).getTop())
+		{
+			// �����ϱ߽�
+			dragPosition = 1;
+		}
+		else
+			if (y > getChildAt(getChildCount() - 1).getBottom())
+			{
+				// �����±߽�
+				dragPosition = getAdapter().getCount() - 1;
+			}
+
+		// ��ݽ���
+		if (dragPosition > 0 && dragPosition < getAdapter().getCount())
+		{
+			/* @SuppressWarnings("unchecked") */
+			DragListAdapter adapter = (DragListAdapter) getAdapter();
+			Object dragItem = adapter.getItem(dragSrcPosition);
+			adapter.remove(dragItem);
+			adapter.insert(dragItem, tempPosition); // dragSrcPosition 存在的问题:1 -> 0不能移动
+
+
+			adapter.notifyDataSetChanged();;
+		}
+
+	}
+
+	public static class DragListAdapter extends BaseAdapter {
+
+		@Override
+		public int getCount() {
+			return 0;
+		}
+
+		@Override
+		public Object getItem(int i) {
+			return null;
+		}
+
+		@Override
+		public long getItemId(int i) {
+			return 0;
+		}
+
+		@Override
+		public View getView(int i, View view, ViewGroup viewGroup) {
+			return null;
+		}
+
+		public void insert(Object object,int position) {
+
+		}
+
+		public void remove(Object object) {
+
+		}
+
+		public int switchpos() {
+//			for (int i = 1; i < getCount(); i++)
+//			{
+//				if (getItem(i)._id < 0)
+//					return i;
+//			}
+			return -1;
+		}
+	}
+}

+ 642 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/EnumSelectAndSort/EnumSelectAndSortActivity.java

@@ -0,0 +1,642 @@
+package com.example.commoneditorlib.EnumSelectAndSort;
+
+import android.content.Context;
+import android.content.Intent;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.usai.redant.CommonEditor.EnumSlectActivity;
+import com.usai.redant.redantmobile.R;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.Serializable;
+
+public class EnumSelectAndSortActivity extends AppCompatActivity {
+
+
+    static String MAX_SELECT = "max_select";
+    static String GROUP_POSITION = "group";
+    static String CHILD_POSITION = "child";
+    static String CADEDATE = "cadedate";
+    static String SINGLE_SELECT = "single_select";
+    static String TITLE = "title";
+    static String AUTO_CLOSE = "auto_close";
+
+    public static class Builder {
+        public Intent build(Context context, String title, int max_select, int group, int child, String cadedate, boolean single_select, boolean auto_close) {
+            if (context == null) {
+                return null;
+            }
+
+            Intent intent = new Intent(context,EnumSelectAndSortActivity.class);
+
+            intent.putExtra(MAX_SELECT,max_select);
+            intent.putExtra(GROUP_POSITION,group);
+            intent.putExtra(CHILD_POSITION,child);
+            if (cadedate != null) {
+                intent.putExtra(CADEDATE,(Serializable) cadedate);
+            }
+            intent.putExtra(SINGLE_SELECT,single_select);
+            if (title != null) {
+                intent.putExtra(TITLE,title);
+            }
+            intent.putExtra(AUTO_CLOSE,auto_close);
+
+            return intent;
+        }
+    }
+
+    public class SearchBarWatcher implements TextWatcher {
+
+        Context mCtx;
+        EditText textView;
+
+        public SearchBarWatcher(Context ctx,EditText textView) {
+            this.mCtx = ctx;
+            this.textView = textView;
+
+
+        }
+
+        String origin_text;
+        String string;
+        int start_position;
+        int change_length; // 修改原文长度
+        int new_string_length;
+
+
+        /**
+         * s        改变前的内容
+         * start    增加内容前光标位置,删除内容后光标位置 (起始位置)
+         * count    选中s中的内容长度(发生改变的原内容长度),未选中为0
+         * after    新添加的内容长度,删除为0
+         * */
+        @Override
+        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+//            Log.d("TextChange", "before Text Changed: " + s + " Start: " + start + " Count: " + count + " After: " + after);
+
+            origin_text = s.toString();
+            start_position = start;
+            change_length = count;
+            new_string_length = after;
+        }
+
+        /**
+         * s        改变后的内容
+         * start    增加内容前光标位置,删除内容后光标位置 (起始位置)
+         * before   选中s中的内容长度(发生改变的原内容长度),未选中为0
+         * count    增加内容长度,删除内容为0
+         * */
+        @Override
+        public void onTextChanged(CharSequence s, int start, int before, int count) {
+//            Log.d("TextChange", "on Text Changed: " + s + " Start: " + start + " Before: " + before + " Count: " + count);
+        }
+
+        @Override
+        public void afterTextChanged(Editable s) {
+
+            /**
+             * 文本处理
+             * */
+            if (new_string_length == 0) {
+                string = "";
+            } else {
+                string = s.toString().substring(start_position,start_position + new_string_length);
+            }
+
+            if (change_length == 0) { // 新加内容
+
+            } else { // 替换原文或删除原文
+
+            }
+
+            /**
+             * 业务逻辑
+             * */
+
+            if (string.equals("\n") || string.equals("\r") || string.equals("\r\n")) {
+                textView.setText(origin_text);
+                return;
+            }
+
+            mKeywords = s.toString();
+            adapter.notifyDataSetChanged();
+
+            if (mKeywords.isEmpty()) {
+                enum_list_view.canDrag =  true;
+            } else {
+                enum_list_view.canDrag = false;
+            }
+
+        }
+    }
+
+
+
+
+    private int maxSelect;
+    private int mGroup;
+    private int mChild;
+    private boolean mSingleSelect;
+    private String mTitle;
+    private boolean mAuto_close;
+    private JSONObject mCadedate;
+    private boolean mDirty;
+
+    private String mKeywords;
+    private int filter_count;
+
+    private DragListView enum_list_view;
+    private EnumAdapter adapter;
+    private Context mCtx;
+
+    private EditText searchBar;
+//    private boolean isEditing = false;
+
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_enum_select_and_sort);
+
+        init();
+
+        setTitle(mTitle);
+
+        searchBar = (EditText)findViewById(R.id.common_editor_enum_select_sort_search_bar);
+        searchBar.addTextChangedListener(new SearchBarWatcher(mCtx,searchBar));
+
+        enum_list_view = (DragListView) findViewById(R.id.enum__select_sort_list_view);
+
+        adapter = new EnumAdapter(mCtx);
+        enum_list_view.setAdapter(adapter);
+
+        enum_list_view.setOnItemClickListener(new CellClickListener(mCtx));
+
+    }
+
+//    @Override
+//    public boolean onCreateOptionsMenu(Menu menu) {
+//        getMenuInflater().inflate(R.menu.enum_select_sort_menu,menu);
+//        return true;
+//    }
+//
+//    @Override
+//    public boolean onOptionsItemSelected(MenuItem item) {
+//
+////        if (item.getItemId() == R.id.enum_menu_sort) {
+////            if (isEditing) {
+////                isEditing = false;
+////                item.setTitle("Sort");
+////            } else {
+////                isEditing = true;
+////                item.setTitle("End Sort");
+////            }
+////
+////            adapter.notifyDataSetChanged();
+////        }
+//        return true;
+//    }
+
+    @Override
+    public void finish() {
+
+        if (mDirty != false) {
+            Intent intent = new Intent();
+            intent.putExtra(CADEDATE,mCadedate.toString());
+            intent.putExtra(GROUP_POSITION,mGroup);
+            intent.putExtra(CHILD_POSITION,mChild);
+
+            setResult(RESULT_OK,intent);
+        }
+
+
+        super.finish();
+    }
+
+    private void init() {
+        mCtx = this;
+        Intent intent = getIntent();
+        String cadedate_str = intent.getStringExtra(CADEDATE);
+        try {
+            mCadedate = new JSONObject(cadedate_str);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        mSingleSelect = intent.getBooleanExtra(SINGLE_SELECT,true);
+        mGroup = intent.getIntExtra(GROUP_POSITION,0);
+        mChild = intent.getIntExtra(CHILD_POSITION,0);
+        mTitle = intent.getStringExtra(TITLE);
+        maxSelect = intent.getIntExtra(MAX_SELECT,0);
+        mAuto_close = intent.getBooleanExtra(AUTO_CLOSE,true);
+
+
+    }
+
+    private class CellClickListener implements AdapterView.OnItemClickListener {
+
+        private Context ctx;
+        public CellClickListener(Context ctx) {
+            this.ctx = ctx;
+        }
+
+        @Override
+        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+
+//            if (isEditing) {
+//                return;
+//            }
+
+            mDirty = true;
+
+            try {
+                if (mSingleSelect) {
+
+                    boolean is_worked = false;
+
+                    if (mKeywords == null || mKeywords.isEmpty()) {
+
+                        for (int i = 0; i < mCadedate.optInt("count"); i++) {
+                            JSONObject val_json = mCadedate.optJSONObject("val_" + i);
+
+                            if (i == position) {
+                                int select = val_json.optInt("check");
+                                if (select == 0) {
+                                    val_json.put("check","1");
+                                } else {
+                                    val_json.put("check","0");
+                                }
+                                is_worked = select == 0;
+                            } else {
+                                val_json.put("check","0");
+                            }
+                            mCadedate.put("val_" + i,val_json);
+
+
+
+                        } // for
+
+                    } // keywords null
+                    else {
+
+
+                        JSONObject val_json = null;
+                        int count = 0;
+                        boolean getIt = false;
+                        for (int cc = 0; cc < mCadedate.optInt("count"); cc++) {
+
+                            JSONObject search_json = mCadedate.optJSONObject("val_" + cc);
+                            String value = search_json.optString("value");
+                            boolean contain = value.toUpperCase().contains(mKeywords.toUpperCase());
+                            if (contain && count < filter_count) {
+                                count++;
+                            }
+
+                            val_json = search_json;
+                            if (!getIt && count - 1 == position) {
+                                getIt = true;
+
+                                //==========
+                                int select = val_json.optInt("check");
+                                if (select != 0) {
+                                    val_json.put("check","0");
+                                } else {
+                                    val_json.put("check","1");
+                                }
+                                is_worked = select == 0;
+
+                            } else  {
+                                val_json.put("check","0");
+                            }
+
+                            mCadedate.put("val_" + cc,val_json);
+                        } // for cc
+
+//                        for (int sc = 0; sc < mCadedate.optInt("count"); sc++) {
+//
+//                            JSONObject sc_json = mCadedate.optJSONObject("val_" + sc);
+//
+//                            if (sc_json.optString("value").equals(val_json.optString("value"))) {
+//                                sc_json.put("check","1");
+//                            } else {
+//                                sc_json.put("check","0");
+//                            }
+//                            mCadedate.put("val_" + sc,sc_json);
+//
+//                        } // for sc
+
+
+                    }
+
+                    if (is_worked) {
+                        if (mAuto_close) {
+                            finish();
+                        } else {
+                            adapter.notifyDataSetChanged();
+                        }
+                    } else {
+                        adapter.notifyDataSetChanged();
+                    }
+
+
+                } // single select
+                else {
+
+                    int index = position;
+                    JSONObject val_json = null;
+                    if (mKeywords == null || mKeywords.isEmpty()) {
+                        val_json = mCadedate.optJSONObject("val_" + position);
+                    } else {
+                        int count = 0;
+                        for (int i = 0; i < mCadedate.optInt("count"); i++) {
+                            if (count >= filter_count) {
+                                break;
+                            }
+                            JSONObject search_json = mCadedate.optJSONObject("val_" + i);
+                            String value = search_json.optString("value");
+                            boolean contain = value.toUpperCase().contains(mKeywords.toUpperCase());
+                            if (contain) {
+                                count++;
+                            }
+
+                            if (count - 1 == position) {
+                                val_json = search_json;
+                                index = i;
+                                break;
+                            }
+                        }
+                    }
+
+                    int check = val_json.optInt("check");
+                    if (check == 1) {
+                        val_json.put("check","0");
+                    } else {
+                        if (check_count() >= maxSelect && maxSelect > 0) {
+                            new AlertDialog.Builder(this.ctx)
+                                    .setTitle("Max count reached")
+                                    .setMessage(maxSelect + " items at most for this field.")
+                                    .setPositiveButton("OK",null)
+                                    .show();
+                            return;
+
+                        }
+                        val_json.put("check","1");
+                    }
+                    mCadedate.put("val_" + index,val_json);
+
+                }
+                adapter.notifyDataSetChanged();
+
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+
+        }
+    }
+
+    public int check_count() {
+
+        int check_count = 0;
+        for (int i = 0; i < mCadedate.optInt("count"); i++) {
+            JSONObject val_json = mCadedate.optJSONObject("val_" + i);
+            int check = val_json.optInt("check");
+            if (check == 1) {
+                check_count++;
+            }
+        }
+        return check_count;
+    }
+
+
+    private class EnumAdapter extends DragListView.DragListAdapter {
+
+        public class Holder {
+            public TextView value_tv;
+            public ImageView check_iv;
+            public ImageView drag_iv;
+
+            public Holder(View cell) {
+                if (cell == null) {
+                    return;
+                }
+                value_tv = (TextView)cell.findViewById(R.id.enum_value_tv);
+                check_iv = (ImageView)cell.findViewById(R.id.enum_check_iv);
+                check_iv.setClickable(false);
+                check_iv.setFocusable(false);
+                drag_iv = (ImageView)cell.findViewById(R.id.drag_list_item_image);
+
+                cell.setTag(this);
+
+            }
+        }
+
+
+        private Context ctx;
+        public EnumAdapter(Context context) {
+            this.ctx = context;
+        }
+
+        @Override
+        public int getCount() {
+
+            if (mCadedate == null) {
+                return 0;
+            }
+
+            if (mKeywords == null || mKeywords.isEmpty()) {
+                filter_count = 0;
+                return mCadedate.optInt("count");
+            }
+
+            int count = 0;
+            for (int i = 0; i < mCadedate.optInt("count"); i++) {
+                JSONObject val_json = mCadedate.optJSONObject("val_" + i);
+                String value = val_json.optString("value");
+                boolean contain = value.toUpperCase().contains(mKeywords.toUpperCase());
+                if (contain) {
+                    count++;
+                }
+            }
+            filter_count = count;
+            return count;
+        }
+
+        @Override
+        public Object getItem(int position) {
+            JSONObject val_json = null;
+            if (mKeywords == null || mKeywords.isEmpty()) {
+                val_json = mCadedate.optJSONObject("val_" + position);
+            } else {
+                int count = 0;
+                for (int i = 0; i < mCadedate.optInt("count"); i++) {
+                    if (count >= filter_count) {
+                        break;
+                    }
+                    JSONObject search_json = mCadedate.optJSONObject("val_" + i);
+                    String value = search_json.optString("value");
+                    boolean contain = value.toUpperCase().contains(mKeywords.toUpperCase());
+                    if (contain) {
+                        count++;
+                    } else {
+                        continue;
+                    }
+
+                    if (count - 1 == position) {
+                        val_json = search_json;
+                        break;
+                    }
+
+                }
+            }
+            return val_json;
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            JSONObject val_json = (JSONObject) getItem(position);
+//            if (mKeywords == null || mKeywords.isEmpty()) {
+//                val_json = mCadedate.optJSONObject("val_" + position);
+//            } else {
+//                val_json = (JSONObject) getItem(position);
+//            }
+
+            Holder holder;
+            if (convertView == null) {
+
+                convertView = LayoutInflater.from(this.ctx).inflate(R.layout.enum_select_sort_cell,null);
+                holder = new Holder(convertView);
+
+            } else {
+                holder = (Holder) convertView.getTag();
+            }
+
+            String value = val_json.optString("value");
+            holder.value_tv.setText(value);
+
+            int check = val_json.optInt("check");
+            if (check == 1) {
+                holder.check_iv.setVisibility(View.VISIBLE);
+            } else {
+                holder.check_iv.setVisibility(View.INVISIBLE);
+            }
+
+
+//            if (isEditing) {
+//                holder.check_iv.setVisibility(View.INVISIBLE);
+//                holder.drag_iv.setVisibility(View.VISIBLE);
+//                holder.drag_iv.setFocusable(false);
+//                holder.drag_iv.setClickable(false);
+//            } else {
+//                if (check == 1) {
+//                    holder.check_iv.setVisibility(View.VISIBLE);
+//                } else {
+//                    holder.check_iv.setVisibility(View.INVISIBLE);
+//                }
+//                holder.drag_iv.setFocusable(false);
+//                holder.drag_iv.setClickable(false);
+//                holder.drag_iv.setVisibility(View.INVISIBLE);
+//            }
+
+            return convertView;
+        }
+
+        @Override
+        public void insert(Object object,int position) {
+
+            int count = getCount();
+
+            mDirty = true;
+            if (position >= count) {
+                if (position > count) {
+                    position = count;
+                }
+
+                JSONObject val_json = (JSONObject)object;
+                try {
+                    mCadedate.put("val_" + position, val_json);
+                    mCadedate.put("count", count+1);
+                } catch (JSONException e) {
+                    e.printStackTrace();
+                }
+
+
+            } else {
+                if (position < 0) {
+                    position = 0;
+                }
+
+                try {
+                    for (int i = count - 1; i >= position; i--) {
+                        JSONObject val_json = mCadedate.getJSONObject("val_" + i);
+                        mCadedate.put("val_" + (i + 1),val_json);
+                    }
+
+                    JSONObject val_json = (JSONObject)object;
+                    mCadedate.put("val_" + position, val_json);
+                    mCadedate.put("count", count+1);
+
+                } catch (JSONException e) {
+                    e.printStackTrace();
+                }
+
+            }
+        }
+
+        @Override
+        public void remove(Object object) {
+
+            int count = getCount();
+            if (count <= 0) {
+                return;
+            }
+
+            mDirty = true;
+            try {
+                int remove_index = count;
+                for (int i = 0; i < count; i++) {
+                    JSONObject val_json = mCadedate.getJSONObject("val_" + i);
+                    if (val_json.equals(object)) {
+                        remove_index = i;
+                    }
+                    if (remove_index < count) { // 有删除
+                        if (i > remove_index) {
+                            mCadedate.put("val_" + (i - 1),val_json);
+                        }
+
+                        if (i == count - 1) { // 清除末尾
+                            mCadedate.put("val_" + i,null);
+                        }
+                        mCadedate.put("count",count - 1);
+                    }
+                }
+            } catch (JSONException e) {
+                e.printStackTrace();
+            }
+
+        }
+    }
+
+
+
+}

+ 506 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/EnumSlectActivity.java

@@ -0,0 +1,506 @@
+package com.example.commoneditorlib;
+
+import android.content.Context;
+import android.content.Intent;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.usai.redant.redantmobile.R;
+
+import org.json.JSONObject;
+
+import java.io.Serializable;
+import java.util.zip.Inflater;
+
+public class EnumSlectActivity extends AppCompatActivity {
+
+    static String MAX_SELECT = "max_select";
+    static String GROUP_POSITION = "group";
+    static String CHILD_POSITION = "child";
+    static String CADEDATE = "cadedate";
+    static String SINGLE_SELECT = "single_select";
+    static String TITLE = "title";
+    static String AUTO_CLOSE = "auto_close";
+
+    public static class Builder {
+        public Intent build(Context context,String title, int max_select, int group, int child, String cadedate,boolean single_select,boolean auto_close) {
+            if (context == null) {
+                return null;
+            }
+
+            Intent intent = new Intent(context,EnumSlectActivity.class);
+
+            intent.putExtra(MAX_SELECT,max_select);
+            intent.putExtra(GROUP_POSITION,group);
+            intent.putExtra(CHILD_POSITION,child);
+            if (cadedate != null) {
+                intent.putExtra(CADEDATE,(Serializable) cadedate);
+            }
+            intent.putExtra(SINGLE_SELECT,single_select);
+            if (title != null) {
+                intent.putExtra(TITLE,title);
+            }
+            intent.putExtra(AUTO_CLOSE,auto_close);
+
+            return intent;
+        }
+    }
+
+    public class SearchBarWatcher implements TextWatcher {
+
+        Context mCtx;
+        EditText textView;
+
+        public SearchBarWatcher(Context ctx,EditText textView) {
+            this.mCtx = ctx;
+            this.textView = textView;
+
+
+        }
+
+        String origin_text;
+        String string;
+        int start_position;
+        int change_length; // 修改原文长度
+        int new_string_length;
+
+
+        /**
+         * s        改变前的内容
+         * start    增加内容前光标位置,删除内容后光标位置 (起始位置)
+         * count    选中s中的内容长度(发生改变的原内容长度),未选中为0
+         * after    新添加的内容长度,删除为0
+         * */
+        @Override
+        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+//            Log.d("TextChange", "before Text Changed: " + s + " Start: " + start + " Count: " + count + " After: " + after);
+
+            origin_text = s.toString();
+            start_position = start;
+            change_length = count;
+            new_string_length = after;
+        }
+
+        /**
+         * s        改变后的内容
+         * start    增加内容前光标位置,删除内容后光标位置 (起始位置)
+         * before   选中s中的内容长度(发生改变的原内容长度),未选中为0
+         * count    增加内容长度,删除内容为0
+         * */
+        @Override
+        public void onTextChanged(CharSequence s, int start, int before, int count) {
+//            Log.d("TextChange", "on Text Changed: " + s + " Start: " + start + " Before: " + before + " Count: " + count);
+        }
+
+        @Override
+        public void afterTextChanged(Editable s) {
+
+            /**
+             * 文本处理
+             * */
+            if (new_string_length == 0) {
+                string = "";
+            } else {
+                string = s.toString().substring(start_position,start_position + new_string_length);
+            }
+
+            if (change_length == 0) { // 新加内容
+
+            } else { // 替换原文或删除原文
+
+            }
+
+            /**
+             * 业务逻辑
+             * */
+
+            if (string.equals("\n") || string.equals("\r") || string.equals("\r\n")) {
+                textView.setText(origin_text);
+                return;
+            }
+
+            mKeywords = s.toString();
+            adapter.notifyDataSetChanged();
+
+        }
+    }
+
+
+    private int maxSelect;
+    private int mGroup;
+    private int mChild;
+    private boolean mSingleSelect;
+    private String mTitle;
+    private boolean mAuto_close;
+    private JSONObject mCadedate;
+    private boolean mDirty;
+
+    private String mKeywords;
+    private int filter_count;
+
+    private ListView enum_list_view;
+    private EnumAdapter adapter;
+    private Context mCtx;
+
+    private EditText searchBar;
+
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_enum_slect);
+
+        init();
+
+        setTitle(mTitle);
+
+        searchBar = (EditText)findViewById(R.id.common_editor_enum_search_bar);
+        searchBar.addTextChangedListener(new SearchBarWatcher(mCtx,searchBar));
+
+        enum_list_view = (ListView)findViewById(R.id.enum_list_view);
+
+        adapter = new EnumAdapter(mCtx);
+        enum_list_view.setAdapter(adapter);
+
+        enum_list_view.setOnItemClickListener(new CellClickListener(mCtx));
+
+
+    }
+
+    @Override
+    public void finish() {
+
+        if (mDirty != false) {
+            Intent intent = new Intent();
+            intent.putExtra(CADEDATE,mCadedate.toString());
+            intent.putExtra(GROUP_POSITION,mGroup);
+            intent.putExtra(CHILD_POSITION,mChild);
+
+            setResult(RESULT_OK,intent);
+        }
+
+
+        super.finish();
+    }
+
+    private void init() {
+        mCtx = this;
+        Intent intent = getIntent();
+        String cadedate_str = intent.getStringExtra(CADEDATE);
+        try {
+            mCadedate = new JSONObject(cadedate_str);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        mSingleSelect = intent.getBooleanExtra(SINGLE_SELECT,true);
+        mGroup = intent.getIntExtra(GROUP_POSITION,0);
+        mChild = intent.getIntExtra(CHILD_POSITION,0);
+        mTitle = intent.getStringExtra(TITLE);
+        maxSelect = intent.getIntExtra(MAX_SELECT,0);
+        mAuto_close = intent.getBooleanExtra(AUTO_CLOSE,true);
+
+
+    }
+
+    private class CellClickListener implements AdapterView.OnItemClickListener {
+
+        private Context ctx;
+        public CellClickListener(Context ctx) {
+            this.ctx = ctx;
+        }
+
+        @Override
+        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+
+            mDirty = true;
+
+            try {
+                if (mSingleSelect) {
+
+                    boolean is_worked = false;
+
+                    if (mKeywords == null || mKeywords.isEmpty()) {
+
+                        for (int i = 0; i < mCadedate.optInt("count"); i++) {
+                            JSONObject val_json = mCadedate.optJSONObject("val_" + i);
+
+                            if (i == position) {
+                                int select = val_json.optInt("check");
+                                if (select == 0) {
+                                    val_json.put("check","1");
+                                } else {
+                                    val_json.put("check","0");
+                                }
+                                is_worked = select == 0;
+                            } else {
+                                val_json.put("check","0");
+                            }
+                            mCadedate.put("val_" + i,val_json);
+
+
+
+                        } // for
+
+                    } // keywords null
+                    else {
+
+
+                        JSONObject val_json = null;
+                        int count = 0;
+                        boolean getIt = false;
+                        for (int cc = 0; cc < mCadedate.optInt("count"); cc++) {
+
+                            JSONObject search_json = mCadedate.optJSONObject("val_" + cc);
+                            String value = search_json.optString("value");
+                            boolean contain = value.toUpperCase().contains(mKeywords.toUpperCase());
+                            if (contain && count < filter_count) {
+                                count++;
+                            }
+
+                            val_json = search_json;
+                            if (!getIt && count - 1 == position) {
+                                getIt = true;
+                                //==========
+                                int select = val_json.optInt("check");
+                                if (select != 0) {
+                                    val_json.put("check","0");
+                                } else {
+                                    val_json.put("check","1");
+                                }
+                                is_worked = select == 0;
+
+                            } else  {
+                                val_json.put("check","0");
+                            }
+
+                            mCadedate.put("val_" + cc,val_json);
+
+
+                        } // for cc
+
+//                        for (int sc = 0; sc < mCadedate.optInt("count"); sc++) {
+//
+//                            JSONObject sc_json = mCadedate.optJSONObject("val_" + sc);
+//
+//                            if (sc_json.optString("value").equals(val_json.optString("value"))) {
+//                                sc_json.put("check","1");
+//                            } else {
+//                                sc_json.put("check","0");
+//                            }
+//                            mCadedate.put("val_" + sc,sc_json);
+//
+//                        } // for sc
+
+
+                    }
+
+                    if (is_worked) {
+                        if (mAuto_close) {
+                            finish();
+                        } else {
+                            adapter.notifyDataSetChanged();
+                        }
+                    } else {
+                        adapter.notifyDataSetChanged();
+                    }
+
+
+                } // single select
+                else {
+
+                    int index = position;
+                    JSONObject val_json = null;
+                    if (mKeywords == null || mKeywords.isEmpty()) {
+                        val_json = mCadedate.optJSONObject("val_" + position);
+                    } else {
+                        int count = 0;
+                        for (int i = 0; i < mCadedate.optInt("count"); i++) {
+                            if (count >= filter_count) {
+                                break;
+                            }
+                            JSONObject search_json = mCadedate.optJSONObject("val_" + i);
+                            String value = search_json.optString("value");
+                            boolean contain = value.toUpperCase().contains(mKeywords.toUpperCase());
+                            if (contain) {
+                                count++;
+                            }
+
+                            if (count - 1 == position) {
+                                val_json = search_json;
+                                index = i;
+                                break;
+                            }
+                        }
+                    }
+
+                    int check = val_json.optInt("check");
+                    if (check == 1) {
+                        val_json.put("check","0");
+                    } else {
+                        if (check_count() >= maxSelect && maxSelect > 0) {
+                            new AlertDialog.Builder(this.ctx)
+                                    .setTitle("Max count reached")
+                                    .setMessage(maxSelect + " items at most for this field.")
+                                    .setPositiveButton("OK",null)
+                                    .show();
+                            return;
+
+                        }
+                        val_json.put("check","1");
+                    }
+                    mCadedate.put("val_" + index,val_json);
+
+                }
+                adapter.notifyDataSetChanged();
+
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+
+        }
+    }
+
+    public int check_count() {
+
+        int check_count = 0;
+        for (int i = 0; i < mCadedate.optInt("count"); i++) {
+            JSONObject val_json = mCadedate.optJSONObject("val_" + i);
+            int check = val_json.optInt("check");
+            if (check == 1) {
+                check_count++;
+            }
+        }
+        return check_count;
+    }
+
+
+    private class EnumAdapter extends BaseAdapter {
+
+        public class Holder {
+            public TextView value_tv;
+            public ImageView check_iv;
+
+            public Holder(View cell) {
+                if (cell == null) {
+                    return;
+                }
+                value_tv = (TextView)cell.findViewById(R.id.enum_value_tv);
+                check_iv = (ImageView)cell.findViewById(R.id.enum_check_iv);
+                check_iv.setClickable(false);
+                check_iv.setFocusable(false);
+                cell.setTag(this);
+
+            }
+        }
+
+
+        private Context ctx;
+        public EnumAdapter(Context context) {
+            this.ctx = context;
+        }
+
+        @Override
+        public int getCount() {
+
+            if (mCadedate == null) {
+                return 0;
+            }
+
+            if (mKeywords == null || mKeywords.isEmpty()) {
+                filter_count = 0;
+                return mCadedate.optInt("count");
+            }
+
+            int count = 0;
+            for (int i = 0; i < mCadedate.optInt("count"); i++) {
+                JSONObject val_json = mCadedate.optJSONObject("val_" + i);
+                String value = val_json.optString("value");
+                boolean contain = value.toUpperCase().contains(mKeywords.toUpperCase());
+                if (contain) {
+                    count++;
+                }
+            }
+            filter_count = count;
+            return count;
+        }
+
+        @Override
+        public Object getItem(int position) {
+            JSONObject val_json = null;
+            if (mKeywords == null || mKeywords.isEmpty()) {
+                val_json = mCadedate.optJSONObject("val_" + position);
+            } else {
+                int count = 0;
+                for (int i = 0; i < mCadedate.optInt("count"); i++) {
+                    if (count >= filter_count) {
+                        break;
+                    }
+                    JSONObject search_json = mCadedate.optJSONObject("val_" + i);
+                    String value = search_json.optString("value");
+                    boolean contain = value.toUpperCase().contains(mKeywords.toUpperCase());
+                    if (contain) {
+                        count++;
+                    } else {
+                        continue;
+                    }
+
+                    if (count - 1 == position) {
+                        val_json = search_json;
+                        break;
+                    }
+
+                }
+            }
+            return val_json;
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            JSONObject val_json = (JSONObject) getItem(position);
+//            if (mKeywords == null || mKeywords.isEmpty()) {
+//                val_json = mCadedate.optJSONObject("val_" + position);
+//            } else {
+//                val_json = (JSONObject) getItem(position);
+//            }
+
+            Holder holder;
+            if (convertView == null) {
+
+                convertView = LayoutInflater.from(this.ctx).inflate(R.layout.enum_select_cell,null);
+                holder = new Holder(convertView);
+
+            } else {
+                holder = (Holder) convertView.getTag();
+            }
+
+            String value = val_json.optString("value");
+            holder.value_tv.setText(value);
+
+            int check = val_json.optInt("check");
+            if (check == 1) {
+                holder.check_iv.setVisibility(View.VISIBLE);
+            } else {
+                holder.check_iv.setVisibility(View.INVISIBLE);
+            }
+
+            return convertView;
+        }
+    }
+}

+ 204 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/ImageUploadActivity.java

@@ -0,0 +1,204 @@
+package com.example.commoneditorlib;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.os.Environment;
+import android.provider.MediaStore;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.Toast;
+
+
+import com.usai.redant.redantmobile.R;
+
+import java.io.File;
+import java.util.UUID;
+
+public class ImageUploadActivity extends AppCompatActivity {
+
+    private ImageView imageView;
+    private ImageButton albumBtn;
+    private ImageButton takeBtn;
+    private ImageButton uploadBtn;
+    private String img_path;
+    private Bitmap bitmap;
+
+    private Context mCtx = this;
+
+    private static int ALBUM_REQUEST_CODE = 1;
+    private static int CAMERA_REQUEST_CODE = 2;
+
+    private int group;
+    private int child;
+    private int btn_tag;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_image_upload);
+
+        imageView = (ImageView) findViewById(R.id.img_view);
+        albumBtn = (ImageButton) findViewById(R.id.photo_library_btn);
+        takeBtn = (ImageButton) findViewById(R.id.tack_photo_btn);
+        uploadBtn = (ImageButton) findViewById(R.id.photo_upload_btn);
+
+        Intent intent = getIntent();
+        group = intent.getIntExtra("group",0);
+        child = intent.getIntExtra("child",0);
+        btn_tag = intent.getIntExtra("btn",0);
+
+
+        if (savedInstanceState != null) {
+            img_path = savedInstanceState.getString("img_path");
+            if (img_path != null && !img_path.isEmpty()) {
+                bitmap = BitmapFactory.decodeFile(img_path);
+                imageView.setImageBitmap(bitmap);
+            }
+        }
+
+        albumBtn.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                Intent intent = new Intent(Intent.ACTION_PICK, null);
+                intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
+                intent.setAction(Intent.ACTION_GET_CONTENT);
+                startActivityForResult(intent, ALBUM_REQUEST_CODE);
+            }
+        });
+
+        takeBtn.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                img_path = startCamera((ImageUploadActivity)mCtx,CAMERA_REQUEST_CODE);
+            }
+        });
+
+        uploadBtn.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+
+
+                if (img_path != null && !img_path.isEmpty()) {
+                    // upload
+
+
+                    UUID uuid = UUID.randomUUID();
+                    String img_path = Utils.cacheTmpImage(bitmap);
+
+                    // upload success
+                    Intent intent = new Intent();
+                    intent.putExtra("url_down",uuid.toString());
+                    intent.putExtra("url_up",uuid.toString());
+                    intent.putExtra("path",img_path);
+                    intent.putExtra("group",group);
+                    intent.putExtra("child",child);
+                    intent.putExtra("btn",btn_tag);
+                    setResult(RESULT_OK,intent);
+                    finish();
+                }
+
+            }
+        });
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+
+        outState.putString("img_path",img_path);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+
+        if (requestCode == ALBUM_REQUEST_CODE) {
+            if (resultCode == RESULT_OK) {
+                try {
+                    Uri uri = data.getData();
+                    final String absolutePath= getAbsolutePath(this, uri);
+                    img_path = absolutePath;
+                    if (img_path != null) {
+                        bitmap = BitmapFactory.decodeFile(img_path);
+                        imageView.setImageBitmap(bitmap);
+                    }
+
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+
+        if (requestCode == CAMERA_REQUEST_CODE) {
+            if (resultCode == RESULT_OK) {
+
+                if (img_path != null) {
+                    bitmap = BitmapFactory.decodeFile(img_path);
+                    imageView.setImageBitmap(bitmap);
+                }
+
+            }
+        }
+
+    }
+
+    public String getAbsolutePath(final Context context, final Uri uri) {
+        if (null == uri) return null;
+        final String scheme = uri.getScheme();
+        String data = null;
+        if (scheme == null)
+            data = uri.getPath();
+        else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
+            data = uri.getPath();
+        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
+            Cursor cursor = context.getContentResolver().query(uri,
+                    new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
+            if (null != cursor) {
+                if (cursor.moveToFirst()) {
+                    int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
+                    if (index > -1) {
+                        data = cursor.getString(index);
+                    }
+                }
+                cursor.close();
+            }
+        }
+        return data;
+    }
+
+    public static String startCamera(Activity activity, int requestCode) {
+        // 指定相机拍摄照片保存地址
+        String state = Environment.getExternalStorageState();
+        if (state.equals(Environment.MEDIA_MOUNTED)) {
+            Intent intent = new Intent();
+            // 指定开启系统相机的Action
+            intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
+            File outDir = Environment
+                    .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
+            if (!outDir.exists()) {
+                outDir.mkdirs();
+            }
+            File outFile = new File(outDir, System.currentTimeMillis() + ".jpg");
+            // 把文件地址转换成Uri格式
+            Uri uri = Uri.fromFile(outFile);
+            // 设置系统相机拍摄照片完成后图片文件的存放地址
+            intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
+            // 此值在最低质量最小文件尺寸时是0,在最高质量最大文件尺寸时是1
+            intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
+            activity.startActivityForResult(intent, requestCode);
+            return outFile.getAbsolutePath();
+        } else {
+            Toast.makeText(activity, "请确认已经插入SD卡",
+                    Toast.LENGTH_LONG).show();
+            return null;
+        }
+    }
+}

+ 16 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/ImageViewActivity.java

@@ -0,0 +1,16 @@
+package com.example.commoneditorlib;
+
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+
+import com.usai.redant.redantmobile.R;
+
+
+public class ImageViewActivity extends AppCompatActivity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_image_view);
+    }
+}

+ 113 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/MonthPickerActivity.java

@@ -0,0 +1,113 @@
+package com.example.commoneditorlib;
+
+import android.content.Context;
+import android.content.Intent;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.NumberPicker;
+
+import com.usai.redant.redantmobile.R;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class MonthPickerActivity extends AppCompatActivity {
+
+    public static class Builder {
+        public Intent build(Context context, String date, int group, int child) {
+
+            if (context == null) {
+                return null;
+            }
+            Intent intent = new Intent(context,MonthPickerActivity.class);
+
+            if (date != null) {
+                intent.putExtra("date",date);
+            }
+
+            intent.putExtra("group",group);
+            intent.putExtra("child",child);
+
+
+            return intent;
+        }
+    }
+
+    private NumberPicker yearPicker = null;
+    private NumberPicker monthPicker = null;
+
+    private int year;
+    private int month;
+    private int group;
+    private int child;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_month_picker);
+
+
+        yearPicker = (NumberPicker) findViewById(R.id.year_picker);
+        yearPicker.setMaxValue(2050);
+        yearPicker.setMinValue(2000);
+
+        monthPicker = (NumberPicker) findViewById(R.id.month_picker);
+        String[] monthArr = {"January","February","March","April","May","June","July","August","September","October","November","December"};
+        monthPicker.setDisplayedValues(monthArr);
+        monthPicker.setMinValue(0);
+        monthPicker.setMaxValue(monthArr.length - 1);
+
+        init();
+    }
+
+    private void init() {
+
+        Intent intent = getIntent();
+
+
+        group = intent.getIntExtra("group",0);
+        child = intent.getIntExtra("child",0);
+        String date_str = intent.getStringExtra("date");
+
+        if (date_str != null) {
+            String[] date_arr = date_str.split("/");
+            year = Integer.valueOf(date_arr[1]);
+            month = Integer.valueOf(date_arr[0]);
+        } else {
+            month = 1;
+            year = 2017;
+        }
+
+        yearPicker.setValue(year);
+        monthPicker.setValue(month - 1);
+
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.set_menu,menu);
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case R.id.set_item: {
+                int year = yearPicker.getValue();
+                int month = monthPicker.getValue() + 1;
+                String date_str = month + "/" + year;
+                Intent intent = new Intent();
+                intent.putExtra("value",date_str);
+                intent.putExtra("group",group);
+                intent.putExtra("child",child);
+                setResult(RESULT_OK,intent);
+                finish();
+            }
+            break;
+        }
+        return true;
+    }
+}

+ 93 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/SignatureActivity.java

@@ -0,0 +1,93 @@
+package com.example.commoneditorlib;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.usai.redant.redantmobile.R;
+
+public class SignatureActivity extends AppCompatActivity {
+
+
+    public static class Builder {
+        public Intent build(Context context,int group, int child) {
+            Intent intent = new Intent(context,SignatureActivity.class);
+
+            intent.putExtra("group",group);
+            intent.putExtra("child",child);
+
+            return intent;
+        }
+    }
+
+    private BrushView brushView;
+    private int group,child;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_signature);
+
+        brushView = (BrushView) findViewById(R.id.brush_view);
+
+//        brushView = new BrushView(this);
+//        setContentView(brushView);
+
+        Intent intent = getIntent();
+        group = intent.getIntExtra("group",0);
+        child = intent.getIntExtra("child",0);
+
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.signature_action_bar_menu,menu);
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+
+        switch (item.getItemId()) {
+            case R.id.save_signature_item: {
+                if (brushView.checkCanSave()) {
+                    Bitmap bitmap = brushView.getDrawBitmap();
+                    String path = Utils.cacheTmpImage(bitmap);
+
+                    // upload signature
+
+                    // upload success
+                    Intent intent = new Intent();
+                    intent.putExtra("url_down",path);
+                    intent.putExtra("url_up",path);
+                    intent.putExtra("path",path);
+                    intent.putExtra("group",group);
+                    intent.putExtra("child",child);
+
+                    setResult(RESULT_OK,intent);
+                    finish();
+                } else {
+
+                    new AlertDialog.Builder(this)
+                            .setTitle("Warning")
+                            .setMessage("Please Sign")
+                            .setPositiveButton("Ok",null)
+                            .show();
+
+                }
+            }
+            break;
+            case R.id.clear_signature_item: {
+                brushView.clear();
+            }
+            break;
+        }
+
+        return true;
+    }
+}

+ 314 - 0
ApexDrivers/CommonEditorLib/src/main/java/com/example/commoneditorlib/Utils.java

@@ -0,0 +1,314 @@
+package com.example.commoneditorlib;
+
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Bundle;
+import android.os.Environment;
+import android.support.v7.app.AlertDialog;
+
+import com.usai.redant.redantmobile.RedAntApplication;
+
+import org.json.JSONObject;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.UUID;
+
+/**
+ * Created by macmini1 on 2017/8/17.
+ */
+
+public class Utils {
+
+    public static String getApplicationName(Context context) {
+
+        if (context == null) {
+            return null;
+        }
+
+        PackageManager packageManager = null;
+        ApplicationInfo applicationInfo = null;
+        try {
+            packageManager = context.getPackageManager();
+            applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0);
+        } catch (PackageManager.NameNotFoundException e) {
+            applicationInfo = null;
+        }
+        String applicationName = (String) packageManager.getApplicationLabel(applicationInfo);
+        return applicationName;
+    }
+
+    public static String stringToMD5(String string) {
+        byte[] hash;
+
+        try {
+            hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+            return null;
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+            return null;
+        }
+
+        StringBuilder hex = new StringBuilder(hash.length * 2);
+        for (byte b : hash) {
+            if ((b & 0xFF) < 0x10)
+                hex.append("0");
+            hex.append(Integer.toHexString(b & 0xFF));
+        }
+
+        return hex.toString();
+    }
+
+    public static Bitmap loadCacheImage(String path,Bitmap holder) {
+
+//        System.gc();
+//        try {
+//            Context context = RedAntApplication.getInstance().getApplicationContext();
+//            String file_path = Environment.getExternalStorageDirectory().getPath() + "/" + getApplicationName(context) + "/Cache/Image" + stringToMD5(path);
+//            File file = new File(file_path);
+//            if (!file.exists()) {
+//                loadImage(path);
+//                return holder;
+//            }
+//            Bitmap bitmap = BitmapFactory.decodeFile(file_path);
+//            return bitmap;
+//
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+//
+//        return holder;
+
+        return loadCacheImage(path,holder,false);
+    }
+
+    public static Bitmap loadCacheImage(String path,Bitmap holder, boolean remoteLoad) {
+        System.gc();
+        try {
+            Context context = RedAntApplication.getInstance().getApplicationContext();
+            String file_path = Environment.getExternalStorageDirectory().getPath() + "/" + getApplicationName(context) + "/Cache/Image" + stringToMD5(path);
+            File file = new File(file_path);
+            if (!file.exists()) {
+                if (remoteLoad) {
+                    loadImage(path);
+                }
+                return holder;
+            }
+            Bitmap bitmap = BitmapFactory.decodeFile(file_path);
+            return bitmap;
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return holder;
+    }
+
+    public static String cacheTmpImage(Bitmap bitmap) {
+        if (bitmap == null) {
+            return null;
+        }
+
+        bitmap = compressBitmap(bitmap);
+
+        Context context = RedAntApplication.getInstance().getApplicationContext();
+        String file_path = Environment.getExternalStorageDirectory().getPath() + "/" + getApplicationName(context) + "/Cache/Tmp";
+        File dir_file = new File(file_path);
+        if (!dir_file.exists()) {
+            dir_file.mkdirs();
+        }
+        file_path = file_path + UUID.randomUUID().toString();
+        try {
+
+            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file_path));
+            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
+            bos.flush();
+            bos.close();
+
+            return file_path;
+        } catch (IOException e) {
+            e.printStackTrace();
+
+        }
+
+        return null;
+
+    }
+
+    public static void loadImage(final String path) {
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                HttpURLConnection cnn = null;
+                Bitmap bitmap = null;
+                try {
+                    URL url = new URL(path);
+                    cnn = (HttpURLConnection)url.openConnection();
+                    cnn.setRequestMethod("GET");
+                    cnn.setUseCaches(false);
+                    cnn.setConnectTimeout(1500);
+                    cnn.setReadTimeout(1500);
+                    bitmap = BitmapFactory.decodeStream(cnn.getInputStream());
+
+                    if (bitmap != null) {
+                        cacheImage(path,bitmap);
+                    }
+
+
+                } catch (IOException e) {
+                    e.printStackTrace();
+
+                } finally {
+                    if (cnn != null) {
+                        cnn.disconnect();
+                    }
+
+                }
+            }
+        }).start();
+    }
+
+    public static void cacheLocalImageToURL(String path,String url) {
+
+
+        String filename =stringToMD5(url);
+        File file = new File(path);
+
+
+
+        if (file.exists()) {
+
+            Context context = RedAntApplication.getInstance().getApplicationContext();
+            String file_path = Environment.getExternalStorageDirectory().getPath() + "/" + getApplicationName(context) + "/Cache/Image";
+            File tmpF = new File(file_path);
+            if (!tmpF.exists()) {
+                tmpF.mkdirs();
+            }
+            file_path = file_path + "/" + filename;
+
+            InputStream is = null;
+            FileOutputStream os = null;
+            try {
+                is = new FileInputStream(file);
+                os = new FileOutputStream(file_path);
+                byte[] buffer = new byte[1024];
+                int read = 0;
+                while ((read = is.read(buffer)) != -1) {
+                    os.write(buffer,0,read);
+                }
+
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                try {
+
+                    os.flush();
+                    os.close();
+                    is.close();
+
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+
+        }
+
+    }
+
+    public static void cacheImage(String path,Bitmap bitmap) {
+
+
+        bitmap = compressBitmap(bitmap);
+
+        try {
+
+            Context context = RedAntApplication.getInstance().getApplicationContext();
+            String file_dir = Environment.getExternalStorageDirectory().getPath() + "/" + getApplicationName(context) + "/Cache/Image";
+            File dir = new File(file_dir);
+            if (!dir.exists()) {
+                dir.mkdirs();
+            }
+            String file_path = file_dir + "/" + stringToMD5(path);
+
+            File file = new File(file_path);
+
+            savePhotoToFile(bitmap,file);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+
+    }
+
+    private static Bitmap compressBitmap(Bitmap bitmap) {
+        int width = 500;
+        int height = 500;
+        if (bitmap.getWidth() > width || bitmap.getHeight() > height) {
+            bitmap = Bitmap.createScaledBitmap(bitmap,width,height,false);
+        }
+        return bitmap;
+    }
+
+    private static void savePhotoToFile(Bitmap bitmap, File photoFile) {
+        if (photoFile == null || bitmap == null) {
+            return;
+        }
+        try {
+
+            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(photoFile));
+            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
+            bos.flush();
+            bos.close();
+
+        } catch (IOException e) {
+            e.printStackTrace();
+
+        }
+    }
+
+
+    public static ProgressDialog waiting_alert(Context ctx,String title, String msg) {
+        if (ctx == null) {
+            return null;
+        }
+        ProgressDialog pd = new ProgressDialog(ctx);
+        pd.setTitle(title);
+        pd.setMessage(msg);
+
+        pd.setCancelable(true);
+
+        pd.show();
+
+        return pd;
+    }
+
+    public static void message_alert(Context ctx,String title,String msg) {
+        if (ctx == null) {
+            return;
+        }
+        new AlertDialog.Builder(ctx)
+                .setTitle(title)
+                .setMessage(msg)
+                .show();
+    }
+
+
+
+
+}

+ 21 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/activity_address_editor.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    tools:context="com.usai.redant.CommonEditor.AddressEditorActivity">
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        />
+    <EditText
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        />
+
+</LinearLayout>

+ 18 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_action_cell.xml

@@ -0,0 +1,18 @@
+<?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="44dp">
+
+    <TextView
+        android:id="@+id/action_cell_lb"
+        android:layout_width="match_parent"
+        android:layout_height="44dp"
+        android:layout_margin="5dp"
+        android:textSize="17sp"
+        android:textColor="#000000"
+        android:textAlignment="center"
+        android:gravity="center"
+        android:text="Label"
+        />
+
+</RelativeLayout>

+ 18 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_auto_complete_list_cell.xml

@@ -0,0 +1,18 @@
+<?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="40dp"
+    android:minHeight="40dp">
+
+
+    <TextView
+        android:id="@+id/auto_complete_value_tv"
+        android:layout_width="match_parent"
+        android:layout_height="40dp"
+        android:layout_margin="5dp"
+        android:gravity="start|center_vertical"
+        android:textColor="#000000"
+        android:textSize="17sp"
+        />
+
+</RelativeLayout>

+ 100 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_date_range_cell.xml

@@ -0,0 +1,100 @@
+<?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="120dp">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="40dp"
+        >
+
+        <TextView
+            android:id="@+id/range_title_tv"
+            android:layout_width="match_parent"
+            android:layout_height="40dp"
+            android:layout_centerVertical="true"
+            android:gravity="start|center_vertical"
+            android:layout_margin="5dp"
+            android:textSize="17sp"
+            android:textColor="#000000"
+            android:text="Label"
+            />
+
+    </RelativeLayout>
+
+
+
+    <LinearLayout
+        android:layout_height="80dp"
+        android:layout_width="match_parent"
+        >
+        <!--left-->
+        <RelativeLayout
+            android:layout_height="match_parent"
+            android:layout_width="0dp"
+            android:layout_weight="1"
+            >
+
+            <Button
+                android:id="@+id/range_minimum_btn"
+                android:layout_width="100dp"
+                android:layout_height="40dp"
+                android:layout_centerVertical="true"
+                android:layout_marginLeft="10dp"
+                android:layout_marginRight="10dp"
+                android:background="@drawable/black_border"
+                android:gravity="center"
+                android:hint="minimum"
+                android:textSize="17sp"/>
+
+        </RelativeLayout>
+
+        <!--mid-->
+        <RelativeLayout
+            android:layout_height="match_parent"
+            android:layout_width="0dp"
+            android:layout_weight="1"
+            >
+
+            <Button
+                android:id="@+id/range_maximum_btn"
+                android:layout_width="100dp"
+                android:layout_height="40dp"
+                android:layout_centerVertical="true"
+                android:layout_marginLeft="10dp"
+                android:layout_marginRight="10dp"
+                android:background="@drawable/black_border"
+                android:gravity="center"
+                android:hint="maximum"
+                android:textSize="17sp"/>
+
+
+        </RelativeLayout>
+
+        <!--right-->
+        <RelativeLayout
+            android:layout_height="match_parent"
+            android:layout_width="0dp"
+            android:layout_weight="1"
+            >
+
+            <Button
+                android:id="@+id/range_reset_btn"
+                android:layout_width="100dp"
+                android:layout_height="40dp"
+                android:layout_centerVertical="true"
+                android:layout_marginLeft="10dp"
+                android:layout_marginRight="10dp"
+                android:background="#00000000"
+                android:gravity="center"
+                android:textSize="17sp"
+                android:text="Reset"
+                android:textAllCaps="false"/>
+
+        </RelativeLayout>
+
+    </LinearLayout>
+
+
+</LinearLayout>

+ 63 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_edit_auto_complete_cell.xml

@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="44dp"
+              android:orientation="horizontal">
+
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="44dp"
+        android:orientation="horizontal"
+        >
+
+        <RelativeLayout
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:layout_centerVertical="true"
+            >
+
+            <TextView
+                android:id="@+id/name_lb"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerVertical="true"
+                android:layout_marginLeft="5dp"
+                android:layout_marginStart="5dp"
+                android:textSize="17sp"
+                android:textColor="#000000"
+                android:text="Label"
+                android:gravity="left|center_vertical"
+                />
+
+            <TextView
+                android:id="@+id/start_mark"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toEndOf="@id/name_lb"
+                android:layout_toRightOf="@id/name_lb"
+                android:layout_alignTop="@id/name_lb"
+                android:text="*"
+                android:textColor="#000000"
+                />
+
+        </RelativeLayout>
+
+        <AutoCompleteTextView
+            android:id="@+id/textField"
+            android:layout_width="0dp"
+            android:layout_weight="4"
+            android:layout_height="match_parent"
+            android:layout_marginLeft="5dp"
+            android:layout_marginStart="5dp"
+            android:layout_marginTop="5dp"
+            android:layout_marginRight="5dp"
+            android:layout_marginEnd="5dp"
+            android:lines="1"
+            android:ellipsize="end"
+            />
+
+        </LinearLayout>
+
+</LinearLayout>

+ 66 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_edit_auto_complete_cell_small.xml

@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="70dp"
+              android:orientation="vertical">
+
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="70dp"
+        android:orientation="vertical"
+        >
+
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            android:layout_centerVertical="true"
+            >
+
+            <TextView
+                android:id="@+id/name_lb"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerVertical="true"
+                android:layout_marginLeft="5dp"
+                android:layout_marginStart="5dp"
+                android:textSize="17sp"
+                android:textColor="#000000"
+                android:text="Label"
+                android:gravity="left|center_vertical"
+                />
+
+            <TextView
+                android:id="@+id/start_mark"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toEndOf="@id/name_lb"
+                android:layout_toRightOf="@id/name_lb"
+                android:layout_alignTop="@id/name_lb"
+                android:text="*"
+                android:textColor="#000000"
+                />
+
+        </RelativeLayout>
+
+
+        <AutoCompleteTextView
+            android:id="@+id/textField"
+            android:layout_width="match_parent"
+            android:layout_weight="2"
+            android:layout_height="0dp"
+            android:layout_marginLeft="5dp"
+            android:layout_marginStart="5dp"
+            android:layout_marginTop="5dp"
+            android:layout_marginRight="5dp"
+            android:layout_marginEnd="5dp"
+            android:lines="1"
+            android:ellipsize="end"
+            />
+
+
+    </LinearLayout>
+
+</LinearLayout>

+ 63 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_edit_cell.xml

@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="44dp"
+              android:orientation="horizontal">
+
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="44dp"
+        android:orientation="horizontal"
+        >
+
+        <RelativeLayout
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:layout_centerVertical="true"
+            >
+
+            <TextView
+                android:id="@+id/name_lb"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerVertical="true"
+                android:layout_marginLeft="5dp"
+                android:layout_marginStart="5dp"
+                android:textSize="17sp"
+                android:textColor="#000000"
+                android:text="Label"
+                android:gravity="left|center_vertical"
+                />
+
+            <TextView
+                android:id="@+id/start_mark"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toEndOf="@id/name_lb"
+                android:layout_toRightOf="@id/name_lb"
+                android:layout_alignTop="@id/name_lb"
+                android:text="*"
+                android:textColor="#000000"
+                />
+
+        </RelativeLayout>
+
+        <EditText
+            android:id="@+id/textField"
+            android:layout_width="0dp"
+            android:layout_weight="4"
+            android:layout_height="match_parent"
+            android:layout_marginLeft="5dp"
+            android:layout_marginStart="5dp"
+            android:layout_marginTop="5dp"
+            android:layout_marginRight="5dp"
+            android:layout_marginEnd="5dp"
+            android:lines="1"
+            android:ellipsize="end"
+            />
+
+        </LinearLayout>
+
+</LinearLayout>

+ 66 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_edit_cell_small.xml

@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="70dp"
+              android:orientation="vertical">
+
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="70dp"
+        android:orientation="vertical"
+        >
+
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            android:layout_centerVertical="true"
+            >
+
+            <TextView
+                android:id="@+id/name_lb"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerVertical="true"
+                android:layout_marginLeft="5dp"
+                android:layout_marginStart="5dp"
+                android:textSize="17sp"
+                android:textColor="#000000"
+                android:text="Label"
+                android:gravity="left|center_vertical"
+                />
+
+            <TextView
+                android:id="@+id/start_mark"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toEndOf="@id/name_lb"
+                android:layout_toRightOf="@id/name_lb"
+                android:layout_alignTop="@id/name_lb"
+                android:text="*"
+                android:textColor="#000000"
+                />
+
+        </RelativeLayout>
+
+
+        <EditText
+            android:id="@+id/textField"
+            android:layout_width="match_parent"
+            android:layout_weight="2"
+            android:layout_height="0dp"
+            android:layout_marginLeft="5dp"
+            android:layout_marginStart="5dp"
+            android:layout_marginTop="5dp"
+            android:layout_marginRight="5dp"
+            android:layout_marginEnd="5dp"
+            android:lines="1"
+            android:ellipsize="end"
+            />
+
+
+    </LinearLayout>
+
+</LinearLayout>

+ 90 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_enum_cell.xml

@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="44dp"
+                android:orientation="horizontal">
+
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="44dp"
+        android:orientation="horizontal"
+        >
+        <RelativeLayout
+            android:layout_width="0dp"
+            android:layout_weight="1"
+            android:layout_height="match_parent"
+            android:layout_centerVertical="true"
+            >
+
+            <TextView
+                android:id="@+id/enum_title_lb"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerVertical="true"
+                android:layout_marginLeft="5dp"
+                android:layout_marginStart="5dp"
+                android:textSize="17sp"
+                android:textColor="#000000"
+                android:text="Label"
+                android:gravity="start|center_vertical"
+                android:textAlignment="textStart"
+                />
+            <TextView
+                android:id="@+id/start_mark"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toEndOf="@id/enum_title_lb"
+                android:layout_toRightOf="@id/enum_title_lb"
+                android:layout_alignTop="@id/enum_title_lb"
+                android:text="*"
+                android:textColor="#000000"
+                />
+
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:layout_width="0dp"
+            android:layout_weight="4"
+            android:layout_height="match_parent"
+            android:layout_centerVertical="true"
+            >
+
+            <ImageView
+                android:id="@+id/more_info"
+                android:layout_width="20dp"
+                android:layout_height="match_parent"
+                android:layout_alignParentEnd="true"
+                android:layout_alignParentRight="true"
+                android:layout_marginEnd="10dp"
+                android:layout_marginRight="10dp"
+                android:scaleType="centerCrop"
+                android:src="@drawable/more_info"
+                />
+
+            <TextView
+                android:id="@+id/enum_value_lb"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_centerVertical="true"
+                android:layout_marginLeft="5dp"
+                android:layout_marginStart="5dp"
+                android:layout_alignParentStart="true"
+                android:layout_alignParentLeft="true"
+                android:layout_toLeftOf="@id/more_info"
+                android:layout_toStartOf="@id/more_info"
+                android:textSize="17sp"
+                android:textColor="#000000"
+                android:text="Label"
+                android:gravity="start|center_vertical"
+                android:textAlignment="textStart"
+                android:maxLines="1"
+                android:ellipsize="end"
+                />
+
+
+
+        </RelativeLayout>
+    </LinearLayout>
+
+</LinearLayout>

+ 90 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_enum_cell_small.xml

@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="70dp"
+                android:orientation="vertical">
+
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="70dp"
+        android:orientation="vertical"
+        >
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_weight="1"
+            android:layout_height="0dp"
+            android:layout_centerVertical="true"
+            >
+
+            <TextView
+                android:id="@+id/enum_title_lb"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerVertical="true"
+                android:layout_marginLeft="5dp"
+                android:layout_marginStart="5dp"
+                android:textSize="17sp"
+                android:textColor="#000000"
+                android:text="Label"
+                android:gravity="start|center_vertical"
+                android:textAlignment="textStart"
+                />
+            <TextView
+                android:id="@+id/start_mark"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toEndOf="@id/enum_title_lb"
+                android:layout_toRightOf="@id/enum_title_lb"
+                android:layout_alignTop="@id/enum_title_lb"
+                android:text="*"
+                android:textColor="#000000"
+                />
+
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_weight="2"
+            android:layout_height="0dp"
+            android:layout_centerVertical="true"
+            >
+
+            <ImageView
+                android:id="@+id/more_info"
+                android:layout_width="20dp"
+                android:layout_height="match_parent"
+                android:layout_alignParentEnd="true"
+                android:layout_alignParentRight="true"
+                android:layout_marginEnd="5dp"
+                android:layout_marginRight="5dp"
+                android:scaleType="centerCrop"
+                android:src="@drawable/more_info"
+                />
+
+            <TextView
+                android:id="@+id/enum_value_lb"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_centerVertical="true"
+                android:layout_marginLeft="5dp"
+                android:layout_marginStart="5dp"
+                android:layout_alignParentStart="true"
+                android:layout_alignParentLeft="true"
+                android:layout_toLeftOf="@id/more_info"
+                android:layout_toStartOf="@id/more_info"
+                android:textSize="17sp"
+                android:textColor="#000000"
+                android:text="Label"
+                android:gravity="start|center_vertical"
+                android:textAlignment="textStart"
+                android:maxLines="1"
+                android:ellipsize="end"
+                />
+
+
+
+        </RelativeLayout>
+    </LinearLayout>
+
+</LinearLayout>

+ 67 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_image_cell.xml

@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="horizontal"
+              android:layout_width="match_parent"
+              android:layout_height="130dp">
+
+   <LinearLayout
+       android:layout_width="match_parent"
+       android:layout_height="130dp">
+
+       <TextView
+           android:id="@+id/img_cell_title_lb"
+           android:layout_width="0dp"
+           android:layout_weight="3"
+           android:layout_height="match_parent"
+           android:layout_margin="5dp"
+           android:textSize="17sp"
+           android:textColor="#000000"
+           android:text="Label"
+           android:gravity="start|center_vertical"
+           android:textAlignment="textStart"
+           />
+       <TextView
+           android:id="@+id/img_cell_desc_lb"
+           android:layout_width="0dp"
+           android:layout_weight="5"
+           android:layout_height="match_parent"
+           android:layout_margin="5dp"
+           android:textSize="17sp"
+           android:textColor="#000000"
+           android:text="Label"
+           android:gravity="start|center_vertical"
+           android:textAlignment="textStart"
+           />
+       <LinearLayout
+           android:orientation="horizontal"
+           android:layout_width="0dp"
+           android:layout_weight="7"
+           android:layout_height="match_parent">
+
+           <ImageButton
+               android:id="@+id/img_btn_0"
+               android:layout_weight="1"
+               android:layout_width="0dp"
+               android:layout_height="match_parent"
+               android:layout_margin="5dp"
+               />
+           <ImageButton
+               android:id="@+id/img_btn_1"
+               android:layout_weight="1"
+               android:layout_width="0dp"
+               android:layout_height="match_parent"
+               android:layout_margin="5dp"
+               />
+           <ImageButton
+               android:id="@+id/img_btn_2"
+               android:layout_weight="1"
+               android:layout_width="0dp"
+               android:layout_height="match_parent"
+               android:layout_margin="5dp"
+               />
+
+       </LinearLayout>
+
+   </LinearLayout>
+
+</LinearLayout>

+ 79 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_image_cell_small.xml

@@ -0,0 +1,79 @@
+<?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="160dp">
+
+   <LinearLayout
+       android:layout_width="match_parent"
+       android:layout_height="160dp"
+       android:orientation="vertical"
+       >
+
+       <LinearLayout
+           android:layout_width="match_parent"
+           android:layout_height="0dp"
+           android:layout_weight="1"
+           android:orientation="horizontal"
+           >
+
+           <TextView
+               android:id="@+id/img_cell_title_lb"
+               android:layout_width="0dp"
+               android:layout_weight="3"
+               android:layout_height="match_parent"
+               android:layout_margin="5dp"
+               android:textSize="17sp"
+               android:textColor="#000000"
+               android:text="Label"
+               android:gravity="start|center_vertical"
+               android:textAlignment="textStart"
+               />
+           <TextView
+               android:id="@+id/img_cell_desc_lb"
+               android:layout_width="0dp"
+               android:layout_weight="5"
+               android:layout_height="match_parent"
+               android:layout_margin="5dp"
+               android:textSize="17sp"
+               android:textColor="#000000"
+               android:text="Label"
+               android:gravity="start|center_vertical"
+               android:textAlignment="textStart"
+               />
+
+       </LinearLayout>
+       <LinearLayout
+           android:orientation="horizontal"
+           android:layout_width="match_parent"
+           android:layout_weight="3"
+           android:layout_height="0dp">
+
+           <ImageButton
+               android:id="@+id/img_btn_0"
+               android:layout_weight="1"
+               android:layout_width="0dp"
+               android:layout_height="match_parent"
+               android:layout_margin="5dp"
+               />
+           <ImageButton
+               android:id="@+id/img_btn_1"
+               android:layout_weight="1"
+               android:layout_width="0dp"
+               android:layout_height="match_parent"
+               android:layout_margin="5dp"
+               />
+
+           <ImageButton
+               android:id="@+id/img_btn_2"
+               android:layout_width="0dp"
+               android:layout_height="match_parent"
+               android:layout_margin="5dp"
+               android:layout_weight="1"
+               />
+
+       </LinearLayout>
+
+   </LinearLayout>
+
+</LinearLayout>

+ 43 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_label_cell.xml

@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="44dp"
+              android:orientation="horizontal">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="44dp"
+        android:orientation="horizontal"
+        >
+
+        <TextView
+            android:id="@+id/cell_title_lb"
+            android:layout_width="0dp"
+            android:layout_weight="1"
+            android:layout_height="match_parent"
+            android:textSize="17sp"
+            android:textColor="#000000"
+            android:text="Label"
+            android:gravity="left|center_vertical"
+            android:layout_margin="5dp"
+            />
+
+        <TextView
+            android:id="@+id/cell_value_lb"
+            android:layout_width="0dp"
+            android:layout_weight="4"
+            android:layout_height="match_parent"
+            android:layout_marginLeft="5dp"
+            android:layout_marginStart="5dp"
+            android:textSize="17sp"
+            android:textColor="#000000"
+            android:text="Label"
+            android:gravity="right|center_vertical"
+            android:layout_margin="5dp"
+            android:maxLines="1"
+            android:ellipsize="end"
+            />
+
+    </LinearLayout>
+
+</LinearLayout>

+ 43 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_label_cell_small.xml

@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="75dp"
+              android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="75dp"
+        android:orientation="vertical"
+        >
+
+        <TextView
+            android:id="@+id/cell_title_lb"
+            android:layout_width="match_parent"
+            android:layout_weight="1"
+            android:layout_height="0dp"
+            android:textSize="17sp"
+            android:textColor="#000000"
+            android:text="Label"
+            android:gravity="left|center_vertical"
+            android:layout_margin="5dp"
+            />
+
+        <TextView
+            android:id="@+id/cell_value_lb"
+            android:layout_width="match_parent"
+            android:layout_weight="2"
+            android:layout_height="0dp"
+            android:layout_marginLeft="5dp"
+            android:layout_marginStart="5dp"
+            android:textSize="17sp"
+            android:textColor="#000000"
+            android:text="Label"
+            android:gravity="right|center_vertical"
+            android:layout_margin="5dp"
+            android:maxLines="1"
+            android:ellipsize="end"
+            />
+
+    </LinearLayout>
+
+</LinearLayout>

+ 204 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_model_cell.xml

@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="100dp">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="100dp"
+        >
+
+        <LinearLayout
+            android:layout_width="0dp"
+            android:layout_weight="1"
+            android:layout_height="match_parent"
+            android:gravity="center">
+
+            <ImageButton
+                android:id="@+id/model_img_view"
+                android:layout_width="match_parent"
+                android:layout_height="50dp"
+                android:layout_alignParentLeft="true"
+                android:layout_alignParentStart="true"
+                android:layout_centerVertical="true"
+                android:layout_margin="5dp"
+                android:background="#00000000"
+                />
+
+        </LinearLayout>
+
+
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="0dp"
+            android:layout_weight="6"
+            android:layout_height="match_parent"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
+            >
+
+            <LinearLayout
+                android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_weight="3"
+                >
+                <TextView
+                    android:id="@+id/model_desc_lb"
+                    android:layout_width="0dp"
+                    android:layout_weight="2"
+                    android:layout_height="match_parent"
+                    android:text="name and description"
+                    android:textSize="10sp"
+                    android:textColor="#000000"
+                    android:gravity="center_vertical|start"
+                    />
+
+                <LinearLayout
+                    android:orientation="vertical"
+                    android:layout_width="0dp"
+                    android:layout_weight="2"
+                    android:layout_height="match_parent"
+                    >
+
+                    <TextView
+                        android:id="@+id/model_master_pack_lb"
+                        android:layout_width="match_parent"
+                        android:layout_height="0dp"
+                        android:layout_weight="1"
+                        android:ellipsize="end"
+                        android:gravity="center"
+                        android:lines="1"
+                        android:text="Master pack:9999"
+                        android:textColor="#000000"
+                        android:textSize="10sp"
+                        />
+
+                    <TextView
+                        android:id="@+id/model_old_price_lb"
+                        android:layout_width="match_parent"
+                        android:layout_height="0dp"
+                        android:layout_weight="1"
+                        android:ellipsize="end"
+                        android:gravity="center"
+                        android:lines="1"
+                        android:text="$1234567.00"
+                        android:textColor="@android:color/holo_red_dark"
+                        android:textSize="10sp"
+                        />
+
+                    <TextView
+                        android:id="@+id/model_discount_lb"
+                        android:layout_width="match_parent"
+                        android:layout_height="0dp"
+                        android:layout_weight="1"
+                        android:ellipsize="end"
+                        android:gravity="center"
+                        android:lines="1"
+                        android:text="Discount 99.99% off"
+                        android:textColor="#000000"
+                        android:textSize="10sp"
+                        />
+
+                </LinearLayout>
+
+                <LinearLayout
+                    android:orientation="vertical"
+                    android:layout_width="0dp"
+                    android:layout_weight="1"
+                    android:layout_height="match_parent"
+                    >
+
+                    <TextView
+                        android:layout_width="match_parent"
+                        android:layout_height="0dp"
+                        android:layout_weight="1"
+                        android:ellipsize="end"
+                        android:gravity="center|right"
+                        android:lines="1"
+                        android:text="Price ($)"
+                        android:textColor="#000000"
+                        android:textSize="10sp"
+                        />
+
+                    <TextView
+                        android:id="@+id/model_unit_price_lb"
+                        android:layout_width="match_parent"
+                        android:layout_height="0dp"
+                        android:layout_weight="1"
+                        android:ellipsize="end"
+                        android:gravity="center|right"
+                        android:lines="1"
+                        android:text="1234567.00"
+                        android:textColor="#000000"
+                        android:textSize="10sp"
+                        />
+
+                    <TextView
+                        android:id="@+id/model_count_lb"
+                        android:layout_width="match_parent"
+                        android:layout_height="0dp"
+                        android:layout_weight="1"
+                        android:ellipsize="end"
+                        android:gravity="center|right"
+                        android:lines="1"
+                        android:text="x9999"
+                        android:textColor="#000000"
+                        android:textSize="10sp"
+                        />
+
+                </LinearLayout>
+
+
+            </LinearLayout>
+
+            <LinearLayout
+                android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_weight="1"
+                >
+
+                <RelativeLayout
+                    android:layout_width="0dp"
+                    android:layout_weight="4"
+                    android:layout_height="match_parent"
+                    >
+
+                    <TextView
+                        android:id="@+id/model_bundle_btn"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_centerVertical="true"
+                        android:gravity="center_vertical|start"
+                        android:textColor="#0099ff"
+                        android:text="Button"
+                        android:textSize="10sp"
+                        android:textAllCaps="false"
+                        android:padding="0dp"
+                        />
+
+                </RelativeLayout>
+
+                <TextView
+                    android:id="@+id/model_total_price_lb"
+                    android:layout_width="0dp"
+                    android:layout_weight="1"
+                    android:layout_height="match_parent"
+                    android:ellipsize="end"
+                    android:gravity="center|right"
+                    android:lines="1"
+                    android:text="123456789.00"
+                    android:textColor="#000000"
+                    android:textSize="10sp"
+                    />
+
+            </LinearLayout>
+
+        </LinearLayout>
+
+    </LinearLayout>
+
+
+
+</LinearLayout>

+ 62 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_multiple_action_cell.xml

@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="horizontal"
+              android:layout_width="match_parent"
+              android:layout_height="70dp">
+
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="70dp"
+        >
+        <Button
+            android:id="@+id/btn_0"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:text="Button"
+            android:textSize="10sp"
+            android:textAllCaps="false"
+            android:layout_marginTop="7dp"
+            android:layout_marginBottom="7dp"
+            />
+
+        <Button
+            android:id="@+id/btn_1"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:text="Button"
+            android:textSize="10sp"
+            android:textAllCaps="false"
+            android:layout_marginTop="7dp"
+            android:layout_marginBottom="7dp"
+            />
+
+        <Button
+            android:id="@+id/btn_2"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:text="Button"
+            android:textSize="10sp"
+            android:textAllCaps="false"
+            android:layout_marginTop="7dp"
+            android:layout_marginBottom="7dp"
+            />
+
+        <Button
+            android:id="@+id/btn_3"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:text="Button"
+            android:textSize="10sp"
+            android:textAllCaps="false"
+            android:layout_marginTop="7dp"
+            android:layout_marginBottom="7dp"
+            />
+
+    </LinearLayout>
+
+</LinearLayout>

+ 100 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_range_cell.xml

@@ -0,0 +1,100 @@
+<?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="120dp">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        >
+
+        <TextView
+            android:id="@+id/range_title_tv"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_centerVertical="true"
+            android:gravity="start|center_vertical"
+            android:layout_margin="5dp"
+            android:textSize="17sp"
+            android:textColor="#000000"
+            android:text="Label"
+            />
+
+    </RelativeLayout>
+
+
+
+
+    <LinearLayout
+        android:layout_height="80dp"
+        android:layout_width="match_parent"
+        >
+        <!--left-->
+        <RelativeLayout
+            android:layout_height="match_parent"
+            android:layout_width="0dp"
+            android:layout_weight="1"
+            >
+
+            <EditText
+                android:id="@+id/range_minimum_et"
+                android:layout_width="100dp"
+                android:layout_height="40dp"
+                android:layout_centerVertical="true"
+                android:layout_margin="10dp"
+                android:gravity="center"
+                android:hint="minimum"
+                android:textSize="17sp"
+                />
+
+        </RelativeLayout>
+
+        <!--mid-->
+        <RelativeLayout
+            android:layout_height="match_parent"
+            android:layout_width="0dp"
+            android:layout_weight="1"
+            >
+
+            <EditText
+                android:id="@+id/range_maximum_et"
+                android:layout_width="100dp"
+                android:layout_height="40dp"
+                android:layout_centerVertical="true"
+                android:layout_margin="10dp"
+                android:gravity="center"
+                android:hint="maximum"
+                android:textSize="17sp"
+                />
+
+
+        </RelativeLayout>
+
+        <!--right-->
+        <RelativeLayout
+            android:layout_height="match_parent"
+            android:layout_width="0dp"
+            android:layout_weight="1"
+            >
+
+            <Button
+                android:id="@+id/range_reset_btn"
+                android:layout_width="100dp"
+                android:layout_height="40dp"
+                android:layout_centerVertical="true"
+                android:layout_marginLeft="10dp"
+                android:layout_marginRight="10dp"
+                android:background="#00000000"
+                android:gravity="center"
+                android:textSize="17sp"
+                android:text="Reset"
+                android:textAllCaps="false"/>
+
+        </RelativeLayout>
+
+    </LinearLayout>
+
+
+</LinearLayout>

+ 44 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_section_header.xml

@@ -0,0 +1,44 @@
+<?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="40dp"
+                android:background="#999999">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="40dp"
+        >
+
+        <TextView
+            android:id="@+id/title_lb"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
+            android:layout_marginLeft="10dp"
+            android:layout_marginStart="10dp"
+            android:gravity="center_vertical|left"
+            android:textColor="#ffffff"
+            android:textSize="15sp"
+            android:text="Title"
+            />
+
+        <TextView
+            android:id="@+id/header_control_btn"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
+            android:layout_marginRight="10dp"
+            android:layout_marginEnd="10dp"
+            android:textColor="#0088ff"
+            android:textSize="15sp"
+            android:text="Hide"
+            />
+
+    </RelativeLayout>
+
+
+</RelativeLayout>

+ 58 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_signature_cell.xml

@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="140dp"
+                android:orientation="horizontal">
+
+
+   <LinearLayout
+       android:layout_width="match_parent"
+       android:layout_height="140dp"
+       android:orientation="horizontal"
+       >
+
+       <RelativeLayout
+           android:layout_width="0dp"
+           android:layout_weight="1"
+           android:layout_height="match_parent"
+           >
+
+           <TextView
+               android:id="@+id/signature_title_lb"
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:layout_centerVertical="true"
+               android:layout_marginLeft="5dp"
+               android:layout_marginStart="5dp"
+               android:textSize="17sp"
+               android:textColor="#000000"
+               android:text="Label"
+               android:gravity="left|center_vertical"
+
+               />
+
+           <TextView
+               android:id="@+id/start_mark"
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:layout_toEndOf="@id/signature_title_lb"
+               android:layout_toRightOf="@id/signature_title_lb"
+               android:layout_alignTop="@id/signature_title_lb"
+               android:text="*"
+               android:textColor="#000000"
+               />
+
+       </RelativeLayout>
+
+       <ImageView
+           android:id="@+id/signature_image_view"
+           android:layout_width="0dp"
+           android:layout_weight="4"
+           android:layout_height="match_parent"
+           android:gravity="center"
+           android:layout_margin="5dp"
+           />
+
+   </LinearLayout>
+
+</LinearLayout>

+ 58 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_signature_cell_small.xml

@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="170dp"
+                android:orientation="vertical">
+
+
+   <LinearLayout
+       android:layout_width="match_parent"
+       android:layout_height="170dp"
+       android:orientation="vertical"
+       >
+
+       <RelativeLayout
+           android:layout_width="match_parent"
+           android:layout_weight="1"
+           android:layout_height="0dp"
+           >
+
+           <TextView
+               android:id="@+id/signature_title_lb"
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:layout_centerVertical="true"
+               android:layout_marginLeft="5dp"
+               android:layout_marginStart="5dp"
+               android:textSize="17sp"
+               android:textColor="#000000"
+               android:text="Label"
+               android:gravity="left|center_vertical"
+
+               />
+
+           <TextView
+               android:id="@+id/start_mark"
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:layout_toEndOf="@id/signature_title_lb"
+               android:layout_toRightOf="@id/signature_title_lb"
+               android:layout_alignTop="@id/signature_title_lb"
+               android:text="*"
+               android:textColor="#000000"
+               />
+
+       </RelativeLayout>
+
+       <ImageView
+           android:id="@+id/signature_image_view"
+           android:layout_width="match_parent"
+           android:layout_weight="4"
+           android:layout_height="0dp"
+           android:gravity="center"
+           android:layout_margin="5dp"
+           />
+
+   </LinearLayout>
+
+</LinearLayout>

+ 50 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_switch_cell.xml

@@ -0,0 +1,50 @@
+<?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="44dp">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="44dp"
+        >
+
+        <TextView
+            android:id="@+id/switch_title_lb"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:layout_marginStart="5dp"
+            android:layout_marginLeft="5dp"
+            android:textSize="17sp"
+            android:textColor="#000000"
+            android:text="Label"
+            />
+        <TextView
+            android:id="@+id/start_mark"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_toEndOf="@id/switch_title_lb"
+            android:layout_toRightOf="@id/switch_title_lb"
+            android:layout_alignTop="@id/switch_title_lb"
+            android:text="*"
+            android:textColor="#000000"
+            />
+
+        <Switch
+            android:id="@+id/switch_cell_switch"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
+            android:layout_centerVertical="true"
+            android:layout_marginRight="5dp"
+            android:layout_marginEnd="5dp"
+            android:layout_marginBottom="10dp"
+            android:layout_marginTop="10dp"
+            />
+
+    </RelativeLayout>
+
+
+
+</RelativeLayout>

+ 68 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_switch_cell_small.xml

@@ -0,0 +1,68 @@
+<?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="80dp">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="80dp"
+        android:orientation="vertical"
+        >
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            >
+
+            <TextView
+                android:id="@+id/switch_title_lb"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerVertical="true"
+                android:layout_marginStart="5dp"
+                android:layout_marginLeft="5dp"
+                android:textSize="17sp"
+                android:textColor="#000000"
+                android:text="Label"
+                />
+            <TextView
+                android:id="@+id/start_mark"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toEndOf="@id/switch_title_lb"
+                android:layout_toRightOf="@id/switch_title_lb"
+                android:layout_alignTop="@id/switch_title_lb"
+                android:text="*"
+                android:textColor="#000000"
+                />
+
+
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            >
+
+            <Switch
+                android:id="@+id/switch_cell_switch"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentRight="true"
+                android:layout_alignParentEnd="true"
+                android:layout_centerVertical="true"
+                android:layout_marginRight="5dp"
+                android:layout_marginEnd="5dp"
+                android:layout_marginBottom="10dp"
+                android:layout_marginTop="10dp"
+                />
+
+        </RelativeLayout>
+
+    </LinearLayout>
+
+
+
+</RelativeLayout>

+ 59 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_text_view_cell.xml

@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="140dp"
+                android:orientation="horizontal">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="140dp"
+        android:orientation="horizontal"
+        >
+
+        <RelativeLayout
+            android:layout_width="0dp"
+            android:layout_weight="1"
+            android:layout_height="match_parent"
+            android:layout_margin="0dp"
+            >
+            <TextView
+                android:id="@+id/name_lb"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="5dp"
+                android:layout_marginStart="5dp"
+                android:textSize="17sp"
+                android:textColor="#000000"
+                android:text="Label"
+                android:gravity="start|center_vertical"
+                android:textAlignment="textStart"
+                android:layout_centerVertical="true"
+                />
+            <TextView
+                android:id="@+id/start_mark"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toEndOf="@id/name_lb"
+                android:layout_toRightOf="@id/name_lb"
+                android:layout_alignTop="@id/name_lb"
+                android:text="*"
+                android:textColor="#000000"
+                />
+
+        </RelativeLayout>
+
+        <EditText
+            android:id="@+id/text_view"
+            android:layout_width="0dp"
+            android:layout_weight="4"
+            android:layout_height="match_parent"
+            android:layout_margin="5dp"
+            android:gravity="top|left"
+            android:minLines="5"
+            android:maxLines="10"
+            android:inputType="none"
+            />
+
+    </LinearLayout>
+
+</LinearLayout>

+ 59 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/common_editor_text_view_cell_small.xml

@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="170dp"
+                android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="170dp"
+        android:orientation="vertical"
+        >
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_weight="1"
+            android:layout_height="0dp"
+            android:layout_margin="0dp"
+            >
+            <TextView
+                android:id="@+id/name_lb"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="5dp"
+                android:layout_marginStart="5dp"
+                android:textSize="17sp"
+                android:textColor="#000000"
+                android:text="Label"
+                android:gravity="start|center_vertical"
+                android:textAlignment="textStart"
+                android:layout_centerVertical="true"
+                />
+            <TextView
+                android:id="@+id/start_mark"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toEndOf="@id/name_lb"
+                android:layout_toRightOf="@id/name_lb"
+                android:layout_alignTop="@id/name_lb"
+                android:text="*"
+                android:textColor="#000000"
+                />
+
+        </RelativeLayout>
+
+        <EditText
+            android:id="@+id/text_view"
+            android:layout_width="match_parent"
+            android:layout_weight="4"
+            android:layout_height="0dp"
+            android:layout_margin="5dp"
+            android:gravity="top|left"
+            android:minLines="5"
+            android:maxLines="10"
+            android:inputType="none"
+            />
+
+    </LinearLayout>
+
+</LinearLayout>

+ 37 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/enum_select_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="40dp">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="40dp"
+        >
+
+        <TextView
+            android:id="@+id/enum_value_tv"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
+            android:layout_marginLeft="5dp"
+            android:layout_marginStart="5dp"
+            android:textColor="#000000"
+            />
+
+        <ImageView
+            android:id="@+id/enum_check_iv"
+            android:layout_width="20dp"
+            android:layout_height="20dp"
+            android:layout_alignParentEnd="true"
+            android:layout_alignParentRight="true"
+            android:layout_centerVertical="true"
+            android:layout_marginRight="5dp"
+            android:layout_marginEnd="5dp"
+            android:scaleType="fitCenter"
+            android:src="@drawable/check"/>
+
+    </RelativeLayout>
+
+</RelativeLayout>

+ 48 - 0
ApexDrivers/CommonEditorLib/src/main/res/layout/enum_select_sort_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="40dp">
+
+    <ImageView
+        android:id="@+id/drag_list_item_image"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentRight="true"
+        android:layout_centerVertical="true"
+        android:src="@drawable/ic_drag"
+        android:visibility="invisible"
+        />
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="40dp"
+        >
+
+        <TextView
+            android:id="@+id/enum_value_tv"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
+            android:layout_marginLeft="5dp"
+            android:layout_marginStart="5dp"
+            android:textColor="#000000"
+            />
+
+        <ImageView
+            android:id="@+id/enum_check_iv"
+            android:layout_width="20dp"
+            android:layout_height="20dp"
+            android:layout_alignParentEnd="true"
+            android:layout_alignParentRight="true"
+            android:layout_centerVertical="true"
+            android:layout_marginRight="5dp"
+            android:layout_marginEnd="5dp"
+            android:scaleType="fitCenter"
+            android:src="@drawable/check"/>
+
+    </RelativeLayout>
+
+
+</RelativeLayout>

+ 19 - 0
ApexDrivers/CommonEditorLib/src/test/java/com/example/commoneditorlib/ExampleUnitTest.java

@@ -0,0 +1,19 @@
+package com.example.commoneditorlib;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest
+{
+    @Test
+    public void addition_isCorrect()
+    {
+        assertEquals(4, 2 + 2);
+    }
+}

+ 1 - 0
ApexDrivers/settings.gradle

@@ -1,3 +1,4 @@
+include ':CommonEditorLib'
 include ':ratradefiling'
 include ':ratradefiling'
 include ':rapdflib'
 include ':rapdflib'
 include ':RALocationLib'
 include ':RALocationLib'