在MUPDF中选择文本并显示弹出式含义

4
我正在使用MUPDF库,并添加了手动缩放、缩小、评分和设置亮度等功能。现在我正在处理长按高亮文本并需要从我的数据库中显示含义的问题。我尝试用两个方法之一,一个是剪贴板,另一个是模拟Shift Held。下面的功能仅适用于Android ICS和JellyBean。有人能否建议我是否可以通过这些方法实现我想要的功能?因为在长按时,我无法捕获文本。建议将会很有帮助。
这是我的MUPDF活动:
      public void createUI(Bundle savedInstanceState) {
    if (core == null)
        return;
    // Now create the UI.
    // First create the document view making use of the ReaderView's internal
    // gesture recognition

    mDocView = new ReaderView(this) {

        private boolean showButtonsDisabled;

        public void onLongPress(MotionEvent e) {
            selectAndCopyText();
            //mDocView.getSelectedItem();
            //SelectText(mDocView);
            /*emulateShiftHeld(layout);
            clipboard =
                    (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
            clipboard.setText(clipboard.getText().toString());
            //layout.findAll(clipboard.getText().toString());
            //ClipMan.setPrimaryClip(clipboard);
            //String s = (String) clipboard.getText();
            //System.out.println("fsfasd"+ s);
            CharSequence pasteData="";
            ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);
            pasteData = item.getText();
            System.out.println("fsf"+pasteData);*/
            //ClipData data = ClipData.newPlainText("", "");
            ///System.out.println("sdf" + data);
            //copyClipboard();
        }

        @SuppressWarnings("deprecation")
        public void selectAndCopyText() {
             try {
                 Method m = WebView.class.getMethod("emulateShiftHeld", Boolean.TYPE); 
                    m.invoke(mDocView, false); 
                } catch (Exception e) {
                    e.printStackTrace();
                    // fallback
                    KeyEvent shiftPressEvent = new KeyEvent(0,0,
                         KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_SHIFT_LEFT,0,0);
                    shiftPressEvent.dispatch(this);
                }

        }

        public void startTextSelection() {
            try {
                WebView.class.getMethod("selectText").invoke(this);
            } catch (Exception e) {
                try {
                    WebView.class.getMethod("emulateShiftHeld").invoke(this);
                } catch (Exception e1) {
                    KeyEvent shiftPressEvent = new KeyEvent(0, 0,
                            KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_SHIFT_LEFT, 0, 0);
                    shiftPressEvent.dispatch(this);
                    Toast.makeText(getContext(), R.string.app_name, Toast.LENGTH_LONG).show();
                }
            }
        }
      // Stick the document view and the buttons overlay into a parent view
       //Embedding my reader view to webview
    layout = new WebView(this);
    layout.addView(mDocView);
    layout.addView(mButtonsView);

    layout.setBackgroundResource(R.drawable.tiled_background);

    //layout.setBackgroundResource(R.color.canvas);
    setContentView(layout);

这是我的阅读模式:

图片描述

    public class ReaderView extends AdapterView<Adapter>
                    implements GestureDetector.OnGestureListener,
                               ScaleGestureDetector.OnScaleGestureListener,
                               Runnable {
private static final int  MOVING_DIAGONALLY = 0;
private static final int  MOVING_LEFT       = 1;
private static final int  MOVING_RIGHT      = 2;
private static final int  MOVING_UP         = 3;
private static final int  MOVING_DOWN       = 4;

private static final int  FLING_MARGIN      = 100;
private static final int  GAP               = 20;
private static final int  SCROLL_SPEED      = 2;

private static final float MIN_SCALE        = 1.0f;
private static final float MAX_SCALE        = 5.0f;

private Adapter           mAdapter;
private int               mCurrent;    // Adapter's index for the current view
private boolean           mResetLayout;
private final SparseArray<View>
              mChildViews = new SparseArray<View>(3);
                       // Shadows the children of the adapter view
                       // but with more sensible indexing
private final LinkedList<View>
              mViewCache = new LinkedList<View>();
private boolean           mUserInteracting;  // Whether the user is interacting
private boolean           mScaling;    // Whether the user is currently pinch zooming
private float             mScale     = 1.0f;
private int               mXScroll;    // Scroll amounts recorded from events.
private int               mYScroll;    // and then accounted for in onLayout
private final GestureDetector
              mGestureDetector;
private final ScaleGestureDetector
              mScaleGestureDetector;
private final Scroller    mScroller;
private int               mScrollerLastX;
private int               mScrollerLastY;
private boolean           mScrollDisabled;

public ReaderView(Context context) {
    super(context);
    mGestureDetector = new GestureDetector(this);
    mScaleGestureDetector = new ScaleGestureDetector(context, this);
    mScroller        = new Scroller(context);
}

public ReaderView(Context context, AttributeSet attrs) {
    super(context, attrs);
    mGestureDetector = new GestureDetector(this);
    mScaleGestureDetector = new ScaleGestureDetector(context, this);
    mScroller        = new Scroller(context);
}

public ReaderView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    mGestureDetector = new GestureDetector(this);
    mScaleGestureDetector = new ScaleGestureDetector(context, this);
    mScroller        = new Scroller(context);
}

public int getDisplayedViewIndex(ToggleButton bookmark_page, String index_from) {
    if (index_from.equals("bookmark_button")) { System.out.println("View_if" + index_from);
        bookmark_page.setBackgroundResource(R.drawable.top3hover);
    } else { System.out.println("View_else" + index_from);
        bookmark_page.setBackgroundResource(R.drawable.top3);
    }
    return mCurrent;
}

public void setDisplayedViewIndex(int i) {
    if (0 <= i && i < mAdapter.getCount()) {
        mCurrent = i;
        onMoveToChild(i);
        mResetLayout = true;
        requestLayout();
    }
}

public void moveToNext() {
    View v = mChildViews.get(mCurrent+1);
    if (v != null)
        slideViewOntoScreen(v);
}

public void moveToPrevious() {
    View v = mChildViews.get(mCurrent-1);
    if (v != null)
        slideViewOntoScreen(v);
}

public void resetupChildren() {
    for (int i = 0; i < mChildViews.size(); i++)
        onChildSetup(mChildViews.keyAt(i), mChildViews.valueAt(i));
}

protected void onChildSetup(int i, View v) {}

protected void onMoveToChild(int i) {}

protected void onSettle(View v) {};

protected void onUnsettle(View v) {};

protected void onNotInUse(View v) {};

public View getDisplayedView() {
    return mChildViews.get(mCurrent);
}

public void run() {
    if (!mScroller.isFinished()) {
        mScroller.computeScrollOffset();
        int x = mScroller.getCurrX();
        int y = mScroller.getCurrY();
        mXScroll += x - mScrollerLastX;
        mYScroll += y - mScrollerLastY;
        mScrollerLastX = x;
        mScrollerLastY = y;
        requestLayout();
        post(this);
    }
    else if (!mUserInteracting) {
        // End of an inertial scroll and the user is not interacting.
        // The layout is stable
        View v = mChildViews.get(mCurrent);
        postSettle(v);
    }
}

public boolean onDown(MotionEvent arg0) {
    mScroller.forceFinished(true);
    return true;
}

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
        float velocityY) {
    if (mScrollDisabled)
        return true;

    View v = mChildViews.get(mCurrent);
    if (v != null) {
        Rect bounds = getScrollBounds(v);
        switch(directionOfTravel(velocityX, velocityY)) {
        case MOVING_LEFT:
            if (bounds.left >= 0) {
                // Fling off to the left bring next view onto screen
                View vl = mChildViews.get(mCurrent+1);

                if (vl != null) {
                    slideViewOntoScreen(vl);
                    return true;
                }
            }
            break;
        case MOVING_RIGHT:
            if (bounds.right <= 0) {
                // Fling off to the right bring previous view onto screen
                View vr = mChildViews.get(mCurrent-1);

                if (vr != null) {
                    slideViewOntoScreen(vr);
                    return true;
                }
            }
            break;
        }
        mScrollerLastX = mScrollerLastY = 0;
        // If the page has been dragged out of bounds then we want to spring back
        // nicely. fling jumps back into bounds instantly, so we don't want to use
        // fling in that case. On the other hand, we don't want to forgo a fling
        // just because of a slightly off-angle drag taking us out of bounds other
        // than in the direction of the drag, so we test for out of bounds only
        // in the direction of travel.
        //
        // Also don't fling if out of bounds in any direction by more than fling
        // margin
        Rect expandedBounds = new Rect(bounds);
        expandedBounds.inset(-FLING_MARGIN, -FLING_MARGIN);

        if(withinBoundsInDirectionOfTravel(bounds, velocityX, velocityY)
                && expandedBounds.contains(0, 0)) {
            mScroller.fling(0, 0, (int)velocityX, (int)velocityY, bounds.left, bounds.right, bounds.top, bounds.bottom);
            post(this);
        }
    }

    return true;
}

public void onLongPress(MotionEvent e) {
}

public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
        float distanceY) {
    if (!mScrollDisabled) {
        mXScroll -= distanceX;
        mYScroll -= distanceY;
        requestLayout();
    }
    return true;
}

public void onShowPress(MotionEvent e) {
}

public boolean onSingleTapUp(MotionEvent e) {
    return false;
}

public boolean onScale(ScaleGestureDetector detector) {
    float previousScale = mScale;
    mScale = Math.min(Math.max(mScale * detector.getScaleFactor(), MIN_SCALE), MAX_SCALE);
    float factor = mScale/previousScale;

    View v = mChildViews.get(mCurrent);
    if (v != null) {
        // Work out the focus point relative to the view top left
        int viewFocusX = (int)detector.getFocusX() - (v.getLeft() + mXScroll);
        int viewFocusY = (int)detector.getFocusY() - (v.getTop() + mYScroll);
        // Scroll to maintain the focus point
        mXScroll += viewFocusX - viewFocusX * factor;
        mYScroll += viewFocusY - viewFocusY * factor;
        requestLayout();
    }
    return true;
}

public boolean onScaleBegin(ScaleGestureDetector detector) {
    mScaling = true;
    // Ignore any scroll amounts yet to be accounted for: the
    // screen is not showing the effect of them, so they can
    // only confuse the user
    mXScroll = mYScroll = 0;
    // Avoid jump at end of scaling by disabling scrolling
    // until the next start of gesture
    mScrollDisabled = true;
    return true;
}

public void onScaleEnd(ScaleGestureDetector detector) {
    mScaling = false;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    //mScaleGestureDetector.onTouchEvent(event);

    if (!mScaling)
        mGestureDetector.onTouchEvent(event);

    if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
        mUserInteracting = true;
    }
    if (event.getActionMasked() == MotionEvent.ACTION_UP) {
        mScrollDisabled = false;
        mUserInteracting = false;

        View v = mChildViews.get(mCurrent);
        if (v != null) {
            if (mScroller.isFinished()) {
                // If, at the end of user interaction, there is no
                // current inertial scroll in operation then animate
                // the view onto screen if necessary
                slideViewOntoScreen(v);
            }

            if (mScroller.isFinished()) {
                // If still there is no inertial scroll in operation
                // then the layout is stable
                postSettle(v);
            }
        }
    }

    requestLayout();
    return true;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int n = getChildCount();
    for (int i = 0; i < n; i++)
        measureView(getChildAt(i));
}

@Override
protected void onLayout(boolean changed, int left, int top, int right,
        int bottom) {
    super.onLayout(changed, left, top, right, bottom);

    View cv = mChildViews.get(mCurrent);
    Point cvOffset;

    if (!mResetLayout) {
        // Move to next or previous if current is sufficiently off center
        if (cv != null) {
            cvOffset = subScreenSizeOffset(cv);
            // cv.getRight() may be out of date with the current scale
            // so add left to the measured width for the correct position
            if (cv.getLeft() + cv.getMeasuredWidth() + cvOffset.x + GAP/2 + mXScroll < getWidth()/2 && mCurrent + 1 < mAdapter.getCount()) {
                postUnsettle(cv);
                // post to invoke test for end of animation
                // where we must set hq area for the new current view
                post(this);

                mCurrent++;
                onMoveToChild(mCurrent);
            }

            if (cv.getLeft() - cvOffset.x - GAP/2 + mXScroll >= getWidth()/2 && mCurrent > 0) {
                postUnsettle(cv);
                // post to invoke test for end of animation
                // where we must set hq area for the new current view
                post(this);

                mCurrent--;
                onMoveToChild(mCurrent);
            }
        }

        // Remove not needed children and hold them for reuse
        int numChildren = mChildViews.size();
        int childIndices[] = new int[numChildren];
        for (int i = 0; i < numChildren; i++)
            childIndices[i] = mChildViews.keyAt(i);

        for (int i = 0; i < numChildren; i++) {
            int ai = childIndices[i];
            if (ai < mCurrent - 1 || ai > mCurrent + 1) {
                View v = mChildViews.get(ai);
                onNotInUse(v);
                mViewCache.add(v);
                removeViewInLayout(v);
                mChildViews.remove(ai);
            }
        }
    } else {
        mResetLayout = false;
        mXScroll = mYScroll = 0;

        // Remove all children and hold them for reuse
        int numChildren = mChildViews.size();
        for (int i = 0; i < numChildren; i++) {
            View v = mChildViews.valueAt(i);
            onNotInUse(v);
            mViewCache.add(v);
            removeViewInLayout(v);
        }
        mChildViews.clear();
        // post to ensure generation of hq area
        post(this);
    }

    // Ensure current view is present
    int cvLeft, cvRight, cvTop, cvBottom;
    boolean notPresent = (mChildViews.get(mCurrent) == null);
    cv = getOrCreateChild(mCurrent);
    // When the view is sub-screen-size in either dimension we
    // offset it to center within the screen area, and to keep
    // the views spaced out
    cvOffset = subScreenSizeOffset(cv);
    if (notPresent) {
        //Main item not already present. Just place it top left
        cvLeft = cvOffset.x;
        cvTop  = cvOffset.y;
    } else {
        // Main item already present. Adjust by scroll offsets
        cvLeft = cv.getLeft() + mXScroll;
        cvTop  = cv.getTop()  + mYScroll;
    }
    // Scroll values have been accounted for
    mXScroll = mYScroll = 0;
    cvRight  = cvLeft + cv.getMeasuredWidth();
    cvBottom = cvTop  + cv.getMeasuredHeight();

    if (!mUserInteracting && mScroller.isFinished()) {
        Point corr = getCorrection(getScrollBounds(cvLeft, cvTop, cvRight, cvBottom));
        cvRight  += corr.x;
        cvLeft   += corr.x;
        cvTop    += corr.y;
        cvBottom += corr.y;
    } else if (cv.getMeasuredHeight() <= getHeight()) {
        // When the current view is as small as the screen in height, clamp
        // it vertically
        Point corr = getCorrection(getScrollBounds(cvLeft, cvTop, cvRight, cvBottom));
        cvTop    += corr.y;
        cvBottom += corr.y;
    }

    cv.layout(cvLeft, cvTop, cvRight, cvBottom);

    if (mCurrent > 0) {
        View lv = getOrCreateChild(mCurrent - 1);
        Point leftOffset = subScreenSizeOffset(lv);
        int gap = leftOffset.x + GAP + cvOffset.x;
        lv.layout(cvLeft - lv.getMeasuredWidth() - gap,
                (cvBottom + cvTop - lv.getMeasuredHeight())/2,
                cvLeft - gap,
                (cvBottom + cvTop + lv.getMeasuredHeight())/2);
    }

    if (mCurrent + 1 < mAdapter.getCount()) {
        View rv = getOrCreateChild(mCurrent + 1);
        Point rightOffset = subScreenSizeOffset(rv);
        int gap = cvOffset.x + GAP + rightOffset.x;
        rv.layout(cvRight + gap,
                (cvBottom + cvTop - rv.getMeasuredHeight())/2,
                cvRight + rv.getMeasuredWidth() + gap,
                (cvBottom + cvTop + rv.getMeasuredHeight())/2);
    }

    invalidate();
}

@Override
public Adapter getAdapter() {
    return mAdapter;
}

@Override
public View getSelectedView() {
    throw new UnsupportedOperationException("Not supported");
}

@Override
public void setAdapter(Adapter adapter) {
    mAdapter = adapter;
    mChildViews.clear();
    removeAllViewsInLayout();
    requestLayout();
}

@Override
public void setSelection(int arg0) {
    throw new UnsupportedOperationException("Not supported");
}

private View getCached() {
    if (mViewCache.size() == 0)
        return null;
    else
        return mViewCache.removeFirst();
}

private View getOrCreateChild(int i) {
    View v = mChildViews.get(i);
    if (v == null) {
        v = mAdapter.getView(i, getCached(), this);
        addAndMeasureChild(i, v);
    }
    onChildSetup(i, v);

    return v;
}

private void addAndMeasureChild(int i, View v) {
    LayoutParams params = v.getLayoutParams();
    if (params == null) {
        params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    }
    addViewInLayout(v, 0, params, true);
    mChildViews.append(i, v); // Record the view against it's adapter index
    measureView(v);
}

private void measureView(View v) {
    // See what size the view wants to be
    v.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
    // Work out a scale that will fit it to this view
    float scale = Math.min((float)getWidth()/(float)v.getMeasuredWidth(),
                (float)getHeight()/(float)v.getMeasuredHeight());
    // Use the fitting values scaled by our current scale factor
    v.measure(View.MeasureSpec.EXACTLY | (int)(v.getMeasuredWidth()*scale*mScale),
            View.MeasureSpec.EXACTLY | (int)(v.getMeasuredHeight()*scale*mScale));
}

private Rect getScrollBounds(int left, int top, int right, int bottom) {
    int xmin = getWidth() - right;
    int xmax = -left;
    int ymin = getHeight() - bottom;
    int ymax = -top;

    // In either dimension, if view smaller than screen then
    // constrain it to be central
    if (xmin > xmax) xmin = xmax = (xmin + xmax)/2;
    if (ymin > ymax) ymin = ymax = (ymin + ymax)/2;

    return new Rect(xmin, ymin, xmax, ymax);
}

private Rect getScrollBounds(View v) {
    // There can be scroll amounts not yet accounted for in
    // onLayout, so add mXScroll and mYScroll to the current
    // positions when calculating the bounds.
    return getScrollBounds(v.getLeft() + mXScroll,
                           v.getTop() + mYScroll,
                           v.getLeft() + v.getMeasuredWidth() + mXScroll,
                           v.getTop() + v.getMeasuredHeight() + mYScroll);
}

private Point getCorrection(Rect bounds) {
    return new Point(Math.min(Math.max(0,bounds.left),bounds.right),
                     Math.min(Math.max(0,bounds.top),bounds.bottom));
}

private void postSettle(final View v) {
    // onSettle and onUnsettle are posted so that the calls
    // wont be executed until after the system has performed
    // layout.
    post (new Runnable() {
        public void run () {
            onSettle(v);
        }
    });
}

private void postUnsettle(final View v) {
    post (new Runnable() {
        public void run () {
            onUnsettle(v);
        }
    });
}

private void slideViewOntoScreen(View v) {
    Point corr = getCorrection(getScrollBounds(v));
    if (corr.x != 0 || corr.y != 0) {
        mScrollerLastX = mScrollerLastY = 0;
        mScroller.startScroll(0, 0, corr.x, corr.y, 400);
        post(this);
    }
}

private Point subScreenSizeOffset(View v) {
    return new Point(Math.max((getWidth() - v.getMeasuredWidth())/2, 0),
            Math.max((getHeight() - v.getMeasuredHeight())/2, 0));
}

private static int directionOfTravel(float vx, float vy) {
    if (Math.abs(vx) > 2 * Math.abs(vy))
        return (vx > 0) ? MOVING_RIGHT : MOVING_LEFT;
    else if (Math.abs(vy) > 2 * Math.abs(vx))
        return (vy > 0) ? MOVING_DOWN : MOVING_UP;
    else
        return MOVING_DIAGONALLY;
}

private static boolean withinBoundsInDirectionOfTravel(Rect bounds, float vx, float vy) {
    switch (directionOfTravel(vx, vy)) {
    case MOVING_DIAGONALLY: return bounds.contains(0, 0);
    case MOVING_LEFT:       return bounds.left <= 0;
    case MOVING_RIGHT:      return bounds.right >= 0;
    case MOVING_UP:         return bounds.top <= 0;
    case MOVING_DOWN:       return bounds.bottom >= 0;
    default: throw new NoSuchElementException();
    }
}

}

1个回答

0
在 Reader 类中,创建本地广播并在主 Activity 中实现它。 public void onLongPress(MotionEvent e) {
    Intent next = new Intent(StringConstant.SEARCH_WORD);
    next.putExtra(StringConstant.DOUBLE_TAP_PDF, "true");
    LocalBroadcastManager.getInstance(mContext).sendBroadcast(next);

}

这是您的广播接收器

private BroadcastReceiver mPdfDoubleClickedReciever = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {

        if (intent != null) {
            Log.e("", "mPdfDoubleClickedReciever called");
            hideEditedNotes();
            MuPDFView pageView = (MuPDFView) mDocView.getDisplayedView();
            boolean success = false;
            if (pageView != null)
                success = pageView.copySelection();
            mTopBarMode = TopBarMode.Main;
            // showInfo(success ?
            // getString(R.string.copied_to_clipboard)
            // : getString(R.string.no_text_selected));

            ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
            selectedClipboardText = "";
            selectedClipboardText = (String) clipboard.getText();

            // Do task here

        }

    }
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接