我正在使用 MUPDF 库,并添加了手动放大、缩小、评级、设置亮度的功能。现在我正在长按突出显示的文本,我必须从我的数据库中显示含义。我正在尝试做两件事,一是剪贴板或 emulateShiftHeld,以下功能仅适用于 android ICS 和 JellyBean。任何机构都可以建议我正在尝试的任何一件事是否适用于此功能。因为在长按上我无法捕获文本。建议会有所帮助。

这个 id 我的 MUPDF Activity :

      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);

}

这是我的读者 View :
    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();
    }
}

}

最佳答案

在 Reader Class 中,进行 localbroadcast 并在您的主 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

        }

    }
};

关于android - 选择文本并在 MUPDF 中弹出显示含义,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17856759/

10-13 02:03