【问题标题】:TextView selection, event for the moment when selection is done?TextView 选择,选择完成时的事件?
【发布时间】:2021-09-15 08:33:13
【问题描述】:

在出现TextView 的选择菜单时如何获得通知?

请参阅下面的屏幕录像。如果您选择一些文本,则会出现上下文菜单(复制/共享/全选)。如果您开始拖动蓝色拖动手柄,上下文菜单就会消失,一旦您松开手柄,菜单就会再次出现。因此,基本上,菜单仅在选择完成时出现,而不是在您仍在选择文本时出现。

我希望在选择完成时收到通知(即与菜单出现的时间相同)。我认为onPrepareActionMode将在选择选择并出现菜单后调用,但在使用下面的代码进行测试后,onPrepareActionMode即使在选择菜单不是的情况下,onPrepareActionMode也是拖动句柄的@ 987654325可见的。此外,它经常因为一次拖动而被调用两次。所以onPrepareActionMode 似乎不是那么回答。那是什么?

    object: ActionMode.Callback{
        @SuppressLint("ResourceType")
        override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean
        {
            Log.d("test", "onCreateActionMode");
            return true;
        }

        override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean
        {
            Log.d("test", "onPrepareActionMode");
            return false
        }

        override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean
        {
            Log.d("test", "onActionItemClicked");
            return false;
        }

        override fun onDestroyActionMode(mode: ActionMode?)
        {
            Log.d("test", "onDestroyActionMode");
        }
    };

【问题讨论】:

    标签: android textview android-widget android-menu


    【解决方案1】:

    没有答案?我认为这将是选择文本时自动执行某些操作的常见要求。无论如何,我花了很多时间试图找到一种方法,但都失败了。但是提示来自一个随机的事情:我注意到,每当文本选择完成并出现菜单时,

    W/androidtc:在主线程上调用 TextClassifier

    打印在 Logcat 中。这就是我发现TextView中有TextClassifier的原因。所以,我尝试了以下代码

        val tc = object:TextClassifier{
            override fun classifyText(request: TextClassification.Request): TextClassification
            {
                Log.d("test", "classifyText")
                return super.classifyText(request)
            }
        }
    
        text2.setTextClassifier(tc);
    

    ,正如我所怀疑的,classifyText 在选择完成时被调用,而不是在我拖动选择句柄期间。这在选择关闭时也会调用(在其他地方点击),但我想我可以通过检查所选文本长度是否为 0 来过滤掉它。我将使用这种解决方法,直到知道更好的人发布更优雅和正确的解决方案.


    PS:以上代码适用于 Android 10/11/12,但在 Android 8.1 上导致运行时异常。我猜这是因为 Android 8.1 上的方法没有默认实现。

    对于 Android 8.1,我尝试了以下方法,并且成功了。如果您不关心分类器本身,我想您不必传递默认分类器并使用注释掉的虚拟返回值。

    override fun onCreate(savedInstanceState: Bundle?)
    {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    
        val textClassificationManager = getSystemService(Context.TEXT_CLASSIFICATION_SERVICE) as TextClassificationManager;
        val defaultOne = textClassificationManager.textClassifier;
        val txt = findViewById<TextView>(R.id.textview1);
        txt.setTextClassifier(MyTextClassfier(defaultOne));
    }
    
    inner class MyTextClassfier(private val fallback:TextClassifier) : TextClassifier by fallback
    {
        override fun suggestSelection(
            text: CharSequence,
            selectionStartIndex: Int,
            selectionEndIndex: Int,
            defaultLocales: LocaleList?
        ): TextSelection
        {
            return fallback.suggestSelection(text, selectionStartIndex, selectionEndIndex, defaultLocales);
            //return TextSelection.Builder(selectionStartIndex, request.getEndIndex()).build();
        }
    
        override fun classifyText(
            text: CharSequence,
            startIndex: Int,
            endIndex: Int,
            defaultLocales: LocaleList?
        ): TextClassification
        {
            //Selection ended. User has lifted his finger.
            return fallback.classifyText(text, startIndex, endIndex, defaultLocales);
            //return TextClassification.Builder().build();
        }
    }
    

    【讨论】:

    • 完美!有效✅
    • @SenocicoStelian 检查添加的代码,如果您希望它在 Android 8.1 上运行。 TextClassifer 类似乎是在 Android 8.0 上添加的,所以我不确定如何在 Android 8.0 之前让它工作。
    猜你喜欢
    • 2019-01-31
    • 1970-01-01
    • 2011-12-05
    • 2014-11-19
    • 2018-06-08
    • 2021-02-06
    • 2012-09-25
    • 1970-01-01
    • 2017-02-16
    相关资源
    最近更新 更多