【问题标题】:Make certain part of text bold using DataBinding使用 DataBinding 使文本的某些部分变为粗体
【发布时间】:2018-08-13 12:18:08
【问题描述】:

我想将我的文本的某些部分设置为粗体,其值是使用 DataBinding 和 ViewModel 设置的。

例如

如果您被选中,您将为您的配对支付 160 美元

我正在使用字符串资源

<string name="product_price">If you are selected, you will have to pay $%d for your pair.</string>

<TextView
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:layout_marginEnd="@dimen/spacing_xlarge"
          android:layout_marginStart="@dimen/spacing_xlarge"
          android:layout_marginBottom="@dimen/spacing_small"
          android:text="@{@string/product_price(productPrice)}"
          android:textColor="@color/button_tertiary"
          android:visibility="@{productPrice > 0}"
          style="@style/Body.Small"
          />

目前通过设置binding.setProductPrice(Object.getPrice())使用带绑定的ViewModel传递产品价格

我知道以下解决方案:但想尝试使用 DataBinding

  • 使用 Html 文本 - 但不想在代码中使用它。
  • 在水平样式中使用不同的 TextView。将该产品价格的样式设置为粗体。 - 非常糟糕的做法
  • 使用 SpannableString - 但不想在代码中使用它。

但上述所有解决方案都是解决方法。

问题::

Want to try DataBinding feature which can be used to style certain part of string. Just like SpannableString

Manipulate String in the Layout file using DataBinding

【问题讨论】:

  • @pskink :我不想将完整的 SpannableString 或 String 传递给 TextView。这个想法是将文本样式应用于文本的某些部分。虽然感谢您的建议。
  • @pskink :是的,这是最后一个选项(传递 SpannableString/SpannableStringBuilder)。但是我们不能使用 DataBinding 应用样式吗?
  • @pskink :使用 DataBinding 返回 SpannableStringBuilderSpannableString。但这对 String 的操作是在 java/kotlin 的代码中。我想使用 DataBinding 在布局文件中操作String
  • 为什么不只是将&lt;b&gt;标签添加到字符串资源:&lt;string name="product_price"&gt;If you are selected, you will have to pay &lt;b&gt;$%d&lt;/b&gt; for your pair.&lt;/string&gt;?这不适用于任意更改(例如,前景色),但对于粗体字应该没问题。 “我想使用 DataBinding 在布局文件中操作字符串。” -- 这不太实用,因为您没有完整的多语句编程语言。 一些内容必须在 Java/Kotlin 中,至少在 BindingAdapter 或其他帮助代码级别。
  • @CommonsWare :尝试将 标记添加到字符串资源:&lt;string name="product_price"&gt;If you are selected, you will have to pay &lt;b&gt;$%d&lt;/b&gt; for your pair.&lt;/string&gt;。但是文本仍然是未格式化的。尝试使用If you are selected, you will have to pay &lt;![CDATA[&lt;b&gt;$%d&lt;/b&gt;]]&gt; for your pair。它仍然显示相同的结果,未格式化的纯文本。

标签: android android-databinding android-mvvm


【解决方案1】:

根据@CommonsWare,

尝试添加基本的 Html 标签&lt;string name="product_price"&gt;If you are selected, you will have to pay &lt;![CDATA[&lt;b&gt;$%d&lt;/b&gt;]]&gt; for your pair.&lt;/string&gt;

布局文件:导入的 Html

 <?xml version="1.0" encoding="utf-8"?>
 <layout
   <data>
   <import type="android.text.Html"/>
   <data>
     <LinearLayout>
       <android.support.design.widget.CoordinatorLayout>
       <TextView
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:layout_marginEnd="@dimen/spacing_xlarge"
          android:layout_marginStart="@dimen/spacing_xlarge"
          android:layout_marginBottom="@dimen/spacing_small"
          android:text="@{Html.fromHtml(@string/product_price(productPrice))}"
          android:textColor="@color/button_tertiary"
          android:visibility="@{productPrice > 0}"
          style="@style/Body.Small"
          />
       </android.support.design.widget.CoordinatorLayout>
     </LinearLayout>
 </layout>

【讨论】:

  • @pskink :是的,应该避免使用Html.fromHtml。但我不想在代码中操纵它。这是我使用 DataBinding 实现的最终目标。将在何时找到其他最佳解决方案时更新答案。
  • @pskink :到目前为止,我只使用string 资源@string/xxxxxandroid:text="@{Html.fromHtml(@string/product_price(productPrice))}"
  • "But I don't want to manipulate it in code" - 和Html.fromHtml 不是java代码?我已经用简单的SpannableString 给了你一个解决方案,但你仍然认为Html.fromHtm 不需要任何java 代码,并且比简单的setSpan 方法更好/更快——这就是我拒绝你的答案的原因
  • @pskink :是的,Html.fromHtml 在内部为此运行 java 代码。但是我不必编写 java 代码,它在幕后做了什么,我现在不太关心这个。但是是的,将来肯定会使用您的解决方案。你对我的回答投了反对票,这很好。
  • "But I don't have to write java code what it does behind the scene",它只有 3 行代码(是的,三行) - 创建一个 StyleSpan,设置 span 并调用 TextUtils#expandTemplate - 现在将其与 Html.fromHtml 正在做的事情进行比较 - 当然真正的工作是在 HtmlToSpannedConverter 中完成的 - 但如果你希望你的应用程序非常慢,你可以随意使用它
【解决方案2】:

你必须创建一个 BindingAdapterSpannableStringBuilder

绑定适配器

object Util {
    @BindingAdapter("main","secondText")
        @JvmStatic
        fun setBoldString(view: AppCompatTextView, maintext: String,sequence: String) {
            view.text = Util.getBoldText(maintext, sequence)
        }



    @JvmStatic
        fun getBoldText(text: String, name: String): SpannableStringBuilder {
            val str = SpannableStringBuilder(text)
            val textPosition = text.indexOf(name)
            str.setSpan(android.text.style.StyleSpan(Typeface.BOLD),
                    textPosition, textPosition + name.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
            return str
        }
}

XML

    <android.support.v7.widget.AppCompatTextView
        android:id="@+id/username"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:main="@{`you will pay $160 for your pair`}"
        app:secondText="@{`$160`}"
        android:textColor="@color/black"
        android:textSize="22sp" />

也许对你有帮助。

【讨论】:

  • 我很惊讶这不是公认的答案。非常干净和最佳。
【解决方案3】:

您可以将绑定适配器与 SpannableString 结合使用。定义绑定适配器后,您可以在所有布局文件中重用它。

@BindingAdapter({"mainText", "priceToFormat"})
public static void format(TextView textView, String mainText, float 
      productPrice){
   //Use spannable string to format your text accordingly
   textView.setText(formattedText);
}

您可以像这样在布局文件中传递这些参数:

<TextView
   .
   .
   app:mainText = "@{ priceText }"
   app:priceToFormat = "@{ price }"/>

祝你好运。

【讨论】:

  • 喜欢您的解决方案。尽管我们仍在代码中进行操作。调用format(view, sdfgsdfg, 12)。您的解决方案只是调用一个具有 BindingAdapter 注释的方法,但在这里没有用。因为我们仍在使用 TexView.setText。我真的很想避免传递 textview 并在代码中对其进行操作。
  • 我的最终目标是充分利用 DataBinding 并避免代码中的所有操作。
  • @VikalpPatel 除非视图中定义了具有此特定功能的方法,否则您必须在代码中对其进行操作。数据绑定只是将您的数据与您的视图绑定。据我所知,除非您定义诸如绑定适配器之类的东西或将数据传递给另一种方法进行处理,否则它不会格式化数据。祝你好运。
  • @rbd_sqrl :是的,我知道 DataBinding 只是将数据与视图绑定。但我的想法是充分探索 DataBinding。是的,我们可以使用 Spannable。感谢您提供解决方案:)
【解决方案4】:

如下所述使用 BindingAdapter

    @BindingAdapter("setBold")
    @JvmStatic
    public static void setBold(TextView view, boolean isBold) {
        if (isBold) {
            view.setTypeface(null, Typeface.BOLD);
        } else {
            view.setTypeface(null, Typeface.NORMAL);
        }
    }

并在xml中使用如下:

  <androidx.appcompat.widget.AppCompatTextView 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:text="@{model.value}"
        app:setBold="@{model.isBold}"
   />

【讨论】:

    【解决方案5】:

    由于 Html.fromHtml 签名在 API 级别 24 (Android N) 发生了变化,Android 团队引入了 HtmlCompat,以便在任何 API 级别中使用相同的签名。

    所以,你应该使用 HtmlCompat 类:

    HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY);
    

    要使用它,您可以在项目的 build.gradle 中包含 AndroidX 核心:

    implementation 'androidx.core:core:1.3.1'
    

    布局 XML 文件:

    <?xml version="1.0" encoding="utf-8"?>
     <layout
       <data>
       <import type="androidx.core.text.HtmlCompat"/>
       <data>
         <LinearLayout>
           <android.support.design.widget.CoordinatorLayout>
           <TextView
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:layout_marginEnd="@dimen/spacing_xlarge"
              android:layout_marginStart="@dimen/spacing_xlarge"
              android:layout_marginBottom="@dimen/spacing_small"
              android:text="@{HtmlCompat.fromHtml(@string/product_price(productPrice),HtmlCompat.FROM_HTML_MODE_LEGACY)}"
              android:textColor="@color/button_tertiary"
              android:visibility="@{productPrice > 0}"
              style="@style/Body.Small"
              />
           </android.support.design.widget.CoordinatorLayout>
         </LinearLayout>
     </layout>
    

    【讨论】:

      【解决方案6】:

      // 将此方法放在您的模型类中,其中名称是字符串变量,根据给定的 api 响应设置

      public Spanned getHtmlText(){
              return Html.fromHtml("<b>" + name + "</b>");
          }
      

      // 在 xml 中使用 this 其中 userList 是模型类的变量名。

       android:text="@{userList.htmlText}"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多