动态拼接android_android 多个音频拼接怎么让其两两拼接 - CSDN
精华内容
参与话题
  • android动态拼接生成界面 ,大量界面

    千次阅读 2019-07-29 14:52:16
    不知道各位小伙伴在开发应用客户端的时候有没有碰到过这样的需求,就是需要在app端维护大量的表数据。 一般的应用可能需要客户端上传数据的时候 就几张表或者几个功能,但是大量的表格就很复杂。...

    不知道各位小伙伴在开发应用客户端的时候有没有碰到过这样的需求,就是需要在app端维护大量的表数据。

    一般的应用可能需要客户端上传数据的时候 就几张表或者几个功能,但是大量的表格就很复杂。

    举列:我们碰到的需求是 维护表格数据 ,这些表格都是政府部门的一些表格文件,而且非常多,一个轨道系统有将近400张表格。对  是400多张,而且没有任何规律,字段什么的都不一样,在之前有个房建系统做了大概几十张,之前的小伙伴是写了几十个activity... 但是这次400张怎么处理?

    如图下面的表格:

     

     

     

    类似上面的表格,400多个,都要可以实现在app端填写,然后上传到服务器。

     

    app端最后实现效果(手机比较小,截图搞了很多张,gif做出来都太大,传不上来,大概意思能看)

     

     

     

    界面不美观,凑合看吧...说重点..

     

    实现的整体思路:

     

    1.处理 400张表的数据 

     

    将400张表的字段存到一张表里面,整理这400张表的数据是个比较大的工作,我们有个做delphi的工程师专门做了一个配置工具,打开每张表配置这张表格的字段。

    数据库主要包括4张表格:T_Table  存储所有表格数据  T_TableDetail 存储所有表的字段数据 T_Type 字典表  存储所有控件类型  T_DIC存储所有表下拉数据

    T_Table  字段包括:id  name  order parentID(因为我们这个表显示有层级结构)  

    T_TableDetail字段主要包括 :字段id   字段名称  字段顺序   表格id(属于哪张表)    类型id(这个字段要用什么控件显示)  isRequired 是否必填 defaultValue默认值 

    row   col  行列   dicid关联字典表数据

    核心的就这些   这个根据自己的具体业务再搭建自己的数据库表结构。
     

    2.搭建界面

    有了基础数据后,我们要做的就是写一个通用Activity去动态拼装整个界面 

    我实现的思路是这样的 :将每种类型的控件都单独写成xml,比如有15种类型的控件就写15个xml,根据字段类型判断加载哪种类型的xml。

    判断加载完界面  处理界面控件设置默认值,设置点击事件,设置是否可以编辑点击等(因为查看  修改  添加都用一套界面),这一些基本逻辑。

     

    我就直接将初始化布局的地方贴出来,大家看一下。

     

    public class ViewTypeUtil {
    	
    	//表格名称类型 输入框  默认带值 且要单独获取值
        public static final int item_view_type_zero = 0;
        //单行输入框
        public static final int item_view_type_one = 1;
        //多行输入框
        public static final int item_view_type_two = 2;
        //短日期 如2012-01-12
        public static final int item_view_type_three = 3;
        //数值
        public static final int item_view_type_four = 4;
        //下拉框
        public static final int item_view_type_five = 5;
        //分部分项
        public static final int item_view_type_six = 6;
        //部位栏
        public static final int item_view_type_seven = 7;
        //单选框
        public static final int item_view_type_eight = 8;
        //多选框
        public static final int item_view_type_nine= 9;
        //列表
        public static final int item_view_type_ten = 10;
        //图纸标准
        public static final int item_view_type_eleven = 11;
        //图片
        public static final int item_view_type_twelve = 12;
        //组
        public static final int item_view_type_thirteen = 13;
        //长日期 2017-07-02 10:38:41
        public static final int item_view_type_fourteen  = 14;
        //时间格式 如 10:25:14
        public static final int item_view_type_fifteen  = 15;
        //标签
        public static final int item_view_type_sixteen  = 16;
        
    
    }
    

     

     

     

     

     

     

    	public void initView(final LinearLayout linearLayout, List<FormDetail> formDetailList) {
    		for (int i = 0; i < formDetailList.size(); i++) {
    			final FormDetail formDetail = formDetailList.get(i);
    			final int mType = formDetail.getTypeId();
    			if (mType == ViewTypeUtil.item_view_type_zero) {
    				mTypeZeroView = LayoutInflater.from(this).inflate(R.layout.item_type_zero, null);
    				mItemZeroFieldTv = (TextView) mTypeZeroView.findViewById(R.id.item_zero_field_tv);
    				mItemZeroValueEt = (EditText) mTypeZeroView.findViewById(R.id.item_zero_value_et);
    				if (mIntentFrom == FLAG_SHOW) {
    					mItemZeroValueEt.setEnabled(false);
    				}
    				mItemZeroValueEt.setText(formDetail.getuValue());
    				mItemZeroValueEt.setTag(formDetail.getTableDetailID());
    				mItemZeroFieldTv.setText(formDetail.getCaption());
    				mTypeZeroView.setTag(mType);
    				linearLayout.addView(mTypeZeroView);
    
    			} else if (mType == ViewTypeUtil.item_view_type_one) {
    				mTypeOneView = LayoutInflater.from(this).inflate(R.layout.item_type_one, null);
    				mItemOneFieldTv = (TextView) mTypeOneView.findViewById(R.id.item_one_field_tv);
    				mItemOneValueEt = (EditText) mTypeOneView.findViewById(R.id.item_one_value_et);
    				if (mIntentFrom == FLAG_SHOW) {
    					mItemOneValueEt.setEnabled(false);
    				}
    				mItemOneValueEt.setText(formDetail.getuValue());
    				mItemOneValueEt.setTag(formDetail.getTableDetailID());
    				mItemOneFieldTv.setText(formDetail.getCaption());
    				mTypeOneView.setTag(mType);
    				linearLayout.addView(mTypeOneView);
    			} else if (mType == ViewTypeUtil.item_view_type_two) {
    				mTypeTwoView = LayoutInflater.from(this).inflate(R.layout.item_type_two, null);
    				mItemTwoValueEt = (EditText) mTypeTwoView.findViewById(R.id.content_et);
    				mItemTwoValueEt.setTypeface(Constants.fontFace);
    				mItemTwoFieldTv = (TextView) mTypeTwoView.findViewById(R.id.item_two_field_tv);
    				if (mIntentFrom == FLAG_SHOW) {
    					mItemTwoValueEt.setEnabled(false);
    				} else {
    					mTypeTwoView.findViewById(R.id.content_iv).setOnClickListener(this);
    					mTypeTwoView.findViewById(R.id.voice_iv).setOnClickListener(this);
    					mTypeTwoView.findViewById(R.id.special_iv).setOnClickListener(this);
    				}
    				mItemTwoValueEt.setText(formDetail.getuValue());
    				mItemTwoFieldTv.setText(formDetail.getCaption());
    				mItemTwoValueEt.setTag(formDetail.getTableDetailID());
    				mTypeTwoView.findViewById(R.id.voice_iv).setTag(formDetail.getTableDetailID());
    				mTypeTwoView.findViewById(R.id.special_iv).setTag(formDetail.getTableDetailID());
    				mTypeTwoView.findViewById(R.id.content_iv).setTag(formDetail.getTableDetailID());
    
    				mTypeTwoView.setTag(mType);
    				linearLayout.addView(mTypeTwoView);
    			} else if (mType == ViewTypeUtil.item_view_type_three) {
    				mTypeThreeView = LayoutInflater.from(this).inflate(R.layout.item_type_three, null);
    				mDateKeyTv = (TextView) mTypeThreeView.findViewById(R.id.tv_test_date_key);
    				mDateValueEt = (EditText) mTypeThreeView.findViewById(R.id.et_test_date_value);
    				mDateKeyTv.setText(formDetail.getCaption());
    				if (mIntentFrom == FLAG_SHOW) {
    					mDateValueEt.setEnabled(false);
    				} else {
    					mDateValueEt.setOnClickListener(this);
    				}
    				if (!TextUtils.isEmpty(formDetail.getuValue())) {
    					mDateValueEt.setText(formDetail.getuValue());
    				} else {
    					mDateValueEt.setText(TimeUtil.getCurDateStr().substring(0, 12));
    				}
    				mDateValueEt.setTag(formDetail.getTableDetailID());
    
    				mTypeThreeView.setTag(mType);
    				linearLayout.addView(mTypeThreeView);
    			} else if (mType == ViewTypeUtil.item_view_type_four) {
    				mTypeFourView = LayoutInflater.from(context).inflate(R.layout.item_type_four, null);
    				mNumEt = (EditText) mTypeFourView.findViewById(R.id.et_num);
    				mItemFourFieldTv = (TextView) mTypeFourView.findViewById(R.id.item_four_field_tv);
    				mNumEt.setText(formDetail.getuValue());
    				mNumEt.setTag(formDetail.getTableDetailID());
    				mItemFourFieldTv.setText(formDetail.getCaption());
    				if (mIntentFrom == FLAG_SHOW) {
    					mNumEt.setEnabled(false);
    				}
    				mTypeFourView.setTag(mType);
    				linearLayout.addView(mTypeFourView);
    			} else if (mType == ViewTypeUtil.item_view_type_five) {
    				mTypeFiveView = LayoutInflater.from(this).inflate(R.layout.item_type_five, null);
    				mSelectKeyTv = (TextView) mTypeFiveView.findViewById(R.id.et_select_key);
    				mSelectValueEt = (EditText) mTypeFiveView.findViewById(R.id.et_select_value);
    				mSelectValueEt.setText(formDetail.getuValue());
    				if (mIntentFrom == FLAG_SHOW) {
    					mSelectValueEt.setEnabled(false);
    				} else {
    					mSelectValueEt.setOnClickListener(this);
    				}
    				mSelectKeyTv.setText(formDetail.getCaption());
    				mSelectValueEt.setTag(R.id.select_view_position, i);
    				mSelectValueEt.setTag(R.id.select_view_detial_id, formDetail.getTableDetailID());
    				mTypeFiveView.setTag(mType);
    				linearLayout.addView(mTypeFiveView);
    			} else if (mType == ViewTypeUtil.item_view_type_six) {
    
    			} else if (mType == ViewTypeUtil.item_view_type_seven) {// 部位栏
    				mTypeSevenView = LayoutInflater.from(this).inflate(R.layout.item_type_seven, null);
    				mPartSelectKeyTv = (TextView) mTypeSevenView.findViewById(R.id.tv_select_part_key);
    				mPartSelectValueEt = (EditText) mTypeSevenView.findViewById(R.id.et_select_part_value);
    				mPartSelectKeyTv.setText(formDetail.getCaption());
    				mPartSelectValueEt.setText(formDetail.getuValue());
    				if (mIntentFrom == FLAG_SHOW) {
    					mPartSelectValueEt.setEnabled(false);
    				} else {
    					mPartSelectValueEt.setOnClickListener(this);
    				}
    				mPartSelectValueEt.setTag(formDetail.getTableDetailID());
    				mTypeSevenView.setTag(mType);
    				linearLayout.addView(mTypeSevenView);
    
    			} else if (mType == ViewTypeUtil.item_view_type_eight) {// 单选框
    				mTypeEightView = LayoutInflater.from(this).inflate(R.layout.item_type_eight, null);
    				mTypeEightKeyTv = (TextView) mTypeEightView.findViewById(R.id.tv_type_eight_key);
    				rgTypeEight = (RadioGroup) mTypeEightView.findViewById(R.id.rb_type_eight);
    				mTypeEightKeyTv.setText(formDetail.getCaption());
    
    				List<DicBean> dicBeans = formDetail.getDicBeanList();
    				if (dicBeans == null) {
    					return;
    				}
    				for (int j = 0; j < dicBeans.size(); j++) {
    					RadioButton radioButton = new RadioButton(context);
    					LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    					radioButton.setText(dicBeans.get(j).getDicName());
    					radioButton.setTag(formDetail.getTableDetailID() + "," + dicBeans.get(j).getDicID());
    					radioButton.setId(j);
    					rgTypeEight.addView(radioButton, params);
    					if (mIntentFrom == FLAG_SHOW) {// 查看
    						radioButton.setEnabled(false);
    						if ((dicBeans.get(j).getDicID() + "").equals(formDetail.getuValue())) {
    							rgTypeEight.check(j);
    						}
    					} else if (mIntentFrom == FLAG_UPDATE) {// 修改
    						radioButton.setEnabled(true);
    						if ((dicBeans.get(j).getDicID() + "").equals(formDetail.getuValue())) {
    							rgTypeEight.check(j);
    						}
    					} else {// 添加
    						rgTypeEight.check(0);
    						radioButton.setEnabled(true);
    					}
    				}
    				mTypeEightView.setTag(mType);
    				linearLayout.addView(mTypeEightView);
    			} else if (mType == ViewTypeUtil.item_view_type_nine) {// 多选框
    				mTypeNineView = LayoutInflater.from(this).inflate(R.layout.item_type_nine, null);
    				mTypeNineKeyTv = (TextView) mTypeNineView.findViewById(R.id.tv_type_nine_key);// 没有用到
    				cbxTypeNine = (CheckBox) mTypeNineView.findViewById(R.id.cbx_type_nine);
    				cbxTypeNine.setText(formDetail.getCaption());
    				cbxTypeNine.setTag(formDetail.getTableDetailID() + "," + formDetail.getDicID());
    				cbxTypeNine.setOnClickListener(this);
    				mTypeNineView.setTag(mType);
    				linearLayout.addView(mTypeNineView);
    			} else if (mType == ViewTypeUtil.item_view_type_ten) {// 列表
    				final String detailId = formDetail.getTableDetailID();
    				mTypeTenView = LayoutInflater.from(context).inflate(R.layout.item_type_ten, null);
    				mTypeTenKeyTv = (TextView) mTypeTenView.findViewById(R.id.tv_type_ten_key);
    				mTypeTenKeyTv.setText(formDetail.getCaption());
    				mTypeTenLinearLayout = (LinearLayout) mTypeTenView.findViewById(R.id.ly_type_ten);
    				mTypeTenLinearLayout.setTag(formDetail.getTableDetailID());
    				mTypeTenView.setTag(mType);
    				linearLayout.addView(mTypeTenView);
    				new AsyncTask<Void, Void, Void>() {
    					@Override
    					protected Void doInBackground(Void... params) {
    						if (mIntentFrom == FLAG_SHOW || mIntentFrom == FLAG_UPDATE) {// 查看,修改
    							mFormDetailMap = GdjtUserDataDBOperation.getInstance().getChildListDetailValueData(mUTableID, formDetail.getTableDetailID());
    						} else {// 添加
    							mFormDetailChildList = GdjtFormDBOperation.getInstance().getChildListDetailData(formDetail.getTableDetailID());
    						}
    						return null;
    					}
    
    					@Override
    					protected void onPostExecute(Void result) {
    						if (mIntentFrom == FLAG_SHOW || mIntentFrom == FLAG_UPDATE) {
    							mTypeTenView.findViewById(R.id.iv_type_ten_add).setVisibility(View.GONE);
    							mTypeTenLinearLayout.setWeightSum(3.0f);
    							ShowChildView();
    						} else {
    							AddListChildView();
    							mTypeTenLinearLayout.setWeightSum(2.5f);
    							mTypeTenView.findViewById(R.id.iv_type_ten_add).setVisibility(View.VISIBLE);
    							mTypeTenView.findViewById(R.id.iv_type_ten_add).setOnClickListener(CommonFormViewActivity.this);
    						}
    					}
    				}.execute();
    
    			} else if (mType == ViewTypeUtil.item_view_type_eleven) {// 图纸标准
    				mTypeElevenView = LayoutInflater.from(this).inflate(R.layout.item_type_eleven, null);
    				mTypeElevenKeyTv = (TextView) mTypeElevenView.findViewById(R.id.tv_type_eleven_key);
    				mDrawingNameTv = (TextView) mTypeElevenView.findViewById(R.id.item_eleven_value_et);
    				mDrawingNameTv.setOnClickListener(this);
    				mDrawingNameTv.setTag(formDetail.getTableDetailID());
    				if (!TextUtils.isEmpty(mDrawingPath)) {
    					mDrawingNameTv.setText(mDrawingPath.subSequence(mDrawingPath.lastIndexOf("/") + 1, mDrawingPath.length()));
    				}
    				mTypeElevenView.findViewById(R.id.item_eleven_value_img_photo).setOnClickListener(this);
    				mTypeElevenView.findViewById(R.id.item_eleven_value_img_folder).setOnClickListener(this);
    				mTypeElevenKeyTv.setText(formDetail.getCaption());
    				mTypeElevenView.setTag(mType);
    				linearLayout.addView(mTypeElevenView);
    			} else if (mType == ViewTypeUtil.item_view_type_twelve) {// 图片
    				mTypeTwelveView = LayoutInflater.from(this).inflate(R.layout.item_type_twelve, null);
    				mTypeTwelveKeyTv = (TextView) mTypeTwelveView.findViewById(R.id.tv_type_twelve_key);
    				mTypeTwelveValueTv = (TextView) mTypeTwelveView.findViewById(R.id.item_twelve_value_path);
    				mTypeTwelveTakePhoto = mTypeTwelveView.findViewById(R.id.item_twelve_value_img_photo);
    				mTypeTwelveSelectPhoto = mTypeTwelveView.findViewById(R.id.item_twelve_value_img_folder);
    				if (mIntentFrom == FLAG_SHOW) {
    					mTypeTwelveTakePhoto.setEnabled(false);
    					mTypeTwelveSelectPhoto.setEnabled(false);
    				} else {
    					mTypeTwelveTakePhoto.setOnClickListener(this);
    					mTypeTwelveSelectPhoto.setOnClickListener(this);
    				}
    				mTypeTwelveValueTv.setOnClickListener(this);
    				mPhotoPath = formDetail.getuValue();
    				mTypeTwelveKeyTv.setText(formDetail.getCaption());
    				mTypeTwelveValueTv.setText(mPhotoPath.substring(mPhotoPath.lastIndexOf("/") + 1));
    				mTypeTwelveValueTv.setTag(formDetail.getTableDetailID());
    				mTypeTwelveTakePhoto.setTag(formDetail.getTableDetailID());
    				mTypeTwelveSelectPhoto.setTag(formDetail.getTableDetailID());
    				mTypeTwelveView.setTag(mType);
    				linearLayout.addView(mTypeTwelveView);
    			} else if (mType == ViewTypeUtil.item_view_type_thirteen) {// 组
    				final String detailId = formDetail.getTableDetailID();
    				mTypeThirteenView = LayoutInflater.from(context).inflate(R.layout.item_type_thirteen, null);
    				mTypeThirteenKeyTv = (TextView) mTypeThirteenView.findViewById(R.id.tv_type_thirteen_key);
    				mTypeThirteenKeyTv.setText(formDetail.getCaption());
    				mTypeThirteenLinearLayout = (LinearLayout) mTypeThirteenView.findViewById(R.id.ly_type_thirteen);
    				mTypeThirteenLinearLayout.setTag(detailId);
    				mTypeThirteenView.setTag(mType);
    				linearLayout.addView(mTypeThirteenView);
    				
    				new AsyncTask<Void, Void, Void>() {
    					@Override
    					protected Void doInBackground(Void... params) {
    						if (mIntentFrom == FLAG_SHOW || mIntentFrom == FLAG_UPDATE) {// 查看,修改
    							mFormDetailMap = GdjtUserDataDBOperation.getInstance().getChildListDetailValueData(mUTableID, detailId);
    						} else {// 添加
    							mFormZuDetailChildList = GdjtFormDBOperation.getInstance().getChildListDetailData(detailId);
    						}
    						return null;
    					}
    
    					@Override
    					protected void onPostExecute(Void result) {
    						
    						if (mIntentFrom == FLAG_SHOW || mIntentFrom == FLAG_UPDATE ) {
    							ShowChildView();
    						} else {
    							AddZuChildView();
    						}
    						// linearLayout.refreshDrawableState();
    					}
    				}.execute();
    
    			} else if (mType == ViewTypeUtil.item_view_type_fourteen) {// 日期时间格式
    				mTypeFourteenView = LayoutInflater.from(this).inflate(R.layout.item_type_three, null);
    				mFourteenDateKeyTv = (TextView) mTypeFourteenView.findViewById(R.id.tv_test_date_key);
    				mFourteenDateValueEt = (EditText) mTypeFourteenView.findViewById(R.id.et_test_date_value);
    				mFourteenDateValueEt.setTag(formDetail.getTableDetailID());
    				mFourteenDateKeyTv.setText(formDetail.getCaption());
    				if (mIntentFrom == FLAG_SHOW) {
    					mFourteenDateValueEt.setEnabled(false);
    				}
    				if (!TextUtils.isEmpty(formDetail.getuValue())) {
    					mFourteenDateValueEt.setText(formDetail.getuValue());
    				} else {
    					mFourteenDateValueEt.setText(TimeUtil.getCurDateStr());
    				}
    				mFourteenDateValueEt.setTag(formDetail.getTableDetailID());
    				mFourteenDateValueEt.setOnClickListener(this);
    				mTypeFourteenView.setTag(mType);
    				linearLayout.addView(mTypeFourteenView);
    			} else if (mType == ViewTypeUtil.item_view_type_fifteen) {// 时间格式
    				mTypeFifteenView = LayoutInflater.from(this).inflate(R.layout.item_type_three, null);
    				mFifteenDateKeyTv = (TextView) mTypeFifteenView.findViewById(R.id.tv_test_date_key);
    				mFifteenDateValueEt = (EditText) mTypeFifteenView.findViewById(R.id.et_test_date_value);
    				mFifteenDateValueEt.setTag(formDetail.getTableDetailID());
    				mFifteenDateKeyTv.setText(formDetail.getCaption());
    				if (mIntentFrom == FLAG_SHOW) {
    					mFifteenDateValueEt.setEnabled(false);
    				}
    				if (!TextUtils.isEmpty(formDetail.getuValue())) {
    					mFifteenDateValueEt.setText(formDetail.getuValue());
    				} else {
    					mFifteenDateValueEt.setText(TimeUtil.getStringTimeShort());
    				}
    				mFifteenDateValueEt.setTag(formDetail.getTableDetailID());
    				mFifteenDateValueEt.setOnClickListener(this);
    				mTypeFifteenView.setTag(mType);
    				linearLayout.addView(mTypeFifteenView);
    			} else if (mType == ViewTypeUtil.item_view_type_sixteen) {// 标签
    				mTypeSixteenView = LayoutInflater.from(this).inflate(R.layout.item_type_zero, null);
    				mItemSixteenFieldTv = (TextView) mTypeSixteenView.findViewById(R.id.item_zero_field_tv);
    				mItemSixteenValueEt = (EditText) mTypeSixteenView.findViewById(R.id.item_zero_value_et);
    				mItemSixteenValueEt.setEnabled(false);
    				mItemSixteenValueEt.setText(formDetail.getuValue());
    				mItemSixteenValueEt.setTag(formDetail.getTableDetailID());
    				mItemSixteenFieldTv.setText(formDetail.getCaption());
    				mTypeSixteenView.setTag(mType);
    				linearLayout.addView(mTypeSixteenView);
    			}
    		}
    	}

     

     

    3.处理复杂控件 

    其实这个里面的复杂控件就两种,一种是列表 一种是组

    给简单大家解释一下列表是什么意思:  大家看有的表格里面是多行多列的,意味着同样的字段数据 可能要添写多条。

    那么对应在app里面   就是 这些字段放到了一起  做成了一个 组。  那么这些字段添加多条 就是 在组后面放了一个 + 号

    点击+号  这个组 就增加一组 。所以这个带+号的字段 就是 列表字段。

     

    组和 列表 处理起来相对来说非常麻烦。

     

    1).子项数据获取   

    2).布局嵌套

    3).点击事件单独处理

    4)保存数据独立拼接

     

    具体这些问题,我就不一一展开说了。大家倘若有做的,具体做的时候自然会体会到。    

     

    4.处理点击事件

    界面拼接完成后 ,要处理控件里面的点击事件。做的时候就会发现  倘若界面出现同一个item布局  ,布局里面包含点击事件 ,正常给控件设置点击事件,会发现 点击控件的时候无法区分开每个点击事件

    所以处理点击事件的时候:原理  就是先循环整体的大布局 ,找到里面的每一项小布局,然后单独处理每一项小布局里面的控件。

    这样才能保证点击事件没有问题。

    代码贴一下:

     

    @Override
    	public void onClick(View v) {
    		 if (v.getId() == R.id.content_iv) {// 范例
    
    		} else if (v.getId() == R.id.voice_iv) {// 语音
    			for (int i = 0; i < mMainView.getChildCount(); i++) {
    				int viewTag = (int) mMainView.getChildAt(i).getTag();
    				if (viewTag == ViewTypeUtil.item_view_type_two) {
    					LinearLayout l = (LinearLayout) ((LinearLayout) mMainView.getChildAt(i)).getChildAt(0);
    					EditText editText = (EditText) l.getChildAt(1);
    					if (v.getTag().equals(editText.getTag())) {
    						mVoice = new VoiceToWord(this, editText);
    						mVoice.GetWordFromVoice();
    					}
    				} else if (viewTag == ViewTypeUtil.item_view_type_thirteen || viewTag == ViewTypeUtil.item_view_type_ten) {
    					LinearLayout l = (LinearLayout) ((LinearLayout) ((LinearLayout) mMainView.getChildAt(i)).getChildAt(0)).getChildAt(1);
    					for (int j = 0; j < l.getChildCount(); j++) {
    						LinearLayout l_add = (LinearLayout) ((LinearLayout) l.getChildAt(j));
    						for (int k = 0; k < l_add.getChildCount(); k++) {
    							int viewTag_child = (int) l_add.getChildAt(k).getTag();
    							if (viewTag_child == ViewTypeUtil.item_view_type_two) {
    								LinearLayout l_view = (LinearLayout) ((LinearLayout) l_add.getChildAt(k)).getChildAt(0);
    								EditText editText = (EditText) l_view.getChildAt(1);
    								if (v.getTag().equals(editText.getTag())) {
    									mVoice = new VoiceToWord(this, editText);
    									mVoice.GetWordFromVoice();
    								}
    							}
    						}
    					}
    				}
    			}
    		} else if (v.getId() == R.id.special_iv) {// 特殊字符
    			for (int i = 0; i < mMainView.getChildCount(); i++) {
    				int viewTag = (int) mMainView.getChildAt(i).getTag();
    				if (viewTag == ViewTypeUtil.item_view_type_two) {
    					LinearLayout l = (LinearLayout) ((LinearLayout) mMainView.getChildAt(i)).getChildAt(0);
    					EditText editText = (EditText) l.getChildAt(1);
    					if (v.getTag().equals(editText.getTag())) {
    						mSpecialdialog = new SpecialWordsDialog(context, editText);
    					}
    				} else if (viewTag == ViewTypeUtil.item_view_type_thirteen || viewTag == ViewTypeUtil.item_view_type_ten) {
    					LinearLayout l = (LinearLayout) ((LinearLayout) ((LinearLayout) mMainView.getChildAt(i)).getChildAt(0)).getChildAt(1);
    					for (int j = 0; j < l.getChildCount(); j++) {
    						LinearLayout l_add = (LinearLayout) ((LinearLayout) l.getChildAt(j));
    						for (int k = 0; k < l_add.getChildCount(); k++) {
    							int viewTag_child = (int) l_add.getChildAt(k).getTag();
    							if (viewTag_child == ViewTypeUtil.item_view_type_two) {
    								LinearLayout l_view = (LinearLayout) ((LinearLayout) l_add.getChildAt(k)).getChildAt(0);
    								EditText editText = (EditText) l_view.getChildAt(1);
    								if (v.getTag().equals(editText.getTag())) {
    									mSpecialdialog = new SpecialWordsDialog(context, editText);
    								}
    							}
    						}
    					}
    				}
    			}
    		} else if (v.getId() == R.id.et_test_date_value) {// 时间选择
    
    			for (int i = 0; i < mMainView.getChildCount(); i++) {
    				int viewTag = (int) mMainView.getChildAt(i).getTag();
    				if (viewTag == ViewTypeUtil.item_view_type_three) {
    					LinearLayout l = (LinearLayout) ((LinearLayout) mMainView.getChildAt(i)).getChildAt(0);
    					EditText editText = (EditText) l.getChildAt(1);
    					if (v.getTag().equals(editText.getTag())) {
    						DlgUtil.showDateTimePickerDlgByType(this, editText, 1);
    					}
    				} else if (viewTag == ViewTypeUtil.item_view_type_fourteen) {
    					LinearLayout l = (LinearLayout) ((LinearLayout) mMainView.getChildAt(i)).getChildAt(0);
    					EditText editText = (EditText) l.getChildAt(1);
    					if (v.getTag().equals(editText.getTag())) {
    						DlgUtil.showDateTimePickerDlg(this, editText);
    
    					}
    				} else if (viewTag == ViewTypeUtil.item_view_type_fifteen) {
    					LinearLayout l = (LinearLayout) ((LinearLayout) mMainView.getChildAt(i)).getChildAt(0);
    					EditText editText = (EditText) l.getChildAt(1);
    					if (v.getTag().equals(editText.getTag())) {
    						DlgUtil.showDateTimePickerDlgByType(this, editText, 2);
    					}
    				} else if (viewTag == ViewTypeUtil.item_view_type_thirteen || viewTag == ViewTypeUtil.item_view_type_ten) {
    					LinearLayout l = (LinearLayout) ((LinearLayout) ((LinearLayout) mMainView.getChildAt(i)).getChildAt(0)).getChildAt(1);
    					for (int j = 0; j < l.getChildCount(); j++) {
    						LinearLayout l_add = (LinearLayout) ((LinearLayout) l.getChildAt(j));
    						for (int k = 0; k < l_add.getChildCount(); k++) {
    							int viewTag_child = (int) l_add.getChildAt(k).getTag();
    							if (viewTag_child == ViewTypeUtil.item_view_type_three) {
    								LinearLayout l_view = (LinearLayout) ((LinearLayout) l_add.getChildAt(i)).getChildAt(0);
    								EditText editText = (EditText) l_view.getChildAt(1);
    								if (v.getTag().equals(editText.getTag())) {
    									DlgUtil.showDateTimePickerDlgByType(this, editText, 1);
    								}
    							} else if (viewTag_child == ViewTypeUtil.item_view_type_fourteen) {
    								LinearLayout l_view = (LinearLayout) ((LinearLayout) l_add.getChildAt(i)).getChildAt(0);
    								EditText editText = (EditText) l_view.getChildAt(1);
    								if (v.getTag().equals(editText.getTag())) {
    									DlgUtil.showDateTimePickerDlg(this, editText);
    
    								}
    							} else if (viewTag_child == ViewTypeUtil.item_view_type_fifteen) {
    								LinearLayout l_view = (LinearLayout) ((LinearLayout) l_add.getChildAt(i)).getChildAt(0);
    								EditText editText = (EditText) l_view.getChildAt(1);
    								if (v.getTag().equals(editText.getTag())) {
    									DlgUtil.showDateTimePickerDlgByType(this, editText, 2);
    								}
    							}
    						}
    					}
    				}
    			}
    
    		} else if (v.getId() == R.id.et_select_value) {
    			for (int i = 0; i < mMainView.getChildCount(); i++) {
    				int viewTag = (int) mMainView.getChildAt(i).getTag();
    				if (viewTag == ViewTypeUtil.item_view_type_five) {
    					LinearLayout l = (LinearLayout) ((LinearLayout) mMainView.getChildAt(i)).getChildAt(0);
    					final EditText editText = (EditText) l.getChildAt(1);
    					if (v.getTag(R.id.select_view_detial_id).equals(editText.getTag(R.id.select_view_detial_id))) {
    						int position = (int) editText.getTag(R.id.select_view_position);
    						mDataList.clear();
    						List<DicBean> dicList = mFormDetailList.get(position).dicBeanList;
    						for (DicBean dicBean : dicList) {
    							mDataList.add(dicBean.getDicName());
    						}
    						CusSpinerAdapter<String> mAdapter = new CusSpinerAdapter<String>(this);
    						mAdapter.refreshData(mDataList, 0);
    						View contentView = LayoutInflater.from(context).inflate(R.layout.common_form_view, null);
    						SpinerPopWindow mSpinerPopWindow = new SpinerPopWindow(this, R.layout.spiner_window_layout, true);
    						mSpinerPopWindow.setAdatper(mAdapter);
    						mSpinerPopWindow.setItemListener(new IOnItemSelectListener() {
    
    							@Override
    							public void onItemClick(int pos) {
    								if (pos >= 0 && pos <= mDataList.size()) {
    									String value = (String) mDataList.get(pos);
    									editText.setText(value.toString());
    								}
    							}
    						});
    						mSpinerPopWindow.setWidth(editText.getWidth());
    
    						int windowPos[] = PopMeasure.calculatePopWindowPos(editText, contentView);
    						int xOff = 25;// 可以自己调整偏移
    						windowPos[0] -= xOff;
    						mSpinerPopWindow.showAtLocation(v, Gravity.TOP | Gravity.START, windowPos[0], windowPos[1]);
    					}
    				}else if(viewTag == ViewTypeUtil.item_view_type_thirteen || viewTag == ViewTypeUtil.item_view_type_ten){
    					LinearLayout l = (LinearLayout) ((LinearLayout) ((LinearLayout) mMainView.getChildAt(i)).getChildAt(0)).getChildAt(1);
    					for (int j = 0; j < l.getChildCount(); j++) {
    						LinearLayout l_add = (LinearLayout) ((LinearLayout) l.getChildAt(j));//第二层布局layout
    						for (int k = 0; k < l_add.getChildCount(); k++) {
    							int viewTag_child = (int) l_add.getChildAt(k).getTag();
    							if(viewTag_child == ViewTypeUtil.item_view_type_five){
    								LinearLayout l_view = (LinearLayout) ((LinearLayout) l_add.getChildAt(k)).getChildAt(0);//第三层每一项
    								final EditText editText = (EditText) l_view.getChildAt(1);
    								if (v.getTag(R.id.select_view_detial_id).equals(editText.getTag(R.id.select_view_detial_id))) {
    									int position = (int) editText.getTag(R.id.select_view_position);
    									mDataList.clear();
    									List<DicBean> dicList = new ArrayList<FormDetailBean.FormDetail.DicBean>();
    									if (viewTag == ViewTypeUtil.item_view_type_ten) {
    										dicList = mFormDetailChildList.get(position).dicBeanList;
    									}else if (viewTag == ViewTypeUtil.item_view_type_thirteen) {
    										dicList = mFormZuDetailChildList.get(position).dicBeanList;
    									}
    									
    									for (DicBean dicBean : dicList) {
    										mDataList.add(dicBean.getDicName());
    									}
    									CusSpinerAdapter<String> mAdapter = new CusSpinerAdapter<String>(this);
    									mAdapter.refreshData(mDataList, 0);
    									View contentView = LayoutInflater.from(context).inflate(R.layout.common_form_view, null);
    									SpinerPopWindow mSpinerPopWindow = new SpinerPopWindow(this, R.layout.spiner_window_layout, true);
    									mSpinerPopWindow.setAdatper(mAdapter);
    									mSpinerPopWindow.setItemListener(new IOnItemSelectListener() {
    
    										@Override
    										public void onItemClick(int pos) {
    											if (pos >= 0 && pos <= mDataList.size()) {
    												String value = (String) mDataList.get(pos);
    												editText.setText(value.toString());
    											}
    										}
    									});
    									mSpinerPopWindow.setWidth(editText.getWidth());
    									
    									int windowPos[] = PopMeasure.calculatePopWindowPos(editText, contentView);
    									int xOff = 200;// 可以自己调整偏移
    									windowPos[0] -= xOff;
    									mSpinerPopWindow.showAtLocation(v, Gravity.TOP | Gravity.START,windowPos[0], windowPos[1]);
    								}
    							}else if(viewTag_child == ViewTypeUtil.item_view_type_thirteen || viewTag_child == ViewTypeUtil.item_view_type_ten){
    								LinearLayout l3 =  (LinearLayout) ((LinearLayout) ((LinearLayout) l_add.getChildAt(k)).getChildAt(0)).getChildAt(1);
    								for (int j3 = 0; j3 < l3.getChildCount(); j3++) {
    									LinearLayout l_add3 = (LinearLayout) ((LinearLayout) l3.getChildAt(j3));
    									for (int k3 = 0; k3 < l_add3.getChildCount(); k3++) {
    										int viewTag_child3 = (int) l_add3.getChildAt(k3).getTag();
    										if(viewTag_child3 == ViewTypeUtil.item_view_type_five){
    											LinearLayout l_view = (LinearLayout) ((LinearLayout) l_add3.getChildAt(k3)).getChildAt(0);
    											final EditText editText = (EditText) l_view.getChildAt(1);
    											if (v.getTag(R.id.select_view_detial_id).equals(editText.getTag(R.id.select_view_detial_id))) {
    												int position = (int) editText.getTag(R.id.select_view_position);
    												mDataList.clear();
    												List<DicBean> dicList = mFormZuDetailChildList.get(position).dicBeanList;
    												for (DicBean dicBean : dicList) {
    													mDataList.add(dicBean.getDicName());
    												}
    												CusSpinerAdapter<String> mAdapter = new CusSpinerAdapter<String>(this);
    												mAdapter.refreshData(mDataList, 0);
    												View contentView = LayoutInflater.from(context).inflate(R.layout.common_form_view, null);
    												SpinerPopWindow mSpinerPopWindow = new SpinerPopWindow(this, R.layout.spiner_window_layout, true);
    												mSpinerPopWindow.setAdatper(mAdapter);
    												mSpinerPopWindow.setItemListener(new IOnItemSelectListener() {
    
    													@Override
    													public void onItemClick(int pos) {
    														if (pos >= 0 && pos <= mDataList.size()) {
    															String value = (String) mDataList.get(pos);
    															editText.setText(value.toString());
    														}
    													}
    												});
    												mSpinerPopWindow.setWidth(editText.getWidth());
    												
    												int windowPos[] = PopMeasure.calculatePopWindowPos(editText, contentView);
    												int xOff = 200;// 可以自己调整偏移
    												windowPos[0] -= xOff;
    												mSpinerPopWindow.showAtLocation(v, Gravity.TOP | Gravity.START,windowPos[0], windowPos[1]);
    											}
    										}
    									}
    								}
    							}
    						}
    					}
    				}
    			}
    		} else if (v.getId() == R.id.et_select_part_value) {
    			CheckPart_Monomer_Activity.actionStartForResult(context, mPartSelectValueEt.getText().toString(), "", "", monomerId, CheckPart_Monomer_Activity.class);
    		} else if (v.getId() == R.id.cbx_type_nine) {// 类型9 多选框意向
    			for (int i = 0; i < mMainView.getChildCount(); i++) {
    				int viewTag = (int) mMainView.getChildAt(i).getTag();
    				if (viewTag == ViewTypeUtil.item_view_type_nine) {
    					LinearLayout l = (LinearLayout) ((LinearLayout) mMainView.getChildAt(i)).getChildAt(0);
    					CheckBox checkBox = (CheckBox) l.getChildAt(1);
    				} else if (viewTag == ViewTypeUtil.item_view_type_thirteen || viewTag == ViewTypeUtil.item_view_type_ten) {
    					LinearLayout l = (LinearLayout) ((LinearLayout) ((LinearLayout) mMainView.getChildAt(i)).getChildAt(0)).getChildAt(1);
    					for (int j = 0; j < l.getChildCount(); j++) {
    						LinearLayout l_add = (LinearLayout) ((LinearLayout) l.getChildAt(j));
    						for (int k = 0; k < l_add.getChildCount(); k++) {
    							int viewTag_child = (int) l_add.getChildAt(k).getTag();
    							if (viewTag_child == ViewTypeUtil.item_view_type_nine) {
    								LinearLayout l_view = (LinearLayout) ((LinearLayout) l_add.getChildAt(k)).getChildAt(0);
    								CheckBox checkBox = (CheckBox) l_view.getChildAt(1);
    							}
    						}
    					}
    				}
    			}
    
    		} else if (v.getId() == R.id.item_eleven_value_et) {
    			for (int i = 0; i < mMainView.getChildCount(); i++) {
    				int viewTag = (int) mMainView.getChildAt(i).getTag(); 
    				if (viewTag == ViewTypeUtil.item_view_type_eleven) {
    					if (!TextUtils.isEmpty(mDrawingPath)) {
    						Intent intent = new Intent(CommonFormViewActivity.this, DrawingTypeActivity.class);
    						intent.putExtra("drawingPath", mDrawingPath);
    						intent.putExtra("tableDetailID", (String) v.getTag());
    						intent.putExtra("intent_from", FLAG_UPDATE);
    						if (mIntentFrom == FLAG_SHOW || mIntentFrom == FLAG_UPDATE) {// 查看,修改记录
    							intent.putExtra("RecordId", mUTableID);
    						}
    						startActivityForResult(intent, 11);
    					}
    				}
    			}
    
    		} else if (v.getId() == R.id.item_eleven_value_img_photo) {// 类型11图纸标准类型拍照按钮
    			mViewTypeFlag = ViewTypeUtil.item_view_type_eleven;
    			if (mCreateBmpFactory == null) {
    				mCreateBmpFactory = new CreateBmpFactory(CommonFormViewActivity.this);
    			}
    			mCreateBmpFactory.OpenCamera();
    		} else if (v.getId() == R.id.item_eleven_value_img_folder) {// 类型11图纸标准类型从图库选择
    			mViewTypeFlag = ViewTypeUtil.item_view_type_eleven;
    			FileSelect chosen = new FileSelect(CommonFormViewActivity.this);
    			chosen.setOnFileSelecteListener(new OnFileSelecteListener() {
    				@Override
    				public void onFileSelected(String filePath, String fileName) {
    					mDrawingPath = filePath;
    					mDrawingNameTv.setText(fileName);
    					Intent intent1 = new Intent(CommonFormViewActivity.this, DrawingTypeActivity.class);
    					intent1.putExtra("drawingPath", mDrawingPath);
    					intent1.putExtra("tableDetailID", (String) mDrawingNameTv.getTag());
    					intent1.putExtra("intent_from", FLAG_UPDATE);
    					if (mIntentFrom == FLAG_SHOW || mIntentFrom == FLAG_UPDATE) {// 查看,修改记录
    						intent1.putExtra("RecordId", mUTableID);
    					}
    					startActivityForResult(intent1, 11);
    				}
    			});
    			chosen.showChosenDialog();
    
    		} else if (v.getId() == R.id.item_twelve_value_path) {// 类型12 图片路径
    			
    		} else if (v.getId() == R.id.item_twelve_value_img_photo) {// 类型12拍照
    			mViewTypeFlag = ViewTypeUtil.item_view_type_twelve;
    			mViewTag = v.getTag();
    			if (mCreateBmpFactory == null) {
    				mCreateBmpFactory = new CreateBmpFactory(CommonFormViewActivity.this);
    			}
    			mCreateBmpFactory.OpenCamera();
    		} else if (v.getId() == R.id.item_twelve_value_img_folder) {// 类型12
    			mViewTypeFlag = ViewTypeUtil.item_view_type_twelve;
    			mViewTag = v.getTag();
    			if (mCreateBmpFactory == null) {
    				mCreateBmpFactory = new CreateBmpFactory(CommonFormViewActivity.this);
    			}
    			mCreateBmpFactory.OpenGallery();
    
    		} else if (v.getId() == R.id.iv_type_ten_add) {
    			AddListChildView();
    		}
    	}


    估计这么写看看都会头晕,因为这上面代码 里面除了处理正常的点击事件,还要处理列表和组  也就是 嵌套布局里面的点击事件。但是原理都是一样的。

     

    就是循环布局找到 你点击的那个布局,那个控件...  如果是嵌套多级  就一级一级的找...

    5.保存上传数据

    我们这边保存处理的逻辑就是将界面上所有的数据都拼成一个JSONOject  里面套JSONArray和JSONObject ,反正就是根据自己的业务往里面套数据,这个数据组织起来稍微有一点点麻烦。

    代码贴一下:

     

    package com.jky.xmxtcommonlib.utils;
    
    import org.json.JSONException;
    import org.json.JSONObject;
    
    import com.jky.xmxtcommonlib.R;
    
    import android.widget.CheckBox;
    import android.widget.EditText;
    import android.widget.LinearLayout;
    import android.widget.RadioButton;
    import android.widget.RadioGroup;
    import android.widget.TextView;
    
    /**
     * Created by zlw on 2017/6/13.
     */
    public class GetViewValueUtil {
    
    	// 表格输入框取值方法
    	public static JSONObject getTypeZeroValue(LinearLayout linearLayout, JSONObject jsonObject) throws JSONException {
    		EditText editText = (EditText) linearLayout.getChildAt(1);
    		String id = editText.getTag() + "";
    		String str = editText.getText().toString().trim();
    		jsonObject.put(id + "", str);
    		return jsonObject;
    	}
    
    	
    	// 单行输入框取值方法
    	public static JSONObject getTypeOneValue(LinearLayout linearLayout, JSONObject jsonObject) throws JSONException {
    		EditText editText = (EditText) linearLayout.getChildAt(1);
    		String id = editText.getTag() + "";
    		String str = editText.getText().toString().trim();
    		jsonObject.put(id + "", str);
    		return jsonObject;
    	}
    
    	// 多行输入框取值方法
    	public static JSONObject getTypeTwoValue(LinearLayout linearLayout, JSONObject jsonObject) throws JSONException {
    		EditText editText = (EditText) linearLayout.getChildAt(1);
    		String id = editText.getTag() + "";
    		String str = editText.getText().toString().trim();
    		jsonObject.put(id + "", str);
    		return jsonObject;
    	}
    
    	// 时间选择框取值方法
    	public static JSONObject getTypeThreeValue(LinearLayout linearLayout, JSONObject jsonObject) throws JSONException {
    		if(linearLayout !=null){
    			EditText editText = (EditText) linearLayout.getChildAt(1);
    			if(editText!=null){
    				String id = editText.getTag() + "";
    				String str = editText.getText().toString().trim();
    				jsonObject.put(id + "", str);
    			}else{
    				JSONObject json= new JSONObject();
    				return json;
    			}
    		} else {
    			JSONObject json= new JSONObject();
    			return json;
    		}
    		
    		return jsonObject;
    	}
    
    	// 数值输入框取值方法
    	public static JSONObject getTypeFourValue(LinearLayout linearLayout, JSONObject jsonObject) throws JSONException {
    		EditText editText = (EditText) linearLayout.getChildAt(1);
    		String id = editText.getTag() + "";
    		String str = editText.getText().toString().trim();
    		jsonObject.put(id + "", str);
    		return jsonObject;
    	}
    
    	// 下拉选择框取值方法
    	public static JSONObject getTypeFiveValue(LinearLayout linearLayout, JSONObject jsonObject) throws JSONException {
    		EditText editText = (EditText) linearLayout.getChildAt(1);
    		String id = editText.getTag(R.id.select_view_detial_id) + "";
    		String str = editText.getText().toString().trim();
    		jsonObject.put(id + "", str);
    		return jsonObject;
    	}
    
    	// 部位选择框取值方法
    	public static JSONObject getTypeSevenValue(LinearLayout linearLayout, JSONObject jsonObject) throws JSONException {
    		EditText editText = (EditText) linearLayout.getChildAt(1);
    		String id = editText.getTag() + "";
    		String str = editText.getText().toString().trim();
    		jsonObject.put(id + "", str);
    		return jsonObject;
    	}
    
    	// 单选框取值方法
    	public static JSONObject getTypeEightValue(LinearLayout linearLayout, JSONObject jsonObject) throws JSONException {
    		RadioGroup radioGroup = (RadioGroup) linearLayout.getChildAt(1);
    		for (int i = 0; i < radioGroup.getChildCount(); i++) {
    			RadioButton radioButton = (RadioButton) radioGroup.getChildAt(i);
    			String  str = (String) radioButton.getTag();
    			String detailId = str.split(",")[0];
    			String dicId = str.split(",")[1];
    			if (radioButton.isChecked()) {
    					jsonObject.put(detailId + "", dicId);
    			}
    		}
    		return jsonObject;
    	}
    
    	// 多选框取值方法
    	public static JSONObject getTypeNineValue(LinearLayout linearLayout, JSONObject jsonObject) throws JSONException {
    		CheckBox checkBox = (CheckBox) linearLayout.getChildAt(1);
    		String value = "";
    		String  str = (String) checkBox.getTag();
    		if (checkBox.isChecked()) {
    			value = checkBox.getText().toString().trim();
    			String detailId = str.split(",")[0];
    			String dicId = str.split(",")[1];
    			jsonObject.put(detailId,dicId);
    		} else {
    			String detailId = str.split(",")[0];
    			jsonObject.put(detailId, "0");
    		}
    		
    		return jsonObject;
    	}
    	
    	// 图纸类表格类型存值
    		public static JSONObject getTypeElevenValue(LinearLayout linearLayout,String path, JSONObject jsonObject) throws JSONException {
    			TextView extView = (TextView) linearLayout.getChildAt(1);
    			String id = extView.getTag() + "";
    			String str = path.trim();
    			jsonObject.put(id + "", str);
    			return jsonObject;
    		}
    	// 照片类表格类型存值
    	public static JSONObject getTypeTwelveValue(LinearLayout linearLayout,String path, JSONObject jsonObject) throws JSONException {
    		TextView extView = (TextView) linearLayout.getChildAt(0);
    		String id = extView.getTag() + "";
    		String str = path.trim();
    		jsonObject.put(id + "", str);
    		return jsonObject;
    	}
    }
    
    	/**
    	 * 得到需要保存的json数据
    	 * 
    	 * @param linearLayout
    	 * @param isChildFlag
    	 * @param jsonKey
    	 * @throws JSONException
    	 */
    	private void getJsonInfo(LinearLayout linearLayout) throws JSONException {
    		for (int i = 0; i < linearLayout.getChildCount(); i++) {
    			int viewTag = (int) linearLayout.getChildAt(i).getTag();
    			if (viewTag == ViewTypeUtil.item_view_type_zero) {
    				LinearLayout l = (LinearLayout) ((LinearLayout) linearLayout.getChildAt(i)).getChildAt(0);
    				mJsonObject = GetViewValueUtil.getTypeZeroValue(l, mJsonObject);
    			} else if (viewTag == ViewTypeUtil.item_view_type_one) {
    				LinearLayout l = (LinearLayout) ((LinearLayout) linearLayout.getChildAt(i)).getChildAt(0);
    				mJsonObject = GetViewValueUtil.getTypeOneValue(l, mJsonObject);
    			} else if (viewTag == ViewTypeUtil.item_view_type_two) {
    				LinearLayout l = (LinearLayout) ((LinearLayout) linearLayout.getChildAt(i)).getChildAt(0);
    				mJsonObject = GetViewValueUtil.getTypeTwoValue(l, mJsonObject);
    			} else if (viewTag == ViewTypeUtil.item_view_type_three) {
    				LinearLayout l = (LinearLayout) ((LinearLayout) linearLayout.getChildAt(i)).getChildAt(0);
    				mJsonObject = GetViewValueUtil.getTypeThreeValue(l, mJsonObject);
    			} else if (viewTag == ViewTypeUtil.item_view_type_four) {
    				LinearLayout l = (LinearLayout) ((LinearLayout) linearLayout.getChildAt(i)).getChildAt(0);
    				mJsonObject = GetViewValueUtil.getTypeFourValue(l, mJsonObject);
    
    			} else if (viewTag == ViewTypeUtil.item_view_type_five) {
    				LinearLayout l = (LinearLayout) ((LinearLayout) linearLayout.getChildAt(i)).getChildAt(0);
    				mJsonObject = GetViewValueUtil.getTypeFiveValue(l, mJsonObject);
    			} else if (viewTag == ViewTypeUtil.item_view_type_six) {
    
    			} else if (viewTag == ViewTypeUtil.item_view_type_seven) {
    				LinearLayout l = (LinearLayout) ((LinearLayout) linearLayout.getChildAt(i)).getChildAt(0);
    				mJsonObject = GetViewValueUtil.getTypeSevenValue(l, mJsonObject);
    			} else if (viewTag == ViewTypeUtil.item_view_type_eight) {
    				LinearLayout l = (LinearLayout) ((LinearLayout) linearLayout.getChildAt(i)).getChildAt(0);
    				mJsonObject = GetViewValueUtil.getTypeEightValue(l, mJsonObject);
    			} else if (viewTag == ViewTypeUtil.item_view_type_nine) {
    				LinearLayout l = (LinearLayout) ((LinearLayout) linearLayout.getChildAt(i)).getChildAt(0);
    				mJsonObject = GetViewValueUtil.getTypeNineValue(l, mJsonObject);
    			} else if (viewTag == ViewTypeUtil.item_view_type_ten) {
    				LinearLayout l = (LinearLayout) ((LinearLayout) linearLayout.getChildAt(i)).getChildAt(0);
    				LinearLayout layout = (LinearLayout) l.getChildAt(1);
    				getSecondJsonInfo(layout, (String) layout.getTag());
    				mJsonObject.put((String) layout.getTag(), mSecondJsonArray);
    			} else if (viewTag == ViewTypeUtil.item_view_type_eleven) {
    				LinearLayout l = (LinearLayout) ((LinearLayout) linearLayout.getChildAt(i)).getChildAt(0);
    				if (!TextUtils.isEmpty(mDrawingPath)) {
    					mJsonObject = GetViewValueUtil.getTypeElevenValue(l, mDrawingPath, mJsonObject);
    				}
    			} else if (viewTag == ViewTypeUtil.item_view_type_twelve) {
    				if(!TextUtils.isEmpty(mPhotoPath)){
    					LinearLayout l = (LinearLayout) ((LinearLayout) ((LinearLayout) linearLayout.getChildAt(i)).getChildAt(0)).getChildAt(1);
    					mJsonObject = GetViewValueUtil.getTypeTwelveValue(l, mPhotoPath, mJsonObject);
    				}
    			} else if (viewTag == ViewTypeUtil.item_view_type_thirteen) {
    				LinearLayout l = (LinearLayout) ((LinearLayout) linearLayout.getChildAt(i)).getChildAt(0);
    				LinearLayout layout = (LinearLayout) l.getChildAt(1);
    				getSecondJsonInfo(layout, (String) layout.getTag());
    				mJsonObject.put((String) layout.getTag(), mSecondJsonArray);
    			} else if (viewTag == ViewTypeUtil.item_view_type_fourteen) {
    				LinearLayout l = (LinearLayout) ((LinearLayout) linearLayout.getChildAt(i)).getChildAt(0);
    				mJsonObject = GetViewValueUtil.getTypeThreeValue(l, mJsonObject);
    			} else if (viewTag == ViewTypeUtil.item_view_type_fifteen) {
    				LinearLayout l = (LinearLayout) ((LinearLayout) linearLayout.getChildAt(i)).getChildAt(0);
    				mJsonObject = GetViewValueUtil.getTypeThreeValue(l, mJsonObject);
    			}
    		}
    	}

     


    大概意思就是这样,核心的就是这个,其实也不是很复杂。

     

     

     

    这样就实现了动态拼接app界面,不用重复性的写大量的界面,当然一般app是没有这么恶心的功能的...但我还是贴出来,希望能帮到后面入坑的同学....

     

    这个由于直接在项目里面写的,不容易抽剥代码。demo暂时先不整理了,大家如果有问题可以加入我的qq群讨论
     

    开发一群:454430053开发二群:537532956

     

    展开全文
  • android开发之音频拼接

    千次阅读 2018-05-05 13:01:59
    第一种情况:不同压缩格式音频拼接,不同的压缩格式拼接需要解码为采样数据然后拼接,然后再编码为统一的压缩格式。 方法一:FFmpeg命令拼接,ffmpeg -I ‘concat:0.mp3|1.wav|2.aac’ -acodec copy merge.mp3...

    第一种情况:不同压缩格式音频拼接,不同的压缩格式拼接需要解码为采样数据然后拼接,然后再编码为统一的压缩格式。
    这里写图片描述

    方法一:FFmpeg命令拼接,ffmpeg -I ‘concat:0.mp3|1.wav|2.aac’ -acodec copy merge.mp3。(注意:这种方式,速度相对还可以,但是在android设备上一下子拼接6个音频以上就会奔溃,应该是C代码中有什么变量没有释放掉)

      static {
            System.loadLibrary("MyLib");
        }
      public native void command(int len,String[] argv);
     /**
         * 使用ffmpeg命令行进行音频合并
         * @param src 源文件
         * @param targetFile 目标文件
         * @return 合并后的文件
         */
        public static  String[] concatAudio(String[] src, String targetFile){
            String join = StringUtils.join("|", src);
            String concatAudioCmd = "ffmpeg -i concat:%s -acodec copy %s";//%s|%s
            concatAudioCmd = String.format(concatAudioCmd, join, targetFile);
            return concatAudioCmd.split(" ");//以空格分割为字符串数组
        }
    
       /**
         * 拼接音频
         * @param paths 音频地址集合
         * @return 音频拼接之后的地址
         */
        private String jointAudio1(List<String> paths) {
            String path = "";
            for (int i = 1; i < paths.size(); i++) {
                String[] pathArr = new String[2];
                    if (i==1) {
                        pathArr[0] = paths.get(i - 1);
                        pathArr[1] = paths.get(i);
                    }else{
                        pathArr[0] = path;
                        pathArr[1] = paths.get(i);
                    }
                File file = new File(paths.get(0));
                path = file.getParent().concat(File.separator).concat(String.valueOf(System.currentTimeMillis()).concat("-debris.mp3"));
                String[] command = FFmpegUtil.concatAudio(pathArr, path);
                command(command.length,command);
            }
            return path;
        }
    #include <jni.h>
    #include <malloc.h>
    #include <string.h>
    #include "ffmpeg.h"
    #include "libavcodec/avcodec.h"
    #include "libavformat/avformat.h"
    #include <libavutil/imgutils.h>
    #include <libswscale/swscale.h>
    //音频采样
    #include <libswresample/swresample.h>
    #include <android/log.h>
    #define LOG_I_ARGS(FORMAT,...) __android_log_print(ANDROID_LOG_INFO,"main",FORMAT,__VA_ARGS__);
    #define LOG_I(FORMAT) LOG_I_ARGS(FORMAT,0);
    
    //视频转码压缩主函数入口
    //ffmpeg_mod.c有一个FFmpeg视频转码主函数入口
    // argc = str.split(" ").length()
    // argv = str.split(" ")  字符串数组
    //参数一:命令行字符串命令个数
    //参数二:命令行字符串数组
    int ffmpegmain(int argc, char **argv);
    
    
    JNIEXPORT void JNICALL Java_com_xy_openndk_audiojointdemo_FFmpegLib_command
            (JNIEnv *env, jobject jobj,jint jlen,jobjectArray jobjArray){
        //转码
        //将java的字符串数组转成C字符串
        int argc = jlen;
        //开辟内存空间
        char **argv = (char**)malloc(sizeof(char*) * argc);
    
        //填充内容
        for (int i = 0; i < argc; ++i) {
            jstring str = (*env)->GetObjectArrayElement(env,jobjArray,i);
            const char* tem = (*env)->GetStringUTFChars(env,str,0);
            argv[i] = (char*)malloc(sizeof(char)*1024);
            strcpy(argv[i],tem);
            (*env)->ReleaseStringUTFChars(env,str,tem);
        }
        //开始转码(底层实现就是只需命令)
        ffmpegmain(argc,argv);
        //释放内存空间
        for (int i = 0; i < argc; ++i) {
            free(argv[i]);
        }
        //释放数组
        free(argv);
    }

    方法二:FFmpeg解码为采样数据之后拼接采样数据,然后再编码为压缩格式数据。这里我选用了FFmpeg进行编解码,当然也可以选择Android系统提供的MediaCodec进行解码拼接再编码。(注意:这种方式速度很慢很慢的,但这种方式是最安全科学的做法。)

    include <jni.h>
    #include <android/log.h>
    extern "C" {
    #include "libavcodec/avcodec.h"
    #include "libavformat/avformat.h"
    #include "libavutil/imgutils.h"
    #include "libswscale/swscale.h"
    //音频采样
    #include "libswresample/swresample.h"
    #include "mp3enc/lame.h"
    }
    #define LOG_I_ARGS(FORMAT, ...) __android_log_print(ANDROID_LOG_INFO,"main",FORMAT,__VA_ARGS__);
    #define LOG_I(FORMAT) LOG_I_ARGS(FORMAT,0);
    #define MAX_AUDIO_FRAME_SIZE (44100)
    AVFormatContext *av_fm_ctx = NULL;
    AVCodecParameters *av_codec_pm = NULL;
    AVCodec *av_codec = NULL;
    AVCodecContext *av_codec_ctx = NULL;
    AVPacket *packet = NULL;
    AVFrame *in_frame = NULL;
    SwrContext *swr_ctx = NULL;
    uint8_t *out_buffer = NULL;
    
    /**
     * 音频解码
     * @param out 拼接的采样数据文件
     * @param path 音频地址
     */
    void decodeAudio(FILE *out, const char *path);
    
    /**
     * 音频编码
     * @param path PCM文件地址
     * @param out 输出文件地址
     */
    void encoder(const char* path,const char* out);
    
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_xy_audio_ffmpegjointaudio_MainActivity_jointAudio(JNIEnv *env, jobject instance,
                                                               jobjectArray paths_, jstring path_,jstring other_) {
        jsize len = env->GetArrayLength(paths_);
        //音频输入文件
        const char *out = env->GetStringUTFChars(path_, NULL);
        const char* other = env->GetStringUTFChars(other_,NULL);
    //    //写入文件
        FILE *file_out_dcm = fopen(out, "wb+");
        //注册输入输出组件
        av_register_all();
    
        for (int i = 0; i < len; i++) {
            jstring str = (jstring) env->GetObjectArrayElement(paths_, i);
            const char *path = env->GetStringUTFChars(str, 0);
            LOG_I(path);
            //解码拼接
            decodeAudio(file_out_dcm, path);
            env->ReleaseStringUTFChars(str, path);
        }
        fclose(file_out_dcm);
        env->ReleaseStringUTFChars(path_, out);
        env->ReleaseStringUTFChars(other_,other);
        av_packet_free(&packet);
        if(out_buffer != NULL)
        av_freep(out_buffer);
        avformat_close_input(&av_fm_ctx);
        avformat_free_context(av_fm_ctx);
        //编码
        encoder(out,other);
    }
    
    /**
     * 音频解码
     * @param out 输出文件
     * @param path 解码的文件地址
     */
    void decodeAudio(FILE *out, const char *path) {
        av_fm_ctx = avformat_alloc_context();
        int av_fm_open_result = avformat_open_input(&av_fm_ctx, path, NULL, NULL);
        if (av_fm_open_result != 0) {
            LOG_I("打开失败!");
            return;
        }
        //获取音频文件信息
        if (avformat_find_stream_info(av_fm_ctx, NULL) < 0) {
            LOG_I("获取信息失败");
            return;
        }
        //查找音频解码器
        //找到音频流索引位置
        int audio_stream_index = -1;
        for (int i = 0; i < av_fm_ctx->nb_streams; i++) {
            //查找音频流索引位置
            if (av_fm_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
                audio_stream_index = i;
                break;
            }
        }
        //判断是否存在音频流
        if (audio_stream_index == -1) {
            LOG_I("没有这个音频流!");
            return;
        }
        //获取编码器上下文(获取编码器ID)
        av_codec_pm = av_fm_ctx->streams[audio_stream_index]->codecpar;
    
        //获取解码器(根据编码器的ID,找到对应的解码器)
        av_codec = avcodec_find_decoder(av_codec_pm->codec_id);
        //打开解码器
        av_codec_ctx = avcodec_alloc_context3(av_codec);
        //根据所提供的编解码器的值填充编译码上下文
        int avcodec_to_context = avcodec_parameters_to_context(av_codec_ctx,av_codec_pm);
        if(avcodec_to_context < 0){
            return;
        }
        int av_codec_open_result = avcodec_open2(av_codec_ctx, av_codec, NULL);
        if (av_codec_open_result != 0) {
            LOG_I("解码器打开失败!");
            return;
        }
        //从输入文件读取一帧压缩数据
        //循环遍历
        //保存一帧读取的压缩数据-(提供缓冲区)
            packet = (AVPacket *) av_malloc(sizeof(AVPacket));
        //内存分配
            in_frame = av_frame_alloc();
        //定义上下文(开辟内存)
            swr_ctx = swr_alloc();
        //设置音频采样上下文参数(例如:码率、采样率、采样格式、输出声道等等......)
        //swr_alloc_set_opts参数分析如下
        //参数一:音频采样上下文
        //参数二:输出声道布局(例如:立体、环绕等等......)
        //立体声
        uint64_t out_ch_layout = AV_CH_LAYOUT_STEREO;
        //参数三:输出音频采样格式(采样精度)
        AVSampleFormat av_sm_fm = AV_SAMPLE_FMT_S16;
        //参数四:输出音频采样率(例如:44100Hz、48000Hz等等......)
        //在这里需要注意:保证输出采样率和输入的采样率保证一直(如果你不想一直,你可进行采样率转换)
        int out_sample_rate = av_codec_ctx->sample_rate;
        //输入声道布局
        int64_t in_ch_layout = av_get_default_channel_layout(av_codec_ctx->channels);
        //参数六:输入音频采样格式(采样精度)
        //参数七:输入音频采样率(例如:44100Hz、48000Hz等等......)
        //参数八:偏移量
        //参数九:日志统计上下文
        swr_alloc_set_opts(swr_ctx,
                           out_ch_layout,
                           av_sm_fm,
                           out_sample_rate,
                           in_ch_layout,
                           av_codec_ctx->sample_fmt,
                           av_codec_ctx->sample_rate,
                           0,
                           NULL);
        //初始化音频采样数据上下文
        swr_init(swr_ctx);
        //音频采样数据缓冲区(每一帧大小)
        //44100 16bit  大小: size = 44100 * 2 / 1024 = 86KB
        //最大采样率
            out_buffer = (uint8_t *) av_malloc(MAX_AUDIO_FRAME_SIZE);
        //获取输出声道数量(根据声道布局获取对应的声道数量)
        int out_nb_channels = av_get_channel_layout_nb_channels(out_ch_layout);
        //大于等于0,继续读取,小于0说明读取完毕或者读取失败
        int ret, index = 0;
        while (av_read_frame(av_fm_ctx, packet) >= 0) {
            //解码一帧音频压缩数据得到音频采样数据
            if (packet->stream_index == audio_stream_index) {
                //解码一帧音频压缩数据,得到一帧音频采样数据
                //0:表示成功(成功解压一帧音频压缩数据)
                //AVERROR(EAGAIN): 现在输出数据不可用,可以尝试发送一帧新的视频压缩数据(或者说尝试解压下一帧视频压缩数据)
                //AVERROR_EOF:解码完成,没有新的视频压缩数据
                //AVERROR(EINVAL):当前是一个编码器,但是编解码器未打开
                //AVERROR(ENOMEM):解码一帧视频压缩数据发生异常
                avcodec_send_packet(av_codec_ctx, packet);
                //返回值解释:
                //0:表示成功(成功获取一帧音频采样数据)
                //AVERROR(EAGAIN): 现在输出数据不可用,可以尝试接受一帧新的视频像素数据(或者说尝试获取下一帧视频像素数据)
                //AVERROR_EOF:接收完成,没有新的视频像素数据了
                //AVERROR(EINVAL):当前是一个编码器,但是编解码器未打开
                ret = avcodec_receive_frame(av_codec_ctx, in_frame);
                if (ret == 0) {
                    //将音频采样数据保存(写入到文件中)
                    //音频采样数据格式是:PCM格式、采样率(44100Hz)、16bit
                    //对音频采样数据进行转换为PCM格式
                    //参数一:音频采样上下文
                    //参数二:输出音频采样缓冲区
                    //参数三:输出缓冲区大小
                    //参数四:输入音频采样数据
                    //参数五:输入音频采样数据大小
                    swr_convert(swr_ctx,
                                &out_buffer,
                                MAX_AUDIO_FRAME_SIZE,
                                (const uint8_t **) in_frame->data, in_frame->nb_samples);
    
                    //获取缓冲区实际数据大小
                    //参数一:行大小
                    //参数二:输出声道个数
                    //参数三:输入的大小
                    //参数四:输出的音频采样数据格式
                    //参数五:字节对齐
                   int out_buffer_size = av_samples_get_buffer_size(NULL,
                  out_nb_channels,in_frame->nb_samples,av_sm_fm, 1);
                    //写入到文件中
                    fwrite(out_buffer, 1, (size_t) out_buffer_size, out);
                    LOG_I_ARGS("音频帧:%d\n", ++index);
                }
            }
        }
        swr_close(swr_ctx);
        swr_free(&swr_ctx);
        av_frame_free(&in_frame);
        avcodec_parameters_free(&av_codec_pm);
        avcodec_close(av_codec_ctx);
        avcodec_free_context(&av_codec_ctx);
    }
    
    /**
     * 音频编码
     * @param path PCM文件地址
     * @param out 输出文件地址
     */
    void encoder(const char* path,const char* out){
        //打开 pcm,MP3文件
        FILE* fpcm = fopen(path,"rb");
        FILE* fmp3 = fopen(out,"wb");
        short int pcm_buffer[8192*2];
        unsigned char mp3_buffer[8192];
        //初始化lame的编码器
        lame_t lame =  lame_init();
        //设置lame mp3编码的采样率
        lame_set_in_samplerate(lame , 44100);
        lame_set_num_channels(lame,2);
        //设置MP3的编码方式
        lame_set_VBR(lame, vbr_default);
        lame_init_params(lame);
        LOG_I("lame init finish");
        int read ; int write; //代表读了多少个次 和写了多少次
        int total=0; // 当前读的wav文件的byte数目
        do{
            read = fread(pcm_buffer,sizeof(short int)*2, 8192,fpcm);
            total +=  read* sizeof(short int)*2;
            LOG_I_ARGS("converting ....%d", total);
    
            // 调用java代码 完成进度条的更新
            if(read!=0){
                write = lame_encode_buffer_interleaved(lame,pcm_buffer,read,mp3_buffer,8192);
                //把转化后的mp3数据写到文件里
                fwrite(mp3_buffer,sizeof(unsigned char),write,fmp3);
            }
            if(read==0){
                lame_encode_flush(lame,mp3_buffer,8192);
            }
        }while(read!=0);
        LOG_I("convert  finish");
        lame_close(lame);
        fclose(fpcm);
        fclose(fmp3);
    }
    
      static {
            System.loadLibrary("native-lib");
        }
       /**
         * 拼接音频
         * @param paths 音频地址集合
         * @param path 采样数据地址
         * @param out 编码数据地址
         */  
     public native void jointAudio(String[]paths,String path,String out);
    
      public void jointAudioClick(View view) {
            List<String> audioList = new ArrayList<String>();
            audioList.add(path+"0.mp3");
            audioList.add(path+"1.wav");
            audioList.add(path+"2.aac");
            new Thread(new Runnable() {
                    @Override
                    public void run() { 
                jointAudio(finalPaths,target,path+"eng100.mp3");  
                    }
                }).start();
                }

    第二种情况,相同格式音频拼接,只需要字节流拼接即可,当然如果不嫌效率低也可以选用以上两种方式进行拼接。(注意:音频的声道数需要一致,我开发遇到把单声道和立体声拼接到一块,会使得音频时间成倍增加,各位请注意。)

     public void jointAudio(String audioPath, String toPath)throws Exception {
            File audioFile = new File(audioPath);
            File toFile = new File(toPath);
            FileInputStream in=new FileInputStream(audioFile);
            FileOutputStream out=new FileOutputStream(toFile,true);
    
            byte bs[]=new byte[1024*4];
            int len=0;
            //先读第一个
            while((len=in.read(bs))!=-1){
                out.write(bs,0,len);
            }
            in.close();
            out.close();
        }
     public void jointAudioClick(View view) {
            List<String> audioList = new ArrayList<String>();
            audioList.add(path+"0.mp3");
            audioList.add(path+"1.mp3");
            audioList.add(path+"2.mp3");
            new Thread(new Runnable() {
                    @Override
                    public void run() { 
                try {
                   for (String audioPath : audioList) {
                      //拼接
                      jointAudio(audioPath, path + "eng100100.mp3");
                      }catch (Exception ex){
                        ex.printStackTrace();
                      }
                    }
                }).start();
                }

    本文章著作版权所属:微笑面对,请关注我的CSDN博客:博客地址

    展开全文
  • Android使用opencv识别两张图片的相同区域,去重拼接,可以拼接多张图片
  • Android拼接合并图片生成长图

    千次阅读 2018-06-20 10:55:00
    Android拼接合并图片生成长图代码实现合并两张图片,以第一张图片的宽度为标准,如果被合并的第二张图片宽度和第一张不同,那么就以第一张图片的宽度为准线,对第二张图片进行缩放。假设根目录的Pictures下已经有两...

    Android拼接合并图片生成长图


    代码实现合并两张图片,以第一张图片的宽度为标准,如果被合并的第二张图片宽度和第一张不同,那么就以第一张图片的宽度为准线,对第二张图片进行缩放。

    假设根目录的Pictures下已经有两张图片zhang.jpg和phil.jpg,最终把这两张图片合并成zhangphil.jpg的长图:

    package zhangphil.test;
    
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.graphics.Matrix;
    import android.os.Bundle;
    import android.os.Environment;
    import android.support.annotation.Nullable;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
    
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    
    public class JavaActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.drawable_activity);
    
            findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    merge();
                }
            });
        }
    
        private void merge() {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    File zhang = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "zhang.jpg");
                    File phil = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "phil.jpg");
    
                    try {
                        Bitmap bitmap1 = BitmapFactory.decodeStream(new FileInputStream(zhang));
                        Bitmap bitmap2 = BitmapFactory.decodeStream(new FileInputStream(phil));
    
                        Bitmap newBmp = newBitmap(bitmap1, bitmap2);
    
                        File zhangphil = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "zhangphil.jpg");
                        if (!zhangphil.exists())
                            zhangphil.createNewFile();
                        save(newBmp, zhangphil, Bitmap.CompressFormat.JPEG, true);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    
        public static Bitmap newBitmap(Bitmap bmp1, Bitmap bmp2) {
            Bitmap retBmp;
            int width = bmp1.getWidth();
            if (bmp2.getWidth() != width) {
                //以第一张图片的宽度为标准,对第二张图片进行缩放。
    
                int h2 = bmp2.getHeight() * width / bmp2.getWidth();
                retBmp = Bitmap.createBitmap(width, bmp1.getHeight() + h2, Bitmap.Config.ARGB_8888);
                Canvas canvas = new Canvas(retBmp);
                Bitmap newSizeBmp2 = resizeBitmap(bmp2, width, h2);
                canvas.drawBitmap(bmp1, 0, 0, null);
                canvas.drawBitmap(newSizeBmp2, 0, bmp1.getHeight(), null);
            } else {
                //两张图片宽度相等,则直接拼接。
                
                retBmp = Bitmap.createBitmap(width, bmp1.getHeight() + bmp2.getHeight(), Bitmap.Config.ARGB_8888);
                Canvas canvas = new Canvas(retBmp);
                canvas.drawBitmap(bmp1, 0, 0, null);
                canvas.drawBitmap(bmp2, 0, bmp1.getHeight(), null);
            }
    
            return retBmp;
        }
    
        public static Bitmap resizeBitmap(Bitmap bitmap, int newWidth, int newHeight) {
            float scaleWidth = ((float) newWidth) / bitmap.getWidth();
            float scaleHeight = ((float) newHeight) / bitmap.getHeight();
            Matrix matrix = new Matrix();
            matrix.postScale(scaleWidth, scaleHeight);
            Bitmap bmpScale = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
            return bmpScale;
        }
    
        /**
         * 保存图片到文件File。
         *
         * @param src     源图片
         * @param file    要保存到的文件
         * @param format  格式
         * @param recycle 是否回收
         * @return true 成功 false 失败
         */
        public static boolean save(Bitmap src, File file, Bitmap.CompressFormat format, boolean recycle) {
            if (isEmptyBitmap(src))
                return false;
    
            OutputStream os;
            boolean ret = false;
            try {
                os = new BufferedOutputStream(new FileOutputStream(file));
                ret = src.compress(format, 100, os);
                if (recycle && !src.isRecycled())
                    src.recycle();
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            return ret;
        }
    
        /**
         * Bitmap对象是否为空。
         */
        public static boolean isEmptyBitmap(Bitmap src) {
            return src == null || src.getWidth() == 0 || src.getHeight() == 0;
        }
    }
    

    合并后生成的长图:



    添加权限:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


    展开全文
  • android 视频拼接demo

    2020-07-30 23:32:14
    很好地解决了mp4视频的拼接问题
  • Android DataBinding 字符串拼接

    万次阅读 2019-05-24 15:39:34
    对于字符串拼接 总是忘记如何实现,特此记录。 <layout xmlns:android="http://schemas.android.com/apk/res/android"><data> <variable name="bean" type="com.ethanco.threa

    对于字符串拼接 总是忘记如何实现,特此记录。

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android">
    
    <data>
    
        <variable
            name="bean"
            type="com.ethanco.threadtest.Bean" />
    </data>
    
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{@string/user_name+bean.name}' />
    </RelativeLayout>
    

    重点在这里

    android:text='@{@string/user_name+bean.name}'  
    

    这里的引号需要使用单引号

    注意

    特别需要注意的是,字符串的拼接不要用直接的文字表示,比如

    android:text='@{"user的name:"+bean.name}'  
    

    这种容易出问题。

    并且,DataBinding报错并不会指向错误源,事后很难排除。

    故,需采用 @string/xxxx的形式进行字符串的拼接

    展开全文
  • 需求:给一个字符串拼接上一个"全国"标签,需要一直跟在文字后面。 ui图: 想法: 采用spannable的方法给文字后面添加图片。 正文 1.写一个xml当"全国"标签view。 &lt;?xml ...
  • Android端使用FFmpeg进行视频画面拼接

    万次阅读 热门讨论 2020-01-08 10:27:24
    今天看到抖音上,有人发布水平拼接的短视频。这创意不错,本身是两个不同的短视频,通过视频拼接技术把两短视频拼在一起。除了视频进行水平拼接,音频也混合在一起。前期还需要对那两视频进行预处理:包括时长、...
  • android bitmap拼接

    2017-09-26 19:23:40
    android bitmap拼接一个简单的拼接方法//bitmaps 需要拼接的图片,按顺序传入public static Bitmap mosaicBitmapVertical(@NonNull Bitmap... bitmaps) { int height = 0; for (int i = 0; i ; i++) { height
  • 2、拼接 Uri.Builder builder = Uri.parse(url).buildUpon(); builder.appendQueryParameter("key", value); 3、修改 public static String replace(String url, String key, String value)
  • android实现图片拼接

    千次阅读 2012-07-20 10:25:04
    通过新建一个矩阵(就是一个整形数组),然后将要拼接的图片的color数组放到矩阵里,然后再重新画图; package com.test; import java.io.BufferedReader; import java.io.File; import java.io....
  • 开发项目中遇到一个需求 就是用手机按照顺序拍几张图片 然后将图片拼接成一张全景的照片 百度了一下 看到OpenCV 的Stitcher工具支持全景图片拼接 于是研究了一下OpenCV 花了差不多一周时间才研究出来 呕心沥血的...
  • Android中几种字符串拼接的效率比较

    万次阅读 2018-01-25 19:18:18
    废话不多说,直接上代码 long n = 10000; long start1 = System.currentTimeMillis(); String s1 = new String("hello");... for (long i = 0;... s1 += "拼接--"; } long end1 = System.currentTim
  • Android图片拼接

    千次阅读 2017-09-19 10:39:47
    有的时候我们的项目是需要拼接图片的,怎么实现呢? 直接上代码: /** * 横向拼接图片 * 功能详细描述> * * @param first * @param second * @return */ public static final Bitmap splitHorizontal...
  • android 字符串拼接

    千次阅读 2016-08-19 11:36:24
    String transport = listjs.getString("transport"); String spStr[] = transport.split(";"); /** * 0:飞机,1:火车,2:轮船,3:汽车 * **/ String transportstr
  • 有些朋友可能会动态的修改Android中strings.xml文件中的值,在这里给大家推荐一种简单的方法。 strings.xml中节点是支持占位符的,如下所示: &lt;string name="data"&gt;整数型:%1$d,浮点型:%2...
  • 动态分析Android App之动态调试

    千次阅读 多人点赞 2019-09-07 17:14:11
    动态分析Android App之动态调试 这个系列一共有五篇左右,内容主要介绍如何动态分析和调试Android App,和网上其他教程相比,内容更充实,体系更健全,深入而浅出。闻道有先后,术业有专攻,希望能给刚入门Android...
  • 字符串拼接在java中很常见,比如拼接url路径,那么到了jni开发中怎么使用java中拼接字符串呢?不废话了啊,直接来个案例分析 我们将Android Studio3.0默认创建的工程文本显示从jni中拼接输出… 我们写一个简单的...
  • Android图片拼接9宫格

    2019-01-29 17:54:06
    /** * 多张图片拼接9宫格 * @param margin * @param bitmaps * @return */ public static Bitmap addBitmaps(int margin, Bitmap... bitmaps) { int row=1; int col=0; ...
1 2 3 4 5 ... 20
收藏数 27,607
精华内容 11,042
关键字:

动态拼接android