gpt4 book ai didi

java - 如何使用 ClickableSpan 切换 Spannable 前景色

转载 作者:行者123 更新时间:2023-12-02 05:15:45 25 4
gpt4 key购买 nike

我使用一个方法创建了这个类,该方法接收 Spannable 对象并将样式应用于它接收的任何对象。我在具有这些 Spoiler 标签的论坛消息解析器上使用它,其中仅当鼠标光标位于其上时才显示内容。对于android,我想让它通过点击隐藏区域来工作,为此我写了这个:

public static class TextRuleStartSpoiler extends TextRuleStart
{
protected TextRuleStartSpoiler()
{
super("spoiler");
}

ArrayList<Spannable> hiddenSpannables = new ArrayList<Spannable>();
boolean hidden = false;

@Override
public void apply(Spannable s, TextView tv)
{
hiddenSpannables.add(s);

s.setSpan(new BackgroundColorSpan(Color.parseColor("#0A1238")),0,s.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
s.setSpan(getForegroundColorSpanShown(), 0, s.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
s.setSpan(getClickableSpanLink(),0,s.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}

public static TextRuleEnd getRuleEnd()
{
return new TextRuleEnd("spoiler");
}

ForegroundColorSpan foregroundColorSpanHidden = null;
private synchronized ForegroundColorSpan getForegroundColorSpanHidden()
{
if(foregroundColorSpanHidden == null)
{
foregroundColorSpanHidden = new ForegroundColorSpan(Color.parseColor("#0A1238"));
}

return foregroundColorSpanHidden;
}

ForegroundColorSpan foregroundColorSpanShown = null;
private synchronized ForegroundColorSpan getForegroundColorSpanShown()
{
if(foregroundColorSpanShown == null)
{
foregroundColorSpanShown = new ForegroundColorSpan(Color.WHITE);
}

return foregroundColorSpanShown;
}

ClickableSpan clickableSpan = null;
private synchronized ClickableSpan getClickableSpanLink()
{
if(clickableSpan == null)
{
clickableSpan = new ClickableSpan() {
@Override
public void onClick(View widget)
{
hidden = !hidden;

if(hidden)
{
for(Spannable s : hiddenSpannables)
{
s.setSpan(getForegroundColorSpanHidden(), 0, s.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
s.removeSpan(getForegroundColorSpanShown());
}
}
else
{
for(Spannable s : hiddenSpannables)
{
s.setSpan(getForegroundColorSpanShown(), 0, s.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
s.removeSpan(getForegroundColorSpanHidden());
}
}

widget.invalidate();
}

@Override
public void updateDrawState(TextPaint ds)
{
//super.updateDrawState(ds);
}
};
}

return clickableSpan;
}
}

但是,无论我点击多少次,都没有任何反应。我也尝试过,不是设置和删除 ForegroundColorSpans,而是将方法 updateDrawState 重写为如下所示:

@Override
public void updateDrawState(TextPaint ds)
{
if(hidden)
{
ds.linkColor = Color.parseColor("#0A1238");
}
else
{
ds.linkColor = Color.WHITE;
}

super.updateDrawState(ds);
}

但它也没有改变任何东西。我添加了一些调试日志打印,并且我确信这些方法正在使用正确的参数调用,但它没有以正确的方式更新,即使我尝试在 onClick 之后立即使 View 无效,同时使用 View v on onClick 和 TextView 电视上应用。

由于我编写的代码的性质,我不可能对 TextView 搞太多困惑,因为它将充满其他 Spannable 对象,其规则与具体的规则完全无关。

更新

事实上,问题不在于这部分代码,而在于我如何在 TextView 中插入 Spannable 对象。我正在迭代多个 Spannable,这让我认为我可以使用 TextView.append方法,但是,这会将 BufferType 更改为 EDITABLE,这会禁用文本中的视觉更新,因此我将其更改为

tv.setText(TextUtils.concat(tv.getText(), s), TextView.BufferType.SPANNABLE);

最佳答案

你应该做的是完全重写 updateDrawState 方法的默认实现,不要调用 super 方法。

示例代码(SpoilerSpan):

public class SpoilerSpan extends ClickableSpan {

private boolean shown = false;

public void setShown(boolean shown){
this.shown = shown;
}

public boolean getShown(){
return this.shown;
}

@Override
public void onClick(View widget) {
//Toggle the shown state
setShown(!getShown());
//Invalidate the view
widget.invalidate();
}

@Override
public void updateDrawState(TextPaint ds) {
//Don't call the super method otherwise this may override our settings!
//super.updateDrawState(ds);

//No need to disable the default underline style because the super method isn't called.
//ds.setUnderlineText(false);

if(getShown()){
ds.setColor(Color.BLACK);
ds.bgColor = 0xFFE7DAC2;
} else {
//Spoiler is not shown, make the text color the same as the background color
ds.setColor(0xFFE7DAC2);
ds.bgColor = 0xFFE7DAC2;
}
}
}

用法:

TextView tv = (TextView) findViewById(R.id.test);
tv.setMovementMethod(LinkMovementMethod.getInstance());

SpannableString testText = new SpannableString("This is some text. This is a spoiler and this isn't.");
testText.setSpan(new SpoilerSpan(), 19, 36, Spannable.SPAN_POINT_MARK);

tv.setText(testText, BufferType.SPANNABLE);

结果: enter image description here

关于java - 如何使用 ClickableSpan 切换 Spannable 前景色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26963425/

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