* 显示富文本
22
 */
23
public class RichTextView extends ScrollView {
24
    private static final String TAG = "RichTextView";
25
    private static final int EDIT_PADDING = 3; // edittext常规padding是10dp
26
27
    private int viewTagIndex = 1; // 新生的view都会打一个tag,对每个view来说,这个tag是唯一的。
28
    private LinearLayout allLayout; // 这个是所有子view的容器,scrollView内部的唯一一个ViewGroup
29
    private LayoutInflater inflater;
30
    private int editNormalPadding = 0; //
31
32
    public RichTextView(Context context) {
33
        this(context, null);
34
    }
35
36
    public RichTextView(Context context, AttributeSet attrs) {
37
        this(context, attrs, 0);
38
    }
39
40
    public RichTextView(Context context, AttributeSet attrs, int defStyleAttr) {
41
        super(context, attrs, defStyleAttr);
42
        inflater = LayoutInflater.from(context);
43
44
        // 1. 初始化allLayout
45
        allLayout = new LinearLayout(context);
46
        allLayout.setOrientation(LinearLayout.VERTICAL);
47
        //allLayout.setBackgroundColor(Color.WHITE);//去掉背景
48
        LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT,
49
                LayoutParams.WRAP_CONTENT);
50
        allLayout.setPadding(50, 15, 50, 15);//设置间距,防止生成图片时文字太靠边
51
        addView(allLayout, layoutParams);
52
53
        LinearLayout.LayoutParams firstEditParam = new LinearLayout.LayoutParams(
54
                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
55
        //editNormalPadding = dip2px(EDIT_PADDING);
56
        TextView firstText = createTextView("没有内容", dip2px(context, EDIT_PADDING));
57
        allLayout.addView(firstText, firstEditParam);
58
    }
59
60
    public int dip2px(Context context, float dipValue) {
61
        float m = context.getResources().getDisplayMetrics().density;
62
        return (int) (dipValue * m + 0.5f);
63
    }
64
65
    /**
66
     * 清除所有的view
67
     */
68
    public void clearAllLayout() {
69
        allLayout.removeAllViews();
70
    }
71
72
    /**
73
     * 获得最后一个子view的位置
74
     *
75
     * @return
76
     */
77
    public int getLastIndex() {
78
        int lastEditIndex = allLayout.getChildCount();
79
        return lastEditIndex;
80
    }
81
82
    /**
83
     * 生成文本输入框
84
     */
85
    public TextView createTextView(String hint, int paddingTop) {
86
        TextView textView = (TextView) inflater.inflate(R.layout.rich_textview, null);
87
        textView.setTag(viewTagIndex++);
88
        textView.setPadding(editNormalPadding, paddingTop, editNormalPadding, paddingTop);
89
        textView.setHint(hint);
90
        return textView;
91
    }
92
93
    /**
94
     * 生成图片View
95
     */
96
    private RelativeLayout createImageLayout() {
97
        RelativeLayout layout = (RelativeLayout) inflater.inflate(
98
                R.layout.edit_imageview, null);
99
        layout.setTag(viewTagIndex++);
100
        View closeView = layout.findViewById(R.id.image_close);
101
        closeView.setVisibility(GONE);
102
        return layout;
103
    }
104
105
    /**
106
     * 在特定位置插入EditText
107
     *
108
     * @param index   位置
109
     * @param editStr EditText显示的文字
110
     */
111
    public void addTextViewAtIndex(final int index, CharSequence editStr) {
112
        TextView textView = createTextView("", EDIT_PADDING);
113
        textView.setText(editStr);
114
115
        allLayout.addView(textView, index);
116
    }
117
118
    /**
119
     * 在特定位置添加ImageView
120
     */
121
    public void addImageViewAtIndex(final int index, String imagePath) {
122
        String width, height;
123
        String[] strarray = imagePath.split("\\&");
124
        final String path = strarray[0];
125
        width = strarray[1];
126
        if (width.contains(".")) {
127
            width = width.substring(0, width.indexOf("."));
128
        }
129
        height = strarray[2];
130
        if (height.contains(".")) {
131
            height = height.substring(0, height.indexOf("."));
132
        }
133
134
//        Bitmap bmp = BitmapFactory.decodeFile(imagePath);
135
136
        final RelativeLayout imageLayout = createImageLayout();
137
        DataImageView imageView = (DataImageView) imageLayout.findViewById(R.id.edit_imageView);
138
        RequestOptions options = new RequestOptions().centerCrop();
139
        Glide.with(getContext()).load(imagePath).apply(options).into(imageView);
140
        //imageView.setImageBitmap(bmp);//这里改用Glide加载图片
141
        //imageView.setBitmap(bmp);//这句去掉,保留下面的图片地址即可,优化图片占用
142
//        imageView.setAbsolutePath(imagePath);//保留这句,后面保存数据会用
143
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);//裁剪剧中
144
145
        // 调整imageView的高度
146
        int imageHeight = 500;
147
        int img_width = Integer.parseInt(width);
148
        int img_height = Integer.parseInt(height);
149
        if (width != null) {
150
            imageHeight = allLayout.getWidth() * img_height / img_width;
151
            // 使用之后,还是回收掉吧
152
//            bmp.recycle();
153
        }
154
//        Log.e(TAG, "addImageViewAtIndex_imageHeight: "+imageHeight );
155
        RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
156
                LayoutParams.MATCH_PARENT, imageHeight);
157
        lp.bottomMargin = 6;
158
        imageView.setLayoutParams(lp);
159
160
        allLayout.addView(imageLayout, index);
161
    }
162
163
    /**
164
     * 根据view的宽度,动态缩放bitmap尺寸
165
     *
166
     * @param width view的宽度
167
     */
168
    public Bitmap getScaledBitmap(String filePath, int width) {
169
        BitmapFactory.Options options = new BitmapFactory.Options();
170
        options.inJustDecodeBounds = true;
171
        BitmapFactory.decodeFile(filePath, options);
172
        int sampleSize = options.outWidth > width ? options.outWidth / width
173
                + 1 : 1;
174
        options.inJustDecodeBounds = false;
175
        options.inSampleSize = sampleSize;
176
        return BitmapFactory.decodeFile(filePath, options);
177
    }
178
179
}

+ 131 - 0
app/src/main/java/com/electric/chargingpile/view/xrichtext/SDCardUtil.java

@ -0,0 +1,131 @@
1
package com.electric.chargingpile.view.xrichtext;
2
3
import android.content.ContentResolver;
4
import android.content.Context;
5
import android.database.Cursor;
6
import android.graphics.Bitmap;
7
import android.net.Uri;
8
import android.os.Environment;
9
import android.provider.MediaStore;
10
11
import java.io.File;
12
import java.io.FileNotFoundException;
13
import java.io.FileOutputStream;
14
import java.io.IOException;
15
16
public class SDCardUtil {
17
    public static String SDCardRoot = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator;
18
19
    /**
20
     * 检查是否存在SDCard
21
     *
22
     * @return
23
     */
24
    public static boolean hasSdcard() {
25
        String state = Environment.getExternalStorageState();
26
        if (state.equals(Environment.MEDIA_MOUNTED)) {
27
            return true;
28
        } else {
29
            return false;
30
        }
31
    }
32
33
    /**
34
     * 获得文章图片保存路径
35
     *
36
     * @return
37
     */
38
    public static String getPictureDir() {
39
        String imageCacheUrl = SDCardRoot + "XRichText" + File.separator;
40
        File file = new File(imageCacheUrl);
41
        if (!file.exists())
42
            file.mkdir();  //如果不存在则创建
43
        return imageCacheUrl;
44
    }
45
46
    /**
47
     * 图片保存到SD卡
48
     *
49
     * @param bitmap
50
     * @return
51
     */
52
    public static String saveToSdCard(Bitmap bitmap) {
53
        String imageUrl = getPictureDir() + System.currentTimeMillis() + "-.jpeg";
54
        File file = new File(imageUrl);
55
        try {
56
            FileOutputStream out = new FileOutputStream(file);
57
            if (bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out)) {
58
                out.flush();
59
                out.close();
60
            }
61
        } catch (FileNotFoundException e) {
62
            e.printStackTrace();
63
        } catch (IOException e) {
64
            e.printStackTrace();
65
        }
66
        return file.getAbsolutePath();
67
    }
68
69
    /**
70
     * 保存到指定路径,笔记中插入图片
71
     *
72
     * @param bitmap
73
     * @param path
74
     * @return
75
     */
76
    public static String saveToSdCard(Bitmap bitmap, String path) {
77
        File file = new File(path);
78
        try {
79
            FileOutputStream out = new FileOutputStream(file);
80
            if (bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out)) {
81
                out.flush();
82
                out.close();
83
            }
84
        } catch (FileNotFoundException e) {
85
            e.printStackTrace();
86
        } catch (IOException e) {
87
            e.printStackTrace();
88
        }
89
        //System.out.println("文件保存路径:"+ file.getAbsolutePath());
90
        return file.getAbsolutePath();
91
    }
92
93
    /**
94
     * 删除文件
95
     **/
96
    public static void deleteFile(String filePath) {
97
        File file = new File(filePath);
98
        if (file.isFile() && file.exists())
99
            file.delete(); // 删除文件
100
    }
101
102
    /**
103
     * 根据Uri获取图片文件的绝对路径
104
     */
105
    public static String getFilePathByUri(Context context, final Uri uri) {
106
        if (null == uri) {
107
            return null;
108
        }
109
        final String scheme = uri.getScheme();
110
        String data = null;
111
        if (scheme == null) {
112
            data = uri.getPath();
113
        } else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
114
            data = uri.getPath();
115
        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
116
            Cursor cursor = context.getContentResolver().query(uri,
117
                    new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
118
            if (null != cursor) {
119
                if (cursor.moveToFirst()) {
120
                    int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
121
                    if (index > -1) {
122
                        data = cursor.getString(index);
123
                    }
124
                }
125
                cursor.close();
126
            }
127
        }
128
        return data;
129
    }
130
131
}

+ 24 - 0
app/src/main/res/layout/edit_imageview.xml

@ -0,0 +1,24 @@
1
<?xml version="1.0" encoding="utf-8"?>
2
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
    android:layout_width="match_parent"
4
    android:layout_height="wrap_content">
5
6
    <com.electric.chargingpile.view.xrichtext.DataImageView
7
        android:id="@+id/edit_imageView"
8
        android:layout_width="match_parent"
9
        android:layout_height="wrap_content"
10
        android:scaleType="fitXY" />
11
12
    <ImageView
13
        android:id="@+id/image_close"
14
        android:layout_width="50dp"
15
        android:layout_height="50dp"
16
        android:layout_alignParentRight="true"
17
        android:paddingLeft="20dp"
18
        android:paddingTop="5dp"
19
        android:paddingRight="5dp"
20
        android:paddingBottom="20dp"
21
        android:scaleType="fitXY"
22
        android:src="@drawable/icon_close" />
23
24
</RelativeLayout>

+ 9 - 0
app/src/main/res/layout/rich_edittext.xml

@ -0,0 +1,9 @@
1
<?xml version="1.0" encoding="utf-8"?>
2
<com.electric.chargingpile.view.xrichtext.DeletableEditText xmlns:android="http://schemas.android.com/apk/res/android"
3
    android:layout_width="match_parent"
4
    android:layout_height="wrap_content"
5
    android:background="@null"
6
    android:cursorVisible="true"
7
    android:lineSpacingExtra="8dp"
8
    android:textColor="#616161"
9
    android:textSize="16sp" />

+ 10 - 0
app/src/main/res/layout/rich_textview.xml

@ -0,0 +1,10 @@
1
<?xml version="1.0" encoding="utf-8"?>
2
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
3
    android:layout_width="match_parent"
4
    android:layout_height="wrap_content"
5
    android:background="@null"
6
    android:cursorVisible="true"
7
    android:lineSpacingExtra="8dp"
8
    android:textIsSelectable="true"
9
    android:textSize="16sp"
10
    android:textColor="#616161" />

Вход - Gogs: Go Git Service

Вход