最近做开发之后用到图文混排的编辑和展示,这里用到了EditView
先说下原理 用Edittext进行编辑 最后Edittext.getText();得到内容然后用Html的格式保存用webView展示
首先是布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_release" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/white" android:clipToPadding="true" android:fitsSystemWindows="true" android:orientation="vertical" tools:context="com.example.administrator.polyesports.application.baseparticulars.ReleaseActivity"> <include layout="@layout/include_toolbar" /> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/white"> <LinearLayout android:id="@+id/ll" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <EditText android:id="@+id/title_et" android:layout_width="match_parent" android:layout_height="48dp" android:layout_marginLeft="30dp" android:background="@null" android:gravity="center_vertical" android:hint="可以加标题哦~" android:textColorHint="@color/maintext2" android:textSize="13.3sp" /> <View style="@style/grey_line_style" android:layout_marginLeft="30dp" android:layout_marginRight="30dp" /> <EditText android:id="@+id/info_et" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="30dp" android:layout_marginRight="30dp" android:layout_marginTop="10dp" android:background="@null" android:gravity="start" android:hint="来说点什么吧" android:lineSpacingExtra="5dp" android:minHeight="100dp" android:textColorHint="@color/maintext2" android:textSize="13.3sp" /> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_below="@id/ll" android:layout_marginBottom="20dp" android:layout_marginRight="30dp" android:gravity="center_vertical" android:orientation="horizontal"> <ImageView android:id="@+id/addimg_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/find_activity_release_addimg" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginLeft="14dp" android:background="@drawable/miaobian_grid" android:gravity="center" android:orientation="horizontal"> <ImageView android:layout_width="wrap_content" android:layout_height="10dp" android:paddingLeft="5dp" android:src="@drawable/comment_loaction" /> <TextView android:id="@+id/loaction_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingBottom="1dp" android:paddingRight="5dp" android:paddingTop="1dp" android:text="位置信息" android:textSize="11sp" /> </LinearLayout> </LinearLayout> </RelativeLayout> </LinearLayout> </ScrollView> </LinearLayout>布局没什么好说的接下来就是activity界面代码
public class ReleaseActivity extends BaseTakePhotosActivity implements OnRequestListener { Context context; @BindView(R.id.title_right) TextView titleRight; @BindView(R.id.toolbar) Toolbar toolbar; @BindView(R.id.title_et) EditText titleEt; @BindView(R.id.info_et) EditText infoEt; @BindView(R.id.loaction_btn) TextView loaction_btn; @BindView(R.id.action_text_right) RelativeLayout actionTextRight; private StringBuilder html;//生成的html文件 private String htmlTitle = "";//html的标题 private List<EditorBean> editorList = new CopyOnWriteArrayList<>();//内容列表[并发容器 防止异常(用arraylist可能会异常)] private String titleTypeStr = "h3";//标题类型的字符串 private String baseImgUrl;//图片存放的路径 //保存图片返回地址 private String lastimg = ""; //设置图片标记 private int imgbiaoji = -1; //集合标记 private int mapbiaoji = -1; //上传照片名字 private String imgsid = ""; //城市名字 private String cityname = ""; private Map<Integer, String> mapimg = new HashMap<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_release); ButterKnife.bind(this); context = ReleaseActivity.this; initView(); } private void initView() { setTitle(toolbar, "编辑发帖", "发送"); //初始化发表按钮 titleRight.setTextColor(getResources().getColor(R.color.maintext2)); actionTextRight.setClickable(false); infoEt.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) { if (!TextUtils.isEmpty(infoEt.getText().toString())) { titleRight.setTextColor(getResources().getColor(R.color.black)); actionTextRight.setClickable(true); } else { titleRight.setTextColor(getResources().getColor(R.color.maintext2)); actionTextRight.setClickable(false); } } }); } /** * 创建/拼接html字符串 */ public String createHtmlStr(EditText editText) { html = new StringBuilder("");//String拼接不出长字符,用可变长度的String //构造html文件 html.append("<!DOCTYPE html>\n" + "<html>\n" + "\t<head>\n" + "\t\t<meta charset=\"UTF-8\">\n" + "\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, minimum-scale=0.5, maximum-scale=2.0, user-scalable=yes\" />\n" +//这里可以使html自动铺满手机屏幕 "\t\t<title>" + htmlTitle + "</title>\n" + "\t\t<style>\n" + "\t\t\tbody {\n" + "\t\t\t\twidth: 100%;\n" + "\t\t\t\theight: 100%;\n" + "\t\t\t\tmargin:0px;\n" + "\t\t\t}\n" + "\t\t\timg {\n" + "\t\t\t\tmax-width: 100%;\n" +//使图片刚好铺满屏幕,不超出屏幕 "\t\t\t}" + "\t\t</style>\n" + "\t</head>\n" + "\n" + "\t<body>\t"); // if (!TextUtils.isEmpty(titleEt.getText().toString().trim())) { // html.append("<" + titleTypeStr + "style=" + "'text-align: center;'" + ">" + titleEt.getText().toString().trim() + "</" + titleTypeStr + ">\n");//拼接标题---->默认h3 // } html.append("<div style=" + "'text-indent:2em;'" + ">" + editText.getText().toString() + "</div>"); html.append("</body>\n" + "</html>"); return html.toString(); } @OnClick({R.id.action_text_right, R.id.addimg_btn, R.id.loaction_btn}) public void onViewClicked(View view) { switch (view.getId()) { //发送按钮 case R.id.action_text_right: showLoading("正在提交"); //将带有<img>标签的和空格去除 String s = infoEt.getText().toString(); s = s.replaceAll("<[^<>]*>|\\s", ""); //得到<img>的内容 String reg = "<img.*?>"; Pattern pattern = Pattern.compile(reg); Matcher matcher = pattern.matcher(createHtmlStr(infoEt));//sendString为网页源码 //使用find()方法查找第一个匹配的对象 boolean result = matcher.find(); //使用循环找出 html里所有的img标签 while (result) { //继续查找下一个匹配对象 System.out.println("img标签===1" + matcher.group().substring(37, matcher.group().length() - 8)); imgsid += matcher.group().substring(37, matcher.group().length() - 8) + ";"; result = matcher.find(); } //提交数据 PostDynamic postDynamic = new PostDynamic(); postDynamic.setTextinfo(s); postDynamic.setContentinfo(createHtmlStr(infoEt)); postDynamic.setImagurls(imgsid); postDynamic.setTitle(titleEt.getText().toString()); postDynamic.setAddress(cityname.equals("不显示位置") ? "" : cityname); HttpRequest.intance().setObject(postDynamic); HttpRequest.intance().getRequest(context, HTTP.OBJECT, 1, Config.POST_DYNAMICADDDYNAMIC, this); break; //添加图片按钮 case R.id.addimg_btn: Log.e("TAG", "onViewClicked: " + infoEt.getText().toString()); setPhotoCount(1); //添加图片 new ActionSheetDialog(this).builder().setCancelable(true).setCanceledOnTouchOutside(true) .addSheetItem("从相册中选择", ActionSheetDialog.SheetItemColor.NORMAL, new ActionSheetDialog.OnSheetItemClickListener() { @Override public void onClick(int which) { getPhotoFromGallery(getTakePhoto(), 1000); } }) .addSheetItem("拍照", ActionSheetDialog.SheetItemColor.NORMAL, new ActionSheetDialog.OnSheetItemClickListener() { @Override public void onClick(int which) { getPhotoFromTake(getTakePhoto(), 1000); } }) .show(); break; //位置按钮 case R.id.loaction_btn: startActivityForResult(new Intent(this, NearAddressActivity.class), 1); break; } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == 1) { cityname = data.getStringExtra("cityname"); loaction_btn.setText(cityname); } } /** * 拍照返回成功 */ @Override public void takeSuccess(TResult result) { super.takeSuccess(result); ArrayList<TImage> images = result.getImages(); for (TImage p : images) { if (getPhotoCode() == 1000) { lastimg = p.getCompressPath(); Log.e("TAG", "takeSuccess: " + p.getCompressPath()); showLoading(); HttpRequest.intance().setParameter("port", p.getCompressPath()); //上传 HttpRequest.intance().getRequest(context, HTTP.FILE, 0, Config.POST_HEADIMG, this); } } } private Bitmap getimage(String srcPath) { BitmapFactory.Options newOpts = new BitmapFactory.Options(); //开始读入图片,此时把options.inJustDecodeBounds 设回true了 newOpts.inJustDecodeBounds = true; Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);//此时返回bm为空 //Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.qingfenglou);//此时返回bm为空 newOpts.inJustDecodeBounds = false; int w = newOpts.outWidth; int h = newOpts.outHeight; //现在主流手机比较多是800*480分辨率,所以高和宽我们设置为 float hh = 800f;//这里设置高度为800f float ww = 480f;//这里设置宽度为480f //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可 int be = 1;//be=1表示不缩放 if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放 be = (int) (newOpts.outWidth / ww); } else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放 be = (int) (newOpts.outHeight / hh); } if (be <= 0) be = 1; newOpts.inSampleSize = be;//设置缩放比例 //重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了 bitmap = BitmapFactory.decodeFile(srcPath, newOpts); //bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.qingfenglou); return compressImage(bitmap);//压缩好比例大小后再进行质量压缩 } private Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中 int options = 100; while (baos.toByteArray().length / 1024 > 100) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩 baos.reset();//重置baos即清空baos image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中 options -= 10;//每次都减少10 } ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中 Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片 return bitmap; } @Override public void onSucess(int requestCode, int flagCode, String content) { if (requestCode == 0) { BasePojo pojo = JSON.parseObject(content, BasePojo.class); if (pojo != null && pojo.getResultCode() == 0) { // TODO Auto-generated method stub Editable eb = infoEt.getEditableText(); eb.insert(infoEt.getSelectionStart(), "\r"); // 获得光标所在位置 int startPosition = infoEt.getSelectionStart(); SpannableString ss = new SpannableString("<div style=" + "'text-align: center;'" + ">" + "<img src='" + "http://120.26.69.155:4001" + "/" + pojo.getResultMessage() + ".jpg" + "' /></div>\n"); ss.setSpan(new ImageSpan(getimage(lastimg), ImageSpan.ALIGN_BASELINE), // ss.setSpan(new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE), 0, ss.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); // 插入图片 eb.insert(startPosition, ss); eb.insert(infoEt.getSelectionStart(), "\r"); cancelLoading(); } else { cancelLoading(); ToastUtils.showShort(context, pojo.getResultMessage()); } } if (requestCode == 1) { cancelLoading(); BasePojo pojo = JSON.parseObject(content, BasePojo.class); if (pojo != null && pojo.getResultCode() == 0) { ToastUtils.showShort(context, "发送成功"); finish(); } else { ToastUtils.showShort(context, pojo.getResultMessage()); } } } @Override public void onFail(int requestCode, int flagCode, String content) { cancelLoading(); } }最后是一张效果图