美文网首页
Android中修改默认Textview和EditText的弹出

Android中修改默认Textview和EditText的弹出

作者: ZSGZ_AD | 来源:发表于2019-02-19 18:14 被阅读13次

    效果图


    image.png

    首先,给TextView添加属性:android:textIsSelectable="true"
    通过自定义textview的回调实现:
    Activity调用:

    public class Main1Activity extends AppCompatActivity {
        TextView tvToast;
        SelectableTextHelper mSelectableTextHelper;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            tvToast = (TextView) findViewById(R.id.tv_toast);
            mSelectableTextHelper = new SelectableTextHelper.Builder(tvToast)
                    .setSelectedColor(getResources().getColor(R.color.color_tv_theme_transparent15))
                    .setCursorHandleSizeInDp(20)
                    .setCursorHandleColor(getResources().getColor(R.color.colotBtnTheme))
                    .build();
            mSelectableTextHelper.setOnNotesClickListener(new OnNoteBookClickListener() {
                @Override
                public void onTextSelect(CharSequence charSequence) {
                  
                    String content = charSequence.toString();
                    Toast.makeText(Main1Activity.this, "点击的是:" + content, Toast.LENGTH_SHORT).show();
                }
            });
    
        }
    }
    

    自定义OnNoteBookClickListener,OnSelectListener和SelectionInfo

    interface  OnNoteBookClickListener {
         void onTextSelect(CharSequence mSelectionContent) ;
    }
    interface  OnNoteBookClickListener {
         void onTextSelect(CharSequence mSelectionContent) ;
    }
    class SelectionInfo {
        public String mSelectionContent;
        public int mStart;
        public int mEnd;
    }
    

    自定义SelectableTextHelper类

    public class SelectableTextHelper {
    
        private final static int DEFAULT_SELECTION_LENGTH = 1;
        private static final int DEFAULT_SHOW_DURATION = 100;
    
        private CursorHandle mStartHandle;
        private CursorHandle mEndHandle;
        private OperateWindow mOperateWindow;
        private SelectionInfo mSelectionInfo = new SelectionInfo();
        private OnSelectListener mSelectListener;
    
        private Context mContext;
        private TextView mTextView;
        private Spannable mSpannable;
    
        private int mTouchX;
        private int mTouchY;
    
        private int mSelectedColor;
        private int mCursorHandleColor;
        private int mCursorHandleSize;
        private BackgroundColorSpan mSpan;
        private boolean isHideWhenScroll;
        private boolean isHide = true;
    
        private ViewTreeObserver.OnPreDrawListener mOnPreDrawListener;
        ViewTreeObserver.OnScrollChangedListener mOnScrollChangedListener;
    
        public SelectableTextHelper(Builder builder) {
            mTextView = builder.mTextView;
            mContext = mTextView.getContext();
            mSelectedColor = builder.mSelectedColor;
            mCursorHandleColor = builder.mCursorHandleColor;
            mCursorHandleSize = TextLayoutUtil.dp2px(mContext, builder.mCursorHandleSizeInDp);
            init();
        }
    
        private void init() {
            mTextView.setText(mTextView.getText(), TextView.BufferType.SPANNABLE);
            mTextView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    showSelectView(mTouchX, mTouchY);
                    return true;
                }
            });
    
            mTextView.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    mTouchX = (int) event.getX();
                    mTouchY = (int) event.getY();
                    return false;
                }
            });
    
            mTextView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    resetSelectionInfo();
                    hideSelectView();
                }
            });
            mTextView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
                @Override
                public void onViewAttachedToWindow(View v) {
    
                }
    
                @Override
                public void onViewDetachedFromWindow(View v) {
                    destroy();
                }
            });
    
            mOnPreDrawListener = new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                    if (isHideWhenScroll) {
                        isHideWhenScroll = false;
                        postShowSelectView(DEFAULT_SHOW_DURATION);
                    }
                    return true;
                }
            };
            mTextView.getViewTreeObserver().addOnPreDrawListener(mOnPreDrawListener);
    
            mOnScrollChangedListener = new ViewTreeObserver.OnScrollChangedListener() {
                @Override
                public void onScrollChanged() {
                    if (!isHideWhenScroll && !isHide) {
                        isHideWhenScroll = true;
                        if (mOperateWindow != null) {
                            mOperateWindow.dismiss();
                        }
                        if (mStartHandle != null) {
                            mStartHandle.dismiss();
                        }
                        if (mEndHandle != null) {
                            mEndHandle.dismiss();
                        }
                    }
                }
            };
            mTextView.getViewTreeObserver().addOnScrollChangedListener(mOnScrollChangedListener);
    
            mOperateWindow = new OperateWindow(mContext);
        }
    
        private void postShowSelectView(int duration) {
            mTextView.removeCallbacks(mShowSelectViewRunnable);
            if (duration <= 0) {
                mShowSelectViewRunnable.run();
            } else {
                mTextView.postDelayed(mShowSelectViewRunnable, duration);
            }
        }
    
        private final Runnable mShowSelectViewRunnable = new Runnable() {
            @Override
            public void run() {
                if (isHide) {
    
                    return;
                }
                if (mOperateWindow != null) {
                    mOperateWindow.show();
                }
                if (mStartHandle != null) {
                    showCursorHandle(mStartHandle);
                }
                if (mEndHandle != null) {
                    showCursorHandle(mEndHandle);
                }
            }
        };
    
        private void hideSelectView() {
            isHide = true;
            if (mStartHandle != null) {
                mStartHandle.dismiss();
            }
            if (mEndHandle != null) {
                mEndHandle.dismiss();
            }
            if (mOperateWindow != null) {
                mOperateWindow.dismiss();
            }
        }
    
        private void resetSelectionInfo() {
            mSelectionInfo.mSelectionContent = null;
            if (mSpannable != null && mSpan != null) {
                mSpannable.removeSpan(mSpan);
                mSpan = null;
            }
        }
    
        private void showSelectView(int x, int y) {
            hideSelectView();
            resetSelectionInfo();
            isHide = false;
            if (mStartHandle == null) {
    
                mStartHandle = new CursorHandle(true);
            }
            if (mEndHandle == null) {
    
                mEndHandle = new CursorHandle(false);
            }
    
            int startOffset = TextLayoutUtil.getPreciseOffset(mTextView, x, y);
            int endOffset = startOffset + DEFAULT_SELECTION_LENGTH;
            if (mTextView.getText() instanceof Spannable) {
                mSpannable = (Spannable) mTextView.getText();
            }
            if (mSpannable == null || startOffset >= mTextView.getText().length()) {
                return;
            }
            selectText(startOffset, endOffset);
            showCursorHandle(mStartHandle);
            showCursorHandle(mEndHandle);
            mOperateWindow.show();
        }
    
        private void showCursorHandle(CursorHandle cursorHandle) {
            Layout layout = mTextView.getLayout();
            int offset = cursorHandle.isLeft ? mSelectionInfo.mStart : mSelectionInfo.mEnd;
            cursorHandle.show((int) layout.getPrimaryHorizontal(offset), layout.getLineBottom(layout.getLineForOffset(offset)));
        }
    
        private void selectText(int startPos, int endPos) {
            if (startPos != -1) {
                mSelectionInfo.mStart = startPos;
            }
            if (endPos != -1) {
                mSelectionInfo.mEnd = endPos;
            }
            if (mSelectionInfo.mStart > mSelectionInfo.mEnd) {
                int temp = mSelectionInfo.mStart;
                mSelectionInfo.mStart = mSelectionInfo.mEnd;
                mSelectionInfo.mEnd = temp;
            }
    
            if (mSpannable != null) {
                if (mSpan == null) {
                    mSpan = new BackgroundColorSpan(mSelectedColor);
                }
                mSelectionInfo.mSelectionContent = mSpannable.subSequence(mSelectionInfo.mStart, mSelectionInfo.mEnd).toString();
                mSpannable.setSpan(mSpan, mSelectionInfo.mStart, mSelectionInfo.mEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
                if (mSelectListener != null) {
                    mSelectListener.onTextSelected(mSelectionInfo.mSelectionContent);
                }
            }
        }
    
        OnNoteBookClickListener mNoteBookClickListener;
        public void setSelectListener(OnSelectListener selectListener) {
            mSelectListener = selectListener;
        }
    
        public void setOnNotesClickListener(OnNoteBookClickListener notesClickListener) {
            mNoteBookClickListener = notesClickListener;
    
        }
    
        public void destroy() {
            mTextView.getViewTreeObserver().removeOnScrollChangedListener(mOnScrollChangedListener);
            mTextView.getViewTreeObserver().removeOnPreDrawListener(mOnPreDrawListener);
            resetSelectionInfo();
            hideSelectView();
            mStartHandle = null;
            mEndHandle = null;
            mOperateWindow = null;
        }
    
        public void dismiss() {
            SelectableTextHelper.this.resetSelectionInfo();
            SelectableTextHelper.this.hideSelectView();
        }
    
        /**
         * Operate windows : copy, select all
         */
        private class OperateWindow {
    
            private PopupWindow mWindow;
            private int[] mTempCoors = new int[2];
    
            private int mWidth;
            private int mHeight;
    
            public OperateWindow(final Context context) {
                View contentView = LayoutInflater.from(context).inflate(R.layout.layout_operate_windows, null);
                contentView.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                        View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
                mWidth = contentView.getMeasuredWidth();
                mHeight = contentView.getMeasuredHeight();
                mWindow =
                        new PopupWindow(contentView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, false);
                mWindow.setClippingEnabled(false);
    
                contentView.findViewById(R.id.tv_copy).setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        ClipboardManager clip = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
                        clip.setPrimaryClip(
                                ClipData.newPlainText(mSelectionInfo.mSelectionContent, mSelectionInfo.mSelectionContent));
                        if (mSelectListener != null) {
                            mSelectListener.onTextSelected(mSelectionInfo.mSelectionContent);
                        }
                        SelectableTextHelper.this.resetSelectionInfo();
                        SelectableTextHelper.this.hideSelectView();
                    }
                });
                contentView.findViewById(R.id.tv_select_all).setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        hideSelectView();
                        selectText(0, mTextView.getText().length());
                        isHide = false;
                        showCursorHandle(mStartHandle);
                        showCursorHandle(mEndHandle);
                        mOperateWindow.show();
                    }
                });
                contentView.findViewById(R.id.tv_note).setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (mNoteBookClickListener != null) {
                            mNoteBookClickListener.onTextSelect(mSelectionInfo.mSelectionContent);
                        }
                        SelectableTextHelper.this.resetSelectionInfo();
                        SelectableTextHelper.this.hideSelectView();
                    }
                });
            }
    
            public void show() {
                mTextView.getLocationInWindow(mTempCoors);
                Layout layout = mTextView.getLayout();
                int posX = (int) layout.getPrimaryHorizontal(mSelectionInfo.mStart) + mTempCoors[0];
                int posY = layout.getLineTop(layout.getLineForOffset(mSelectionInfo.mStart)) + mTempCoors[1] - mHeight - 16;
                if (posX <= 0) {
    
                    posX = 16;
                }
                if (posY < 0) {
    
                    posY = 16;
                }
                if (posX + mWidth > TextLayoutUtil.getScreenWidth(mContext)) {
                    posX = TextLayoutUtil.getScreenWidth(mContext) - mWidth - 16;
                }
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    mWindow.setElevation(8f);
                }
                mWindow.showAtLocation(mTextView, Gravity.NO_GRAVITY, posX, posY);
            }
    
            public void dismiss() {
                mWindow.dismiss();
            }
    
            public boolean isShowing() {
                return mWindow.isShowing();
            }
        }
    
        private class CursorHandle extends View {
    
            private PopupWindow mPopupWindow;
            private Paint mPaint;
    
            private int mCircleRadius = mCursorHandleSize / 2;
            private int mWidth = mCircleRadius * 2;
            private int mHeight = mCircleRadius * 2;
            private int mPadding = 25;
            private boolean isLeft;
    
            public CursorHandle(boolean isLeft) {
                super(mContext);
                this.isLeft = isLeft;
                mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
                mPaint.setColor(mCursorHandleColor);
    
                mPopupWindow = new PopupWindow(this);
                mPopupWindow.setClippingEnabled(false);
                mPopupWindow.setWidth(mWidth + mPadding * 2);
                mPopupWindow.setHeight(mHeight + mPadding / 2);
                invalidate();
            }
    
            @Override
            protected void onDraw(Canvas canvas) {
                canvas.drawCircle(mCircleRadius + mPadding, mCircleRadius, mCircleRadius, mPaint);
                if (isLeft) {
                    canvas.drawRect(mCircleRadius + mPadding, 0, mCircleRadius * 2 + mPadding, mCircleRadius, mPaint);
                } else {
                    canvas.drawRect(mPadding, 0, mCircleRadius + mPadding, mCircleRadius, mPaint);
                }
            }
    
            private int mAdjustX;
            private int mAdjustY;
    
            private int mBeforeDragStart;
            private int mBeforeDragEnd;
    
            @Override
            public boolean onTouchEvent(MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        mBeforeDragStart = mSelectionInfo.mStart;
                        mBeforeDragEnd = mSelectionInfo.mEnd;
                        mAdjustX = (int) event.getX();
                        mAdjustY = (int) event.getY();
                        break;
                    case MotionEvent.ACTION_UP:
                    case MotionEvent.ACTION_CANCEL:
                        mOperateWindow.show();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        mOperateWindow.dismiss();
                        int rawX = (int) event.getRawX();
                        int rawY = (int) event.getRawY();
                        update(rawX + mAdjustX - mWidth, rawY + mAdjustY - mHeight);
                        break;
                }
                return true;
            }
    
            private void changeDirection() {
                isLeft = !isLeft;
                invalidate();
            }
    
            public void dismiss() {
                mPopupWindow.dismiss();
            }
    
            private int[] mTempCoors = new int[2];
    
            public void update(int x, int y) {
                mTextView.getLocationInWindow(mTempCoors);
                int oldOffset;
                if (isLeft) {
                    oldOffset = mSelectionInfo.mStart;
                } else {
                    oldOffset = mSelectionInfo.mEnd;
                }
    
                y -= mTempCoors[1];
    
                int offset = TextLayoutUtil.getHysteresisOffset(mTextView, x, y, oldOffset);
    
                if (offset != oldOffset) {
                    resetSelectionInfo();
                    if (isLeft) {
                        if (offset > mBeforeDragEnd) {
                            CursorHandle handle = getCursorHandle(false);
                            changeDirection();
                            handle.changeDirection();
                            mBeforeDragStart = mBeforeDragEnd;
                            selectText(mBeforeDragEnd, offset);
                            handle.updateCursorHandle();
                        } else {
                            selectText(offset, -1);
                        }
                        updateCursorHandle();
                    } else {
                        if (offset < mBeforeDragStart) {
                            CursorHandle handle = getCursorHandle(true);
                            handle.changeDirection();
                            changeDirection();
                            mBeforeDragEnd = mBeforeDragStart;
                            selectText(offset, mBeforeDragStart);
                            handle.updateCursorHandle();
                        } else {
                            selectText(mBeforeDragStart, offset);
                        }
                        updateCursorHandle();
                    }
                }
            }
    
            private void updateCursorHandle() {
                mTextView.getLocationInWindow(mTempCoors);
                Layout layout = mTextView.getLayout();
                if (isLeft) {
                    mPopupWindow.update((int) layout.getPrimaryHorizontal(mSelectionInfo.mStart) - mWidth + getExtraX(),
                            layout.getLineBottom(layout.getLineForOffset(mSelectionInfo.mStart)) + getExtraY(), -1, -1);
                } else {
                    mPopupWindow.update((int) layout.getPrimaryHorizontal(mSelectionInfo.mEnd) + getExtraX(),
                            layout.getLineBottom(layout.getLineForOffset(mSelectionInfo.mEnd)) + getExtraY(), -1, -1);
                }
            }
    
            public void show(int x, int y) {
                mTextView.getLocationInWindow(mTempCoors);
                int offset = isLeft ? mWidth : 0;
                mPopupWindow.showAtLocation(mTextView, Gravity.NO_GRAVITY, x - offset + getExtraX(), y + getExtraY());
            }
    
            public int getExtraX() {
                return mTempCoors[0] - mPadding + mTextView.getPaddingLeft();
            }
    
            public int getExtraY() {
                return mTempCoors[1] + mTextView.getPaddingTop();
            }
        }
    
        private CursorHandle getCursorHandle(boolean isLeft) {
            if (mStartHandle.isLeft == isLeft) {
                return mStartHandle;
            } else {
                return mEndHandle;
            }
        }
    
        public static class Builder {
            private TextView mTextView;
            private int mCursorHandleColor = 0xFF1379D6;
            private int mSelectedColor = 0xFFAFE1F4;
            private float mCursorHandleSizeInDp = 24;
    
            public Builder(TextView textView) {
                mTextView = textView;
            }
    
            public Builder setCursorHandleColor(@ColorInt int cursorHandleColor) {
                mCursorHandleColor = cursorHandleColor;
                return this;
            }
    
            public Builder setCursorHandleSizeInDp(float cursorHandleSizeInDp) {
                mCursorHandleSizeInDp = cursorHandleSizeInDp;
                return this;
            }
    
            public Builder setSelectedColor(@ColorInt int selectedBgColor) {
                mSelectedColor = selectedBgColor;
                return this;
            }
    
            public SelectableTextHelper build() {
                return new SelectableTextHelper(this);
            }
        }
    }
    

    TextLayoutUtil

    package com.example.acandroidlisten.textviewcheck;
    
    import android.content.Context;
    import android.text.Layout;
    import android.widget.TextView;
    
    public class TextLayoutUtil {
    
        public static int getScreenWidth(Context context) {
            return context.getResources().getDisplayMetrics().widthPixels;
        }
    
        public static int getPreciseOffset(TextView textView, int x, int y) {
            Layout layout = textView.getLayout();
            if (layout != null) {
                int topVisibleLine = layout.getLineForVertical(y);
                int offset = layout.getOffsetForHorizontal(topVisibleLine, x);
    
                int offsetX = (int) layout.getPrimaryHorizontal(offset);
    
                if (offsetX > x) {
                    return layout.getOffsetToLeftOf(offset);
                } else {
                    return offset;
                }
            } else {
                return -1;
            }
        }
    
        public static int getHysteresisOffset(TextView textView, int x, int y, int previousOffset) {
            final Layout layout = textView.getLayout();
            if (layout == null) return -1;
    
            int line = layout.getLineForVertical(y);
    
            // The "HACK BLOCK"S in this function is required because of how Android Layout for
            // TextView works - if 'offset' equals to the last character of a line, then
            //
            // * getLineForOffset(offset) will result the NEXT line
            // * getPrimaryHorizontal(offset) will return 0 because the next insertion point is on the next line
            // * getOffsetForHorizontal(line, x) will not return the last offset of a line no matter where x is
            // These are highly undesired and is worked around with the HACK BLOCK
            //
            // @see Moon+ Reader/Color Note - see how it can't select the last character of a line unless you move
            // the cursor to the beginning of the next line.
            //
            ////////////////////HACK BLOCK////////////////////////////////////////////////////
    
            if (isEndOfLineOffset(layout, previousOffset)) {
                // we have to minus one from the offset so that the code below to find
                // the previous line can work correctly.
                int left = (int) layout.getPrimaryHorizontal(previousOffset - 1);
                int right = (int) layout.getLineRight(line);
                int threshold = (right - left) / 2; // half the width of the last character
                if (x > right - threshold) {
                    previousOffset -= 1;
                }
            }
            ///////////////////////////////////////////////////////////////////////////////////
    
            final int previousLine = layout.getLineForOffset(previousOffset);
            final int previousLineTop = layout.getLineTop(previousLine);
            final int previousLineBottom = layout.getLineBottom(previousLine);
            final int hysteresisThreshold = (previousLineBottom - previousLineTop) / 2;
    
            // If new line is just before or after previous line and y position is less than
            // hysteresisThreshold away from previous line, keep cursor on previous line.
            if (((line == previousLine + 1) && ((y - previousLineBottom) < hysteresisThreshold)) || ((line == previousLine - 1) && ((
                    previousLineTop
                            - y) < hysteresisThreshold))) {
                line = previousLine;
            }
    
            int offset = layout.getOffsetForHorizontal(line, x);
    
            // This allow the user to select the last character of a line without moving the
            // cursor to the next line. (As Layout.getOffsetForHorizontal does not return the
            // offset of the last character of the specified line)
            //
            // But this function will probably get called again immediately, must decrement the offset
            // by 1 to compensate for the change made below. (see previous HACK BLOCK)
            /////////////////////HACK BLOCK///////////////////////////////////////////////////
            if (offset < textView.getText().length() - 1) {
                if (isEndOfLineOffset(layout, offset + 1)) {
                    int left = (int) layout.getPrimaryHorizontal(offset);
                    int right = (int) layout.getLineRight(line);
                    int threshold = (right - left) / 2; // half the width of the last character
                    if (x > right - threshold) {
                        offset += 1;
                    }
                }
            }
            //////////////////////////////////////////////////////////////////////////////////
    
            return offset;
        }
    
        private static boolean isEndOfLineOffset(Layout layout, int offset) {
            return offset > 0 && layout.getLineForOffset(offset) == layout.getLineForOffset(offset - 1) + 1;
        }
    
        public static int dp2px(Context context, float dpValue) {
            final float scale = context.getResources().getDisplayMetrics().density;
            return (int) (dpValue * scale + 0.5f);
        }
    }
    
    

    layout_operate_windows

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="#9e9e9e"
        tools:context=".MainActivity">
    
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:background="#9e9e9e">
    
            <Button
                android:id="@+id/tv_copy"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="#ffffff"
                android:text="拷贝" />
    
            <View
                android:layout_width="1dp"
                android:layout_height="match_parent"
                android:background="#ffffff" />
    
            <Button
                android:id="@+id/tv_select_all"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="#ffffff"
                android:text="全选" />
    
            <View
                android:layout_width="1dp"
                android:layout_height="match_parent"
                android:background="#ffffff" />
    
            <Button
                android:id="@+id/tv_note"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="#ffffff"
                android:text="笔记" />
    
        </LinearLayout>
     
    </LinearLayout>
    

    另外还有一种设置setCustomSelectionActionModeCallback()系统的方式
    参考及拓展阅读:
    https://www.jianshu.com/p/89970f098012
    https://blog.csdn.net/wapchief/article/details/83309961

    相关文章

      网友评论

          本文标题:Android中修改默认Textview和EditText的弹出

          本文链接:https://www.haomeiwen.com/subject/wivfyqtx.html