android - वेबविय टेक्स्ट चयन के लिए एक कस्टम प्रासंगिक ऐक्शन बार का उपयोग करें




webview touch-event (2)

जिस तरह से मैंने ऐसा कुछ किया था, वह केवल टचलाइस्टनर को ओवरराइड करना था और जब वेबव्यू लंबे समय से दबाया गया था और जो कुछ मैं वहां से चाहता था, तो पता लगाने के लिए एक जेस्चर डिटेक्टर को खोलना था। यहां कुछ नमूना कोड है जो आपको वेबविज़ में पाठ-चयन का त्याग किए बिना लंबी-प्रेस घटनाओं को पकड़ने की अनुमति देता है। उम्मीद है कि यह मदद करता है

@Override
protected void onCreate(Bundle savedInstanceState) {
    WebView mWebView = (WebView) findViewById(R.id.myWebView);
    GestureDetector mGestureDetector = new GestureDetector(this, new CustomGestureListener());
    mWebView.setOnTouchListener(new OnTouchListener(){
        @Override
        public boolean onTouch(View view, MotionEvent arg1) {

            //Suggestion #1 - this just lets the touch to be handled by the system but allows you to detect long presses
            mGestureDetector.onTouchEvent(arg1);
            return false;

            //Suggestion #2 - this code will only let the touch be handled by the system if you don't detect a long press
            return mGestureDetector.onTouchEvent(arg1);
        }
    });
}

private class CustomGestureListener extends SimpleOnGestureListener {

    @Override
    public void onLongPress(MotionEvent e) {
        //do stuff
    }

}

मैंने इस गाइड का उपयोग Google से किया है और इस ट्यूटोरियल को अपना प्रासंगिक एक्शन बार बनाने के लिए इस्तेमाल किया है।

private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {

    // Called when the action mode is created; startActionMode() was called
    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        // Inflate a menu resource providing context menu items
        MenuInflater inflater = mode.getMenuInflater();
        inflater.inflate(R.menu.annotation_menu, menu);
        return true;
    }

    // Called each time the action mode is shown.
    // Always called after onCreateActionMode, but
    // may be called multiple times if the mode is invalidated.
    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false; // Return false if nothing is done
    }

    // Called when the user selects a contextual menu item
    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        switch (item.getItemId()) {
            case R.id.custom_button:
                // do some stuff
                break;
            case R.id.custom_button2:
                // do some other stuff
                break;
            default:
                // This essentially acts as a catch statement
                // If none of the other cases are true, return false
                // because the action was not handled
                return false;
        }
        finish(); // An action was handled, so close the CAB
        return true;
    }

    // Called when the user exits the action mode
    @Override
    public void onDestroyActionMode(ActionMode mode) {
        mActionMode = null;
    }
};

यह मेनू प्रदर्शित होने के लिए डिज़ाइन किया गया है जब उपयोगकर्ता टेक्स्ट का चयन करता है, इसलिए यह मूल कॉपी / पेस्ट मेनू को ओवरराइड करता है। अब मैं अपने मुद्दे पर आ गया

क्योंकि मैं पाठ चयन के लिए कार्यों को ओवरराइड कर रहा हूं, मैंने एक LongClickListener लिए एक LongClickListener को भी जोड़ा और onLongClick(View v) विधि को लागू किया है ताकि मैं उपयोगकर्ताओं को चयन कर onLongClick(View v)

    myWebView.setOnLongClickListener(new View.OnLongClickListener() {

        @Override
        public boolean onLongClick(View v) {
            if (mActionMode != null) {
                return false;
            }

            mActionMode = startActionMode(mActionModeCallback);
            v.setSelected(true);
            return true;
        }
    });

जब मैं लंबे समय से क्लिक करता हूं, तो मेरा कस्टम मेनू दिखाई देता है, लेकिन कोई भी टेक्स्ट हाइलाइट नहीं किया जाता है।
मुझे पाठ चयन कार्यप्रणाली की आवश्यकता है; इसके बिना, मेरा मेनू व्यर्थ है

मैं onLongClick(View v) ओवरराइड कैसे कर सकता हूं, लेकिन एंड्रॉइड द्वारा प्रदान की जाने वाली पाठ चयन को बनाए रखना चाहिए?
अगर यह संभव नहीं है, तो मैं कहीं और startActionMode(mActionModeCallback) को कॉल करने के लिए कॉल कर सकता हूं ताकि पाठ को सामान्य के रूप में चुना जाए, लेकिन मेरा कस्टम मेनू भी दिखाई देगा?
अगर उनमें से कोई भी संभव नहीं है ... सहायता


वहाँ एक आसान तरीका है! नीचे अपडेट देखें: डी

पूर्णता के लिए, यहां बताया गया है कि मैंने इस समस्या को कैसे तय किया है:

मैंने इस उत्तर के अनुसार सुझाव का पालन किया, ओवरराइड्स कोड से अधिक बारीकी से मिलान करने के लिए थोड़ा और अधिक tweaking:

public class MyWebView extends WebView {

    private ActionMode mActionMode;
    private mActionMode.Callback mActionModeCallback;

    @Override
    public ActionMode startActionMode(Callback callback) {
        ViewParent parent = getParent();
        if (parent == null) {
            return null;
        }
        mActionModeCallback = new CustomActionModeCallback();
        return parent.startActionModeForChild(this, mActionModeCallback);
    }
}

मूलतः, यह आपके ऐडवर्ड्स सीएबी के बजाए प्रदर्शित होने के लिए आपके कस्टमाइज्ड सीएबी को मजबूर करता है। अब आपको अपने कॉलबैक को संशोधित करना होगा ताकि पाठ हाइलाइट सीएबी के साथ दूर हो जाए:

public class MyWebView extends WebView {
    ...
    private class CustomActionModeCallback implements ActionMode.Callback {
        ...
        // Everything up to this point is the same as in the question

        // Called when the user exits the action mode
        @Override
        public void onDestroyActionMode(ActionMode mode) {
            clearFocus(); // This is the new code to remove the text highlight
             mActionMode = null;
        }
    }
}

यही सब है इसके लिए। ध्यान रखें कि जब तक आप MyWebView साथ MyWebView का उपयोग कर रहे हैं, तब तक देशी CAB (एक WebView के मामले में कॉपी / पेस्ट मेनू) प्राप्त करने का कोई तरीका नहीं है। इस तरह के व्यवहार को क्रियान्वित करना संभव हो सकता है, लेकिन वह यह तरीका नहीं है कि यह कोड काम करता है।

अद्यतनः ऐसा करने के लिए एक बहुत आसान तरीका है! उपरोक्त समाधान अच्छी तरह से काम करता है, लेकिन यह एक वैकल्पिक, आसान तरीका है।

यह समाधान ActionMode पर कम नियंत्रण प्रदान करता है, लेकिन इसके लिए उपरोक्त समाधान की तुलना में बहुत कम कोड की आवश्यकता होती है।

public class MyActivity extends Activity {

    private ActionMode mActionMode = null;

    @Override
    public void onActionModeStarted(ActionMode mode) {
        if (mActionMode == null) {
            mActionMode = mode;
            Menu menu = mode.getMenu();
            // Remove the default menu items (select all, copy, paste, search)
            menu.clear();

            // If you want to keep any of the defaults,
            // remove the items you don't want individually:
            // menu.removeItem(android.R.id.[id_of_item_to_remove])

            // Inflate your own menu items
            mode.getMenuInflater().inflate(R.menu.my_custom_menu, menu);
        }

        super.onActionModeStarted(mode);
    }

    // This method is what you should set as your item's onClick
    // <item android:onClick="onContextualMenuItemClicked" />
    public void onContextualMenuItemClicked(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.example_item_1:
                // do some stuff
                break;
            case R.id.example_item_2:
                // do some different stuff
                break;
            default:
                // ...
                break;
        }

        // This will likely always be true, but check it anyway, just in case
        if (mActionMode != null) {
            mActionMode.finish();
        }
    }

    @Override
    public void onActionModeFinished(ActionMode mode) {
        mActionMode = null;
        super.onActionModeFinished(mode);
    }
}

आपको आरंभ करने के लिए यहां एक उदाहरण मेनू है:

<!-- my_custom_menu.xml -->
<?xml version="1.0" encoding="utf-8"?>

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/example_item_1"
        android:icon="@drawable/ic_menu_example_1"
        android:showAsAction="always"
        android:onClick="onContextualMenuItemClicked"
        android:title="@string/example_1">
    </item>

    <item
        android:id="@+id/example_item_2"
        android:icon="@drawable/ic_menu_example_2"
        android:showAsAction="ifRoom"
        android:onClick="onContextualMenuItemClicked"
        android:title="@string/example_2">
    </item>

</menu>

बस! हो गया! अब आपका कस्टम मेनू दिखाया जाएगा, आपको चयन के बारे में चिंता करने की ज़रूरत नहीं है, और आपको ActionMode साथ खुद को चिंता करने की ज़रूरत नहीं है

यह लगभग पूरी तरह से एक WebView साथ काम करता है जो इसकी संपूर्ण अभिभावक Activity WebView करता है मुझे यकीन नहीं है कि अगर एक बार आपकी Activity भीतर एक बार कई View हो जाएंगे तो यह कितनी अच्छी तरह काम करेगा संभवतः उस मामले में कुछ tweaking की आवश्यकता होगी