如何用数据驱动实现通用化巡检APP(如何一个界面里添加多个点击拍照按钮并显示在不同的imageview里)

最近启动了一个新项目叫通用化,老师的设想是这样的:APP里显示的内容和布局都是不确定的,需要从后台传过来的json串中解析出来,然后经过一系列的循环和判断语句,为APP添加上json中要求的布局和内容,就连文字的大小和颜色也都是从后台获取的。
刚开始的时候觉得这样很难实现,但是可能也是可以实现的,不过今天下午遇到了一个世纪大难题,我和实验室另两个同学讨论了半天也没有解决。如果哪天解决了,我就去吃一顿好的,所以先记录一下~

JSON串

先来看看我们要用来确定内容和布局的json,我发誓是我读研以来设计过或者见过的最长的json。大体说分为三层,task,event,work,app要把这三层内容显示出来,而且每个数组里元素的个数都是不确定的,每次从后台获取的都是类似结构但是不同内容的json

{
    "task_ID": "123",
    "font_size": 25,
    "font_color": "#080808",
    "note": [{
        "note_name": "任务开始时间",
        "note_content": "2018-6-6 12:00:00",
        "font_color": "#080808",
        "font_size": "20"
    }, {
        "note_name": "任务结束时间",
        "note_content": "2018-6-6 18:00:00",
        "font_color": "#080808",
        "font_size": "20"
    }, {
        "note_name": "安装人员",
        "note_content": "张三",
        "font_color": "#080808",
        "font_size": "20"
    }, {
        "note_name": "任务性质",
        "note_content": "普通",
        "font_color": "#080808",
        "font_size": "20"
    }, {
        "note_name": "必备工具",
        "note_content": "螺丝刀、钳子",
        "font_color": "#080808",
        "font_size": "20"
    }],
    "event": [{
        "event_ID": "A1",
        "event_name": "除氧器",
        "font_color": "#6699FF",
        "font_size": "20",
        "work": [{
            "work_ID": "B1",
            "work_name": "温度",
            "font_color": "#6699FF",
            "font_size": "20",
            "work_note": [{
                "note_name": "正常范围",
                "note_content": "10-15",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "异常标准",
                "note_content": "过大或过小",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "特殊提示",
                "note_content": "避免烫伤",
                "font_color": "#6699FF",
                "font_size": "20"
            }],
            "view": [{
                "view_class": "拍照",
                "view_name": "温度拍照",
                "font_size": 20,
                "font_color": "#080808"
            }, {
                "view_class": "输入框",
                "view_name": "输入温度",
                "font_size": 20,
                "font_color": "#080808"
            }]
        }, {
            "work_ID": "B2",
            "work_name": "仪表参数",
            "font_color": "#6699FF",
            "font_size": "20",
            "work_note": [{
                "note_name": "正常范围",
                "note_content": "10-15",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "异常标准",
                "note_content": "过大或过小",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "特殊提示",
                "note_content": "避免烫伤",
                "font_color": "#6699FF",
                "font_size": "20"
            }],
            "view": [{
                "view_class": "拍照",
                "view_name": "仪表拍照",
                "font_size": 20,
                "font_color": "#080808"
            }, {
                "view_class": "输入框",
                "view_name": "输入仪表数字",
                "font_size": 20,
                "font_color": "#080808"
            }]
        }]
    }, {
        "event_ID": "A2",
        "event_name": "汽缸",
        "font_color": "#6699FF",
        "font_size": "20",
        "work": [{
            "work_ID": "B3",
            "work_name": "油温",
            "font_color": "#6699FF",
            "font_size": "20",
            "work_note": [{
                "note_name": "正常范围",
                "note_content": "10-15",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "异常标准",
                "note_content": "过大或过小",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "特殊提示",
                "note_content": "避免烫伤",
                "font_color": "#6699FF",
                "font_size": "20"
            }],
            "view": [{
                "view_class": "拍照",
                "view_name": "油温拍照",
                "font_size": 20,
                "font_color": "#080808"
            }, {
                "view_class": "输入框",
                "view_name": "输入油温",
                "font_size": 20,
                "font_color": "#080808"
            }]
        }, {
            "work_ID": "B4",
            "work_name": "电机振动",
            "font_color": "#6699FF",
            "font_size": "20",
            "work_note": [{
                "note_name": "正常范围",
                "note_content": "10-15",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "异常标准",
                "note_content": "过大或过小",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "特殊提示",
                "note_content": "避免烫伤",
                "font_color": "#6699FF",
                "font_size": "20"
            }],
            "view": [{
                "view_class": "拍照",
                "view_name": "电机拍照",
                "font_size": 20,
                "font_color": "#080808"
            }, {
                "view_class": "输入框",
                "view_name": "输入电机参数",
                "font_size": 20,
                "font_color": "#080808"
            }]
        }]
    }, {
        "event_ID": "A3",
        "event_name": "循环泵房",
        "font_color": "#6699FF",
        "font_size": "20",
        "work": [{
            "work_ID": "B5",
            "work_name": "温度",
            "font_color": "#6699FF",
            "font_size": "20",
            "work_note": [{
                "note_name": "正常范围",
                "note_content": "10-15",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "异常标准",
                "note_content": "过大或过小",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "特殊提示",
                "note_content": "避免烫伤",
                "font_color": "#6699FF",
                "font_size": "20"
            }],
            "view": [{
                "view_class": "拍照",
                "view_name": "温度拍照",
                "font_size": 20,
                "font_color": "#080808"
            }, {
                "view_class": "输入框",
                "view_name": "输入温度",
                "font_size": 20,
                "font_color": "#080808"
            }]
        }, {
            "work_ID": "B6",
            "work_name": "仪表参数",
            "font_color": "#6699FF",
            "font_size": "20",
            "work_note": [{
                "note_name": "正常范围",
                "note_content": "10-15",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "异常标准",
                "note_content": "过大或过小",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "特殊提示",
                "note_content": "避免烫伤",
                "font_color": "#6699FF",
                "font_size": "20"
            }],
            "view": [{
                "view_class": "拍照",
                "view_name": "仪表拍照",
                "font_size": 20,
                "font_color": "#080808"
            }, {
                "view_class": "输入框",
                "view_name": "输入仪表数字",
                "font_size": 20,
                "font_color": "#080808"
            }]
        }]
    }, {
        "event_ID": "A4",
        "event_name": "给水泵",
        "font_color": "#6699FF",
        "font_size": "20",
        "work": [{
            "work_ID": "B7",
            "work_name": "温度",
            "font_color": "#6699FF",
            "font_size": "20",
            "work_note": [{
                "note_name": "正常范围",
                "note_content": "10-15",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "异常标准",
                "note_content": "过大或过小",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "特殊提示",
                "note_content": "避免烫伤",
                "font_color": "#6699FF",
                "font_size": "20"
            }],
            "view": [{
                "view_class": "拍照",
                "view_name": "温度拍照",
                "font_size": 20,
                "font_color": "#080808"
            }, {
                "view_class": "输入框",
                "view_name": "输入温度",
                "font_size": 20,
                "font_color": "#080808"
            }]
        }, {
            "work_ID": "B8",
            "work_name": "仪表参数",
            "font_color": "#6699FF",
            "font_size": "20",
            "work_note": [{
                "note_name": "正常范围",
                "note_content": "10-15",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "异常标准",
                "note_content": "过大或过小",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "特殊提示",
                "note_content": "避免烫伤",
                "font_color": "#6699FF",
                "font_size": "20"
            }],
            "view": [{
                "view_class": "拍照",
                "view_name": "仪表拍照",
                "font_size": 20,
                "font_color": "#080808"
            }, {
                "view_class": "输入框",
                "view_name": "输入仪表数字",
                "font_size": 20,
                "font_color": "#080808"
            }]
        }]
    }, {
        "event_ID": "A5",
        "event_name": "疏水泵",
        "font_color": "#6699FF",
        "font_size": "20",
        "work": [{
            "work_ID": "B9",
            "work_name": "温度",
            "font_color": "#6699FF",
            "font_size": "20",
            "work_note": [{
                "note_name": "正常范围",
                "note_content": "10-15",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "异常标准",
                "note_content": "过大或过小",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "特殊提示",
                "note_content": "避免烫伤",
                "font_color": "#6699FF",
                "font_size": "20"
            }],
            "view": [{
                "view_class": "拍照",
                "view_name": "温度拍照",
                "font_size": 20,
                "font_color": "#080808"
            }, {
                "view_class": "输入框",
                "view_name": "输入温度",
                "font_size": 20,
                "font_color": "#080808"
            }]
        }, {
            "work_ID": "B10",
            "work_name": "仪表参数",
            "font_color": "#6699FF",
            "font_size": "20",
            "work_note": [{
                "note_name": "正常范围",
                "note_content": "10-15",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "异常标准",
                "note_content": "过大或过小",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "特殊提示",
                "note_content": "避免烫伤",
                "font_color": "#6699FF",
                "font_size": "20"
            }],
            "view": [{
                "view_class": "拍照",
                "view_name": "仪表拍照",
                "font_size": 20,
                "font_color": "#080808"
            }, {
                "view_class": "输入框",
                "view_name": "输入仪表数字",
                "font_size": 20,
                "font_color": "#080808"
            }]
        }]
    }, {
        "event_ID": "A6",
        "event_name": "射水泵",
        "font_color": "#6699FF",
        "font_size": "20",
        "work": [{
            "work_ID": "B11",
            "work_name": "温度",
            "font_color": "#6699FF",
            "font_size": "20",
            "work_note": [{
                "note_name": "正常范围",
                "note_content": "10-15",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "异常标准",
                "note_content": "过大或过小",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "特殊提示",
                "note_content": "避免烫伤",
                "font_color": "#6699FF",
                "font_size": "20"
            }],
            "view": [{
                "view_class": "拍照",
                "view_name": "温度拍照",
                "font_size": 20,
                "font_color": "#080808"
            }, {
                "view_class": "输入框",
                "view_name": "输入温度",
                "font_size": 20,
                "font_color": "#080808"
            }]
        }, {
            "work_ID": "B12",
            "work_name": "仪表参数",
            "font_color": "#6699FF",
            "font_size": "20",
            "work_note": [{
                "note_name": "正常范围",
                "note_content": "10-15",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "异常标准",
                "note_content": "过大或过小",
                "font_color": "#6699FF",
                "font_size": "20"
            }, {
                "note_name": "特殊提示",
                "note_content": "避免烫伤",
                "font_color": "#6699FF",
                "font_size": "20"
            }],
            "view": [{
                "view_class": "拍照",
                "view_name": "仪表拍照",
                "font_size": 20,
                "font_color": "#080808"
            }, {
                "view_class": "输入框",
                "view_name": "输入仪表数字",
                "font_size": 20,
                "font_color": "#080808"
            }]
        }]
    }, ]
}

json解析

首先程序中要把json每一层的内容都解析出来,然后显示在相应的位置上。再根据view数组来确定当前页面的布局

JSONArray event_array = test.getJSONArray("event");
      for (int i = 0; i < event_array.length(); i++) {
        JSONObject event = event_array.getJSONObject(i);
        if (event.getString("event_ID").toString().equals(event_ID)) {
                    JSONArray work_array = event.getJSONArray("work");
                    for (int j = 0; j < work_array.length(); j++) {
                        JSONObject work = work_array.getJSONObject(j);
                        String work_ID = work.getString("work_ID");
                        String work_name = work.getString("work_name");
                        addtext(work_ID+work_name, work.getString("font_color"), work.getInt("font_size"));
                        JSONArray work_note_array = work.getJSONArray("work_note");
                    for (int k = 0; k < work_note_array.length(); k++) {
                JSONObject work_note = work_note_array.getJSONObject(k);
                String note_name = work_note.getString("note_name");
            String note_content = work_note.getString("note_content");
                            addtext(note_name + ":" + note_content,
                                    work_note.getString("font_color"), work_note.getInt("font_size"));

                        }
                        JSONArray view_array = work.getJSONArray("view");
                        for (int k = 0; k < view_array.length(); k++) {
                            JSONObject view = view_array.getJSONObject(k);
                            String view_name = view.getString("view_name");
                            String view_class = view.getString("view_class");
                            addtext(view_name, view.getString("font_color"), view.getInt("font_size"));
                            if (view_class.equals("拍照")) {
                                btn_capture = addview_capture();
                                btn_capture.setOnClickListener(new OnClickListener() {          
                                    @Override
                                    public void onClick(View v) {
                                        // TODO Auto-generated method stub
                                        Log.v("capture", "-1");
                                        new AlertDialog.Builder(ExecuteActivity.this)
                                        .setTitle("添加图片")
                                        .setItems(addPhoto, new DialogInterface.OnClickListener() {
                                            @Override
                                            public void onClick(DialogInterface dialog, int which) {
                                                // TODO Auto-generated method stub
                                                if (which == 0) {
                                                    String haveSD = Environment.getExternalStorageState();                      
                                                    String filename = "$1.jpg";
                                                    cameraFile = new File(Environment.getExternalStorageDirectory()+"/"+filename);
                                                    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                                                    intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cameraFile));
                                                    startActivityForResult(intent, 0);

                                                        }
                                                        if (which == 1) {
//                                           
                                                            Intent intent = new Intent();
                                                            intent.setType("image/*");//可选择图片视频
                                                            //修改为以下两句代码
                                                            intent.setAction(Intent.ACTION_PICK);
                                                            intent.setData(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);//使用以上这种模式,并添加以上两句
                                                            startActivityForResult(intent, 1);
                                                            Log.v("capture", "0");
                                                        }
                                                    }                                 
                                                })
                                        .show();
                                    }
                                    });
                            }else if (view_class.equals("输入框")) {
                                addview_et2();
                            }
                        }
                    }
                }
            }

for循环里根据view_class来确定接下来要添加的布局,也就是说调用下面的某一个函数。

//添加文本
    private void addtext(String content,String color,int size){
        TextView tView = new TextView(this);
        tView.setText(content);
        tView.setTextColor(Color.parseColor(color));
        tView.setTextSize(size);
        l.addView(tView);
    }
    //添加文字输入框布局
    private void addview_et2(){

        final TextView tv_numleft = new TextView(this);     
        EditText et = new EditText(this); 
        l.addView(et);
        et.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                number_left = "剩余字数:"+ (maxNum-s.length());
                tv_numleft.setText(number_left);
                Log.v("YBYZZZZZZZZZZZZZZZ", number_left);
                if((maxNum-s.length()<0)){
                    tv_numleft.setTextColor(ExecuteActivity.this.getResources().getColor(R.color.red));
                }else {
                    tv_numleft.setTextColor(ExecuteActivity.this.getResources().getColor(R.color.black));
                }
            }
        });   
    }
    //添加拍照布局
    private ImageButton addview_capture(){
        final ImageButton btn_capture = new ImageButton(this);
        btn_capture.setBackgroundResource(R.drawable.capture);
        //设置图片大小
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(120,  
                120);  
        btn_capture.setLayoutParams(params); 
        l.addView(btn_capture);

        return btn_capture;

    }

但是这就产生了终极难题!
每次添加的拍照布局中的imagebutton没法动态命名,导致想要显示拍好的照片时,onactivityResult函数里找不到对应的imagebutton。师妹说可能只能通过重写安卓底层的类,修改onactivityResult函数的参数来解决了~

恩,没过几天这个所谓终极难题就解决啦!
方法就是最外层定义一个imagebutton的数组,再定义一个int类型的变量count,每次imagebutton的点击事件里都把count的值更改成当前imagebutton在数组中的位置,然后在onactivityresult里面获取到这个count,就可以把拍好的图片显示在当前点击的imagebutton里了!看下代码

//添加拍照布局
    private ImageView addview_capture(){
        final ImageView btn_capture = new ImageButton(this);
        btn_capture.setImageResource(R.drawable.capture);
        btn_capture.setBackgroundColor(Color.parseColor("#FFFFFF"));
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(400,  
                400);  
        btn_capture.setLayoutParams(params); 
        //添加时settag当前的count值
        **btn_capture.setTag(count);**
        Button button = new Button(this);   
        LinearLayout.LayoutParams params2 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); 
        params2.gravity = Gravity.RIGHT;
        button.setLayoutParams(params2); 
        button.setText("提交");
        l.addView(btn_capture);
        l.addView(button);

        return btn_capture;

    }

调用这个函数后count加1;并在点击事件里传入tag值

if (view_class.equals("拍照")) {  
                                btn_capture[count] = addview_capture();
                                btn_capture[count].setOnClickListener(new OnClickListener() {
                                    @Override
                                    public void onClick(View v) {

                                        count = (Integer)v.getTag();
                                        new AlertDialog.Builder(ExecuteActivity.this)
                                        .setTitle("添加图片")
                                        .setItems(addPhoto, new DialogInterface.OnClickListener() {
                                            @Override
                                            public void onClick(DialogInterface dialog, int which) {
                                                // TODO Auto-generated method stub
                                                if (which == 0) {
                                                    String haveSD = Environment.getExternalStorageState();                      
                                                    String filename = "$1.jpg";
                                                    cameraFile = new File(Environment.getExternalStorageDirectory()+"/"+filename);
                                                    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                                                    intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cameraFile));
                                                    startActivityForResult(intent, 0);

                                                    }
                                               if (which == 1) {
//                                           
                                                    Intent intent = new Intent();
                                                    intent.setType("image/*");//可选择图片视频
                                                            //修改为以下两句代码
                                                    intent.setAction(Intent.ACTION_PICK);
                                                    intent.setData(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);//使用以上这种模式,并添加以上两句
                                                    startActivityForResult(intent, 1);
//                                                  Log.v("capture", "0");
                                                        }
                                                    }                                 
                                                })
                                        .show();
                                    }
                                    });
                                count = count+1;

onactivityresult函数里的count值已经变成当前imagebutton在数组中的顺位了!

@SuppressLint("ShowToast") protected void onActivityResult(int requestCode, int resultCode, Intent data) {      
        switch (requestCode) {
        case 1: 

        if (resultCode == Activity.RESULT_OK) {
            /**
             * 当选择的图片不为空的话,在获取到图片的途径
             */

            Uri uri = data.getData();
            try {
                String[] pojo = { MediaStore.Images.Media.DATA };

                Cursor cursor = getContentResolver().query(uri, pojo, null, null, null);
                if (cursor != null) {

                    ContentResolver cr = this.getContentResolver();
                    int colunm_index = cursor
                            .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                    cursor.moveToFirst();
                    String path = cursor.getString(colunm_index);
                    /***
                     * 这里加这样一个判断主要是为了第三方的软件选择,比如:使用第三方的文件管理器的话,你选择的文件就不一定是图片了,
                     * 这样的话,我们判断文件的后缀名 如果是图片格式的话,那么才可以
                     */             
                        String picPath = path;
                        Toast.makeText(ExecuteActivity.this, picPath, 1000).show();
                        Bitmap bitmap = BitmapFactory.decodeStream(cr
                                .openInputStream(uri));
                        Log.v("capture","1");
                        btn_capture[count].setImageBitmap(bitmap);
                        Log.v("capture", bitmap.toString());
                        btn_capture[count].setScaleType(ImageView.ScaleType.FIT_CENTER);
//                      btn_capture[y].getBackground().setAlpha(0);
                } else {
                }

            } catch (Exception e) {
            }
        }       
            break;
        case 0:
            if (resultCode == RESULT_OK) {
                Toast.makeText(ExecuteActivity.this, "要成功了哦!", 1000).show();
                try {
                    FileInputStream fis = new FileInputStream(ExecuteActivity.cameraFile);
                    bitmap = BitmapFactory.decodeStream(fis);
                    fis.close();
                    } catch (Exception e) { 
                    e.printStackTrace(); 
                    }
                    if (bitmap!=null) {
                    Log.e(getClass().getName(), (bitmap.getWidth()+","+bitmap.getHeight()));
                    }

            }
            }

        super.onActivityResult(requestCode, resultCode, data);

}

猜你喜欢

转载自blog.csdn.net/ulike_MFY/article/details/79100015
今日推荐