富文本編輯器,如圖:
Android 富文本編輯器實現思路:
默認狀態下編輯器顯示一個EditText,點擊圖片,選擇插入本地圖片或者拍照圖片.
插入圖片時,如果當前位置後面沒有文字,則直接插入圖片,如果後面有文字,那麼就將後面的文字截取出來,先插入這張圖片,再新增一個EditText顯示截取的文字;
刪除信息時需要判斷幾種情況:
1.前面是文字,直接刪除文字
2.當這個EditText中的已經沒有信息了,繼續點刪除時,如果前面是圖片,那麼先刪除當前這個EditText然後刪除圖片
3.如果前面是文字,那麼先刪除當前這個EditText,然後將光標置於前面EditText的最後一個
大體思路如上,下面看具體代碼:
首先這個RichTextEditor集成自LinearLayout,
添加默認的EditText:
<span style="font-family:SimHei;font-size:18px;"> LayoutParams firstEditParam = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
EditText firstEdit = createEditText("", dip2px(EDIT_FIRST_PADDING_TOP));
allLayout.addView(firstEdit, firstEditParam);</span>
添加一張本地圖片:
<span style="font-family:SimHei;font-size:18px;"> /**
* 插入一張圖片
*/
private void insertImage(Bitmap bitmap, String imagePath) {
String lastEditStr = lastFocusEdit.getText().toString();
int cursorIndex = lastFocusEdit.getSelectionStart();
String editStr1 = lastEditStr.substring(0, cursorIndex).trim();
int lastEditIndex = allLayout.indexOfChild(lastFocusEdit);
lastFocusEdit.setText(editStr1);
String editStr2 = lastEditStr.substring(cursorIndex).trim();
addEditTextAtIndex(lastEditIndex + 1, editStr2);
addImageViewAtIndex(lastEditIndex + 1, bitmap, imagePath);
lastFocusEdit.requestFocus();
lastFocusEdit.setSelection(editStr1.length(), editStr1.length());
hideKeyBoard();
}</span>
先得到當前EditText中的文字信息,接下來判斷光標所處位置,如果不是在文字的最後,則將文字拆分開,添加一個新的EditText並插入圖片
<span style="font-family:SimHei;font-size:18px;">/**
* 在特定位置添加ImageView
*/
private void addImageViewAtIndex(final int index, Bitmap bmp,
String imagePath) {
final RelativeLayout imageLayout = createImageLayout();
DataImageView imageView = (DataImageView) imageLayout
.findViewById(R.id.edit_imageView);
imageView.setImageBitmap(bmp);
imageView.setBitmap(bmp);
imageView.setAbsolutePath(imagePath);
// 調整imageView的高度
int imageHeight = getWidth() * bmp.getHeight() / bmp.getWidth();
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
LayoutParams.MATCH_PARENT, imageHeight);
imageView.setLayoutParams(lp);
// onActivityResult無法觸發動畫,此處post處理
allLayout.postDelayed(new Runnable() {
@Override
public void run() {
allLayout.addView(imageLayout, index);
}
}, 200);
}</span>
<span style="font-family:SimHei;font-size:18px;">/**
* 生成圖片View
*/
private RelativeLayout createImageLayout() {
RelativeLayout layout = (RelativeLayout) inflater.inflate(
R.layout.richtextedit_imageview, null);
layout.setTag(viewTagIndex++);
View closeView = layout.findViewById(R.id.image_close);
closeView.setTag(layout.getTag());
closeView.setOnClickListener(btnListener);
return layout;
}
</span>
先生成自定義的圖片佈局,然後找到裏面的DataImageView,這個類繼承ImageView,額外提供設置圖片的絕對地址的方法等,然後將圖片和圖片地址設置到這個DataImageView中,最後添加到這個LinearLayout中,這裏通過延遲UI操作添加.
在實際的項目中,不僅需要我們發送富文本信息,同樣也需要我們顯示並修改從服務器端傳過來的富文本信息,下面看一下添加一張網絡圖片:
<span style="font-family:SimHei;font-size:18px;"> /**
* 插入網絡圖片
*
* @param url
*/
public void insertImageByURL(String url) {
if (url == null)
return;
final RelativeLayout imageLayout = createImageLayout();
final DataImageView imageView = (DataImageView) imageLayout
.findViewById(R.id.edit_imageView);
imageView.setImageResource(R.drawable.logo);
imageView.setScaleType(ImageView.ScaleType.CENTER);
allLayout.addView(imageLayout);
addEditTextAtIndex(-1, "");
ImageLoader.getInstance().displayImage(url, imageView,
new SimpleImageLoadingListener() {
@Override
public void onLoadingComplete(String imageUri, View view,
Bitmap loadedImage) {
String path = fileUtils.savaRichTextImage(imageUri,
loadedImage);
imageView.setImageBitmap(loadedImage);
imageView.setBitmap(loadedImage);
imageView.setAbsolutePath(path);
int imageHeight = getWidth() * loadedImage.getHeight()
/ loadedImage.getWidth();
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
LayoutParams.MATCH_PARENT, imageHeight);
imageView.setLayoutParams(lp);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
}
});
}</span>
這個方法用於顯示網絡返回的富文本信息,一般返回的富文本信息中的圖片信息多以URL連接形式返回,這裏使用ImageLoader類加載圖片,並將加載出來的圖片加載到緩存中,同時也將圖片的地址添加到DataImageView中.
返回富文本中的信息:
<span style="font-family:SimHei;font-size:18px;">public HashMap<String, Object> getRichEditData() {
HashMap<String, Object> data = new HashMap<>();
StringBuilder editTextSB = new StringBuilder();
List<String> imgUrls = new ArrayList<>();
char separator = 26;
int num = allLayout.getChildCount();
for (int index = 0; index < num; index++) {
View itemView = allLayout.getChildAt(index);
if (itemView instanceof EditText) {
EditText item = (EditText) itemView;
editTextSB.append(item.getText().toString());
} else if (itemView instanceof RelativeLayout) {
DataImageView item = (DataImageView) itemView
.findViewById(R.id.edit_imageView);
imgUrls.add(item.getAbsolutePath());
editTextSB.append(separator);
}
}
data.put("text", editTextSB);
data.put("imgUrls", imgUrls);
return data;
}</span>
遍歷LinearLayout中的元素,若爲EditText則獲取文字信息,若爲ImageView,則獲取圖片地址.
更多的代碼實現邏輯就在項目中查找吧.