【问题标题】:Android EditText Destroys Webview ActionmodeAndroid EditText 破坏 Webview Actionmode
【发布时间】:2017-05-19 20:35:09
【问题描述】:

背景:

  • 我有一个带有动作模式回调的 webview。

  • 如果您在 webview 上长按并选择文本,则会显示操作模式。

  • webview 操作模式的编辑菜单选项在 webview 底部打开一个带有编辑文本字段的线性布局。

问题:

  • 当我点击编辑文本字段时,操作模式关闭 (线性布局上还有一个按钮,它不会像编辑文本那样关闭动作模式)

预期结果:

  • 我希望选择保持选中状态,即使用户点击并输入编辑文本

更多信息:

  • 在 API 21 上测试 - 安卓 5.0 每次点击编辑文本都会关闭动作模式,但是在 API 25 - android 7.1.1 第一次点击编辑文本会关闭动作模式,点击第二次编辑文本不会关闭操作模式,并且从这里开始按预期工作

代码:

您可以在此处从 github 克隆项目: https://github.com/fmarais/webview_edit_text/tree/master

app/src/main/java/com/my_package/webview_edit_text/MainActivity.java

package com.my_package.webview_edit_text;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.ActionMode;
import android.view.View;
import android.webkit.WebViewClient;
import android.widget.EditText;
import android.widget.LinearLayout;

public class MainActivity extends AppCompatActivity {
    private CustomWebview mWebview;
    private ActionMode mActionMode;
    private LinearLayout editLayout;
    private EditText editText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getSupportActionBar().setTitle("onCreate()");

        editLayout = (LinearLayout) findViewById(R.id.edit_layout);
        editText = (EditText) findViewById(R.id.edit_text);

        mWebview = (CustomWebview) findViewById(R.id.webview);
        mWebview.setWebViewClient(new WebViewClient());
        mWebview.getSettings().setJavaScriptEnabled(true);
        mWebview.loadUrl("http://www");

        // TODO: USE ONE AT A TIME
//        enableActivityActionmode();
//        mWebview.enableWebviewActionmodeInline(editLayout, editText);
        // this is the one we want, using TYPE_PRIMARY
        mWebview.enableWebviewActionmodeActionBar(editLayout, editText);
    }

    private void enableActivityActionmode() {
        mWebview.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                mActionMode = MainActivity.this.startActionMode(new MyActionmodeCallback(editLayout, editText));
                return false;
            }
        });
    }
}

app/src/main/java/com/my_package/webview_edit_text/CustomWebview.java

package com.my_package.webview_edit_text;

import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ActionMode;
import android.webkit.WebView;
import android.widget.EditText;
import android.widget.LinearLayout;

import static android.view.ActionMode.TYPE_PRIMARY;

public class CustomWebview extends WebView {
    private static final String TAG = "CustomWebview";
    private boolean enableWebviewActionmodeInline = false;
    private boolean enableWebviewActionmodeActionbar = false;
    private LinearLayout editLayout;
    private EditText editText;

    public CustomWebview(Context context) {
        super(context);
    }

    public CustomWebview(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomWebview(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public void enableWebviewActionmodeInline(LinearLayout editLayout, EditText editText) {
        this.enableWebviewActionmodeInline = true;
        this.editLayout = editLayout;
        this.editText = editText;
    }

    public void enableWebviewActionmodeActionBar(LinearLayout editLayout, EditText editText) {
        this.enableWebviewActionmodeActionbar = true;
        this.editLayout = editLayout;
        this.editText = editText;
    }

    @Override
    public ActionMode startActionMode(ActionMode.Callback callback) {
        if (enableWebviewActionmodeInline) {
            // custom actionmode enabled
            Log.i(TAG, "startActionMode() enableWebviewActionmodeInline");
            return super.startActionMode(new MyActionmodeCallback(editLayout, editText));
        }

        if (enableWebviewActionmodeActionbar) {
            // custom actionmode enabled
            Log.i(TAG, "startActionMode() enableWebviewActionmodeActionbar");
            return super.startActionModeForChild(this, new MyActionmodeCallback(editLayout, editText));
        }

        // default
        Log.i(TAG, "startActionMode() default");
        return super.startActionMode(callback);
    }

    @Override
    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
        if (enableWebviewActionmodeInline) {
            // custom actionmode enabled
            Log.i(TAG, "startActionMode()_type enableWebviewActionmodeInline");
            return super.startActionMode(new MyActionmodeCallback(editLayout, editText), type);
        }

        if (enableWebviewActionmodeActionbar) {
            // custom actionmode enabled
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                Log.i(TAG, "startActionMode()_type enableWebviewActionmodeActionbar Build.VERSION_CODES.M");
                return super.startActionModeForChild(getRootView(), new MyActionmodeCallback(editLayout, editText), TYPE_PRIMARY);
//                return super.startActionModeForChild(this, new MyActionmodeCallback(editLayout, editText), TYPE_PRIMARY);
//                return super.startActionModeForChild(this, new MyActionmodeCallback(editLayout), TYPE_FLOATING);
            } else {
                Log.i(TAG, "startActionMode()_type enableWebviewActionmodeActionbar");
                return super.startActionModeForChild(this, new MyActionmodeCallback(editLayout, editText));
            }
        }

        // default
        Log.i(TAG, "startActionMode()_type default");
        return super.startActionMode(callback, type);
    }
}

app/src/main/java/com/my_package/webview_edit_text/MyActionmodeCallback.java

package com.my_package.webview_edit_text;

import android.util.Log;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;

public class MyActionmodeCallback implements ActionMode.Callback {
    private static final String TAG = "MyActionmodeCallback";
    private LinearLayout editLayout;
    private EditText editText;

    public MyActionmodeCallback(LinearLayout editLayout, EditText editText) {
        this.editLayout = editLayout;
        this.editText = editText;
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        Log.i(TAG, "onActionItemClicked()");

        // TODO Auto-generated method stub
        switch (item.getItemId()) {
            case R.id.item_edit:
                Log.i(TAG, "onActionItemClicked() R.id.item_option1");
                editLayout.setVisibility(View.VISIBLE);
                return true;
        }
        return false;
    }

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        mode.getMenuInflater().inflate(R.menu.menu, menu);
        return true;
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
        editLayout.setVisibility(View.GONE);
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        mode.setTitle("onPrepareActionMode()");
        return false;
    }
}

app/src/main/res/layouts/activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                tools:context="com.my_package.webview_edit_text.MainActivity">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!-- WEBVIEW -->
        <com.my_package.webview_edit_text.CustomWebview
            android:id="@+id/webview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

        <!-- EDIT TEXT LAYOUT -->
        <LinearLayout android:id="@+id/edit_layout"
                      xmlns:android="http://schemas.android.com/apk/res/android"
                      android:layout_width="match_parent"
                      android:layout_height="wrap_content"
                      android:layout_gravity="bottom"
                      android:orientation="vertical"
                      android:visibility="gone">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="#2b2d2e"
                android:orientation="vertical">

                <Button
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="10dp"
                    android:text="Test button"/>

                <EditText
                    android:id="@+id/edit_text"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="#b48ade"
                    android:hint="Edit text here"
                    android:padding="10dp"/>
            </LinearLayout>
        </LinearLayout>
    </FrameLayout>
</RelativeLayout>

app/src/main/res/menu/menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/item_edit"
        android:icon="@android:drawable/ic_menu_edit"
        android:title="Edit">
    </item>
</menu>

app/src/main/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.my_package.webview_edit_text"
          xmlns:android="http://schemas.android.com/apk/res/android">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>

app/src/main/build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.3"
    defaultConfig {
        applicationId "com.my_package.webview_edit_text"
        minSdkVersion 16
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
            exclude group: 'com.android.support', module: 'support-annotations'
        })
        compile 'com.android.support:appcompat-v7:25.3.1'
        compile 'com.android.support.constraint:constraint-layout:1.0.2'
        testCompile 'junit:junit:4.12'
    }

【问题讨论】:

    标签: java android webview android-edittext


    【解决方案1】:
    • 而不是在 MainActivity 上使用 LinearLayout 来容纳编辑布局。使用对话框

    • 使用对话框保留网络视图文本选择

    • 在 android 5.0 和 7.1.1 上测试

    Github 链接(对话分支)-> https://github.com/fmarais/webview_edit_text/tree/dialog

    将以下内容添加到 app/src/main/java/com/my_package/webview_edit_text/MainActivity.java

    public void showDialog() {
            final Dialog dialog = new Dialog(this);
            dialog.setContentView(R.layout.dialog);
    
            // Setting dialogview
            Window window = dialog.getWindow();
            window.setGravity(Gravity.BOTTOM);
    
            window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
            dialog.setTitle("Edit");
            dialog.setContentView(R.layout.dialog);
            dialog.setCancelable(true);
    
            dialog.show();
        }
    

    • MainActivity.this 引用传递给 CustomWebview,然后传递给 MyActionmodeCallback
    • MyActionmodeCallback onActionItemClicked() 中使用
    • 显示对话框

    MainActivity

    mWebview.enableWebviewActionmodeActionBar(this, editLayout, editText);
    

    自定义网页视图

    @Override
        public ActionMode startActionMode(ActionMode.Callback callback) {
            if (enableWebviewActionmodeInline) {
                // custom actionmode enabled
                Log.i(TAG, "startActionMode() enableWebviewActionmodeInline");
                return super.startActionMode(new MyActionmodeCallback(mainActivity, this, editLayout, editText));
            }
    
            if (enableWebviewActionmodeActionbar) {
                // custom actionmode enabled
                Log.i(TAG, "startActionMode() enableWebviewActionmodeActionbar");
                return super.startActionMode(new MyActionmodeCallback(mainActivity, this, editLayout, editText));
            }
    
            // default
            Log.i(TAG, "startActionMode() default");
            return super.startActionMode(callback);
        }
    
        @Override
        public ActionMode startActionMode(ActionMode.Callback callback, int type) {
            if (enableWebviewActionmodeInline) {
                // custom actionmode enabled
                Log.i(TAG, "startActionMode()_type enableWebviewActionmodeInline");
                return super.startActionMode(new MyActionmodeCallback(mainActivity, this, editLayout, editText), type);
            }
    
            if (enableWebviewActionmodeActionbar) {
                // custom actionmode enabled
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    Log.i(TAG, "startActionMode()_type enableWebviewActionmodeActionbar Build.VERSION_CODES.M");
                    return super.startActionMode(new MyActionmodeCallback(mainActivity, this, editLayout, editText), TYPE_PRIMARY);
                } else {
                    Log.i(TAG, "startActionMode()_type enableWebviewActionmodeActionbar");
                    return super.startActionMode(new MyActionmodeCallback(mainActivity, this, editLayout, editText));
                }
            }
    
            // default
            Log.i(TAG, "startActionMode()_type default");
            return super.startActionMode(callback, type);
        }
    

    MyActionmodeCallback

    @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            Log.i(TAG, "onActionItemClicked()");
    
            // TODO Auto-generated method stub
            switch (item.getItemId()) {
                case R.id.item_edit:
                    Log.i(TAG, "onActionItemClicked() R.id.item_option1");
    //                editLayout.setVisibility(View.VISIBLE);
                    mainActivity.showDialog();
                    return true;
            }
            return false;
        }
    

    【讨论】:

      猜你喜欢
      • 2012-08-20
      • 2015-03-19
      • 1970-01-01
      • 2016-07-05
      • 2018-06-27
      • 2019-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多