Android EditText图文混排
程序员文章站
2022-04-25 09:05:26
...
关于图文混排,一些功能要求接受用户的反馈,发布等。。。。一些功能,来满足公司要求,对于一些光标的要求,图片是否插入到相对应的位置,一定要有一个清楚的认识,虽然一些工具类是别人写的,但在用的时候自己看一下了解了再用,别盲目的使用就行,接下来为大家贴出一些简单易理解的代码,希望能帮到大家。
下面是效果图:
布局我就用了一个Editext和button
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<com.example.admin.testdemo.PictureTextEditorView
android:id="@+id/edit_text"
android:layout_width="match_parent"
android:layout_height="500dp"
android:background="@null"
android:gravity="top"
android:hint="分享你想说的..."
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:includeFontPadding="false"
android:paddingTop="10dp"
android:lineSpacingExtra="3dp"
android:textColor="#3a3a3a"
android:textColorHint="#999999"
android:textSize="14sp"
/>
<Button
android:id="@+id/button_add_picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点我插图"
/>
</LinearLayout>
下面是一个工具类,继承了EditText
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.text.Editable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ImageSpan;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.widget.EditText;
import java.util.ArrayList;
import java.util.List;
@SuppressLint("AppCompatCustomView")
public class PictureTextEditorView extends EditText {
private final String TAG = "PictureTextEditorView";
private Context mContext;
private List<String> mContentList;
public static final String mBitmapTag = "☆";
private String mNewLineTag = "\n";
public PictureTextEditorView(Context context) {
super(context);
init(context);
}
public PictureTextEditorView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public PictureTextEditorView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
mContext = context;
mContentList = getmContentList();
insertData();
}
// 根据路径获得图片并压缩,返回bitmap用于显示
public Bitmap getSmallBitmap(String filePath, int reqWidth, int reqHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);
DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
int w_screen = dm.widthPixels;
int w_width = w_screen/3;
int b_width = bitmap.getWidth();
int b_height = bitmap.getHeight();
int w_height = w_screen * b_height / b_width/3;
// int w_height = w_width * b_height / b_width;
bitmap = Bitmap.createScaledBitmap(bitmap, w_width, w_height, false);
return bitmap;
}
//计算图片的缩放值
public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
/**
* 插入图片
*
* @param bitmap
* @param path
* @return
*/
private SpannableString insertBitmap(String path, Bitmap bitmap) {
Editable edit_text = getEditableText();
int index = getSelectionStart(); // 获取光标所在位置
//插入换行符,使图片单独占一行
SpannableString newLine = new SpannableString("\n");
edit_text.insert(index, newLine);//插入图片前换行
// 创建一个SpannableString对象,以便插入用ImageSpan对象封装的图像
path = mBitmapTag + path + mBitmapTag;
SpannableString spannableString = new SpannableString(path);
// 根据Bitmap对象创建ImageSpan对象
ImageSpan imageSpan = new ImageSpan(mContext, bitmap);
// 用ImageSpan对象替换你指定的字符串
spannableString.setSpan(imageSpan, 0, path.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// 将选择的图片追加到EditText中光标所在位置
if (index < 0 || index >= edit_text.length()) {
edit_text.append(spannableString);
} else {
edit_text.insert(index, spannableString);
}
edit_text.insert(index, newLine);//插入图片后换行
return spannableString;
}
/**
* 设置数据
*/
private void insertData() {
if (mContentList.size() > 0) {
for (String str : mContentList) {
if (str.indexOf(mBitmapTag) != -1) {//判断是否是图片地址
String path = str.replace(mBitmapTag, "");//还原地址字符串
Bitmap bitmap = getSmallBitmap(path, 480, 800);
//插入图片
insertBitmap(path, bitmap);
} else {
//插入文字
SpannableString ss = new SpannableString(str);
append(ss);
}
}
}
}
/**
* 用集合的形式获取控件里的内容
*
* @return
*/
public List<String> getmContentList() {
if (mContentList == null) {
mContentList = new ArrayList<String>();
}
String content = getText().toString().replaceAll(mNewLineTag, "");
if (content.length() > 0 && content.contains(mBitmapTag)) {
String[] split = content.split("☆");
mContentList.clear();
for (String str : split) {
mContentList.add(str);
}
} else {
mContentList.add(content);
}
return mContentList;
}
float oldY = 0;
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
oldY = event.getY();
requestFocus();
break;
case MotionEvent.ACTION_MOVE:
float newY = event.getY();
if (Math.abs(oldY - newY) > 20) {
clearFocus();
}
break;
case MotionEvent.ACTION_UP:
break;
default:
break;
}
return super.onTouchEvent(event);
}
/**
* 插入图片
*
* @param path
*/
public void insertBitmap(String path) {
Bitmap bitmap = getSmallBitmap(path, 480, 800);
insertBitmap(path, bitmap);
}
}
在下面就是怎么实现的了,我这里只调用本地相机,你要是用手机相机拍照,把拍照的路径放里面就行了
import android.app.Activity;
import android.content.ContentUris;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.support.annotation.RequiresApi;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
private static final int LOCAL_IMAGE_CODE = 888;
private PictureTextEditorView mEditText;
private Button mButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mEditText = (PictureTextEditorView) findViewById(R.id.edit_text);
mButton = (Button) findViewById(R.id.button_add_picture);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
selectPicFromLocal(MainActivity.this, 888);//获取手机本地图片的代码,大家可以自行实现
}
});
mEditText.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) {
Log.i("EditActivity", mEditText.getmContentList().toString());
}
@Override
public void afterTextChanged(Editable editable) {
}
});
}
public void selectPicFromLocal(MainActivity mContext, int LOCAL_IMAGE_CODE) {
// intent.setType(“image/*”); //选择图片
// intent.setType(“audio/*”); //选择音频
// intent.setType(“video/*”); //选择视频 (mp4 3gp 是android支持的视频格式)
// intent.setType(“video/*;image/*”);//同时选择视频和图片
Intent intent = new Intent();
String IMAGE_TYPE = "image/*";
intent.setType(IMAGE_TYPE);
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent, LOCAL_IMAGE_CODE);
}
//4.4之前
public void handleImageBeforeKitKat(Intent data) {
Uri uri = data.getData();
String imagePath = getImagePath(uri, null);
Log.d("Uri1", imagePath);
mEditText.insertBitmap(imagePath);
}
//4.4之后
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void handleImageOnKitKat(Intent data) {
String imagePath = null;
Uri uri = data.getData();
if (DocumentsContract.isDocumentUri(this, uri)) {
String docId = DocumentsContract.getDocumentId(uri);
if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
//解析出数字格式的ID
String id = docId.split(":")[1];
//获取相册路径
String selection = MediaStore.Images.Media._ID + "=" + id;
imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);
} else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {
Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://download/public_downloads"), Long.valueOf(docId));
imagePath = getImagePath(contentUri, null);
}
} else if ("content".equalsIgnoreCase(uri.getScheme())) {
imagePath = getImagePath(uri, null);
Log.d("Uri1", imagePath);
}
mEditText.insertBitmap(imagePath);
}
private String getImagePath(Uri uri, String selection) {
String path = null;
Cursor cursor = getContentResolver().query(uri, null, selection, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
}
cursor.close();
}
return path;
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case LOCAL_IMAGE_CODE:
if (data != null) {
if (resultCode == RESULT_OK) {
if (Build.VERSION.SDK_INT >= 19) {
handleImageOnKitKat(data);
} else {
handleImageBeforeKitKat(data);
}
}
}
break;
default:
break;
}
}
}
}
这样,一个简单的功能就实现了,如果要不理解的可以给我留言哦
上一篇: git仓库 与vscode连接 与ssh**的相关配置
下一篇: 图文混排