gpt4 book ai didi

android ClickableSpan 拦截点击事件

转载 作者:IT老高 更新时间:2023-10-28 22:21:02 29 4
gpt4 key购买 nike

我在布局中有一个 TextView。就是这么简单。我在布局中放置了一个 OnClickListener,TextView 的某些部分设置为 ClickableSpan。我希望 ClickableSpan 在单击时在 onClick 函数中执行某些操作,并且当点击TextView的另一部分时,它必须在布局的OnClickListener的onClick函数中做一些事情。这是我的代码。

    RelativeLayout l = (RelativeLayout)findViewById(R.id.contentLayout);
l.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "whole layout", Toast.LENGTH_SHORT).show();
}
});

TextView textView = (TextView)findViewById(R.id.t1);
textView.setMovementMethod(LinkMovementMethod.getInstance());

SpannableString spannableString = new SpannableString(textView.getText().toString());
ClickableSpan span = new ClickableSpan() {
@Override
public void onClick(View widget) {
Toast.makeText(MainActivity.this, "just word", Toast.LENGTH_SHORT).show();
}
};
spannableString.setSpan(span, 0, 5, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
textView.setText(spannableString);

最佳答案

我也遇到过这个问题,感谢@KMDev 提到的源代码,我想出了一个更简洁的方法。

首先,由于我只有一个 TextView 可以部分点击,实际上我不需要大部分功能 LinkMovementMethod (及其父类(super class) ScrollingMovementMethod),增加了处理按键、滚动等的能力。

相反,创建一个使用 LinkMovementMethod 中的 OnTouch() 代码的自定义 MovementMethod:

ClickableMovementMethod.java

package com.example.yourapplication;

import android.text.Layout;
import android.text.Selection;
import android.text.Spannable;
import android.text.method.BaseMovementMethod;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.view.MotionEvent;
import android.widget.TextView;

/**
* A movement method that traverses links in the text buffer and fires clicks. Unlike
* {@link LinkMovementMethod}, this will not consume touch events outside {@link ClickableSpan}s.
*/
public class ClickableMovementMethod extends BaseMovementMethod {

private static ClickableMovementMethod sInstance;

public static ClickableMovementMethod getInstance() {
if (sInstance == null) {
sInstance = new ClickableMovementMethod();
}
return sInstance;
}

@Override
public boolean canSelectArbitrarily() {
return false;
}

@Override
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {

int action = event.getActionMasked();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {

int x = (int) event.getX();
int y = (int) event.getY();
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();

Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);

ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length > 0) {
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(widget);
} else {
Selection.setSelection(buffer, buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
}
return true;
} else {
Selection.removeSelection(buffer);
}
}

return false;
}

@Override
public void initialize(TextView widget, Spannable text) {
Selection.removeSelection(text);
}
}

那么使用这个ClickableMovementMethod,touch事件就不会再被movement方法消费了。但是,调用 TextView.fixFocusableAndClickableSettings()TextView.setMovementMethod() 会将可点击、可长按和可聚焦设置为 true,这将使 View.onTouchEvent() 使用触摸事件。要解决此问题,只需重置三个属性即可。

因此,伴随 ClickableMovementMethod 的最终实用方法在这里:

public static void setTextViewLinkClickable(TextView textView) {
textView.setMovementMethod(ClickableMovementMethod.getInstance());
// Reset for TextView.fixFocusableAndClickableSettings(). We don't want View.onTouchEvent()
// to consume touch events.
textView.setClickable(false);
textView.setLongClickable(false);
}

这对我来说就像一个魅力。

ClickableSpans 上的点击事件被触发,并且在它们之外的点击被传递给父布局监听器。

请注意,如果您让 TextView 可选择,我还没有测试过这种情况,也许您需要自己挖掘源代码:P

关于android ClickableSpan 拦截点击事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16792963/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com