【问题标题】:Displaying multiple kinds of shapes behind text in Android在Android中在文本后面显示多种形状
【发布时间】:2017-11-11 20:48:01
【问题描述】:

我目前面临一个问题,我想在文本的一部分后面显示一个形状,然后在下一部分文本后面显示一个不同的形状。我尝试使用多个 TextView,但我不知道如何让它们像一个文本一样显示。我也尝试使用 SpannableString,但我无法完成这项工作。为了更清楚地说明这一点,这就是我想要的方式:

我的形状是 XML 文件,加载为可绘制对象。

我试过的 SpannableString 代码是这样的:

SpannableString ss = new SpannableString("abc");
Drawable d1 = getResources().getDrawable(R.drawable.oval_background);
d1.setBounds(0, 0, d1.getIntrinsicWidth(), d1.getIntrinsicHeight());
ImageSpan span = new ImageSpan(d1, ImageSpan.ALIGN_BASELINE);
ss.setSpan(span, 0, 3, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
tv.setText(ss);

但文字和背景都没有出现在这里。尝试另一个可绘制对象会显示可绘制对象,但不会显示文本。

这是oval_background.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >

  <corners
    android:bottomLeftRadius="30dp"
    android:bottomRightRadius="30dp"
    android:radius="60dp"
    android:topLeftRadius="30dp"
    android:topRightRadius="30dp" />

  <solid android:color="#1287A8" />

  <padding
    android:bottom="5dp"
    android:left="10dp"
    android:right="10dp"
    android:top="5dp" />

</shape>   

现在我的问题是,获得我想要的结果的最佳方法是什么?

编辑:将 Flexbox 用作 @R。 Zagórski 建议,我得出这个结果:

这是一项改进,但尚未完成。我使用的 Flexbox 代码是:

<com.google.android.flexbox.FlexboxLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:flexDirection="row"
    app:flexWrap="wrap"
    app:justifyContent="flex_start"
    app:alignItems="flex_start"
    app:alignContent="flex_start"
    android:id="@+id/flexbox"
    android:layout_marginTop="@dimen/text_margin_small"
    android:layout_marginLeft="@dimen/text_margin_small"
    android:layout_marginRight="@dimen/text_margin_small">

</com.google.android.flexbox.FlexboxLayout>

【问题讨论】:

    标签: java android xml android-layout


    【解决方案1】:

    要为TextView 应用背景,请使用android:background 属性,如this answer 或以编程方式创建时使用TextViewsetBackground 方法。 要像您显示的那样安排 TextViews,请使用来自 Google 的 FlexBoxLayouthttps://github.com/google/flexbox-layout

    【讨论】:

    • 感谢您的回答,我查看了您建议的 Flexbox。我无法完全按照我想要的方式得到它,但这是朝着正确方向迈出的一步。我编辑了 OP。
    • 嗯,我不太明白,问题到底出在哪里。也许您需要测量文本宽度以将较长的文本部分分成较小的部分以适合一行? stackoverflow.com/a/18958569/6507689
    【解决方案2】:

    无需任何库即可轻松完成。这是工作示例

    更新

    1. 定义主方法。这将调用创建视图。 (您可以使用自定义布局或其他东西)。然后创建随机形状作为视图和颜色的背景。

      /**
       * Max Width for all random text.
       * Should include margins of layout, etc.
       */
      private int getMaxWidthLine () {
          Display display = getWindowManager().getDefaultDisplay();
          Point size = new Point();
          display.getSize(size);
          return size.x - 20;
      }
      /**
       * Parent of all Random TextView should LinerLayout with vertical
       * orientation, to apply building Views line by line, based on Width.
       */
      private void addRandomTextInLine (LinearLayout mainViewGroup, TextView textView) {
          LinearLayout lastTextHolder;
          if (mainViewGroup.getChildCount() > 0) {
              lastTextHolder = (LinearLayout) mainViewGroup.
                      getChildAt(mainViewGroup.getChildCount() - 1);
          } else {
              LinearLayout firstTextHolder = new LinearLayout(MainActivity.this);
              firstTextHolder.setLayoutParams(new ActionBar.LayoutParams
                      (ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
              firstTextHolder.addView(textView);
              mainViewGroup.addView(firstTextHolder);
              return;
          }
          mainViewGroup.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
          lastTextHolder.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
          textView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
      
          int maxParentWidth = getMaxWidthLine();
          int lastHolderWidth = lastTextHolder.getMeasuredWidth();
          int nextTextWidth = textView.getMeasuredWidth();
      
          if (maxParentWidth - lastHolderWidth >= nextTextWidth ) {
              lastTextHolder.addView(textView);
          } else {
              LinearLayout newTextHolder = new LinearLayout(MainActivity.this);
              newTextHolder.setLayoutParams(new ActionBar.LayoutParams
                      (ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
              newTextHolder.addView(textView);
              mainViewGroup.addView(newTextHolder);
          }
      }
      
      /**
       * Start method, for generation TextView with Random Background
       */
      @SuppressWarnings("deprecation")
      private void addRandomCornersText (ViewGroup group, String text) {
          /*
           * Just defining View programmatically.
           * You can use inflate from layout.
           */
          TextView itemText = new TextView(MainActivity.this);
          LinearLayout.LayoutParams params = new LinearLayout.LayoutParams
                  (ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
          float scale = getResources().getDisplayMetrics().density;
          int margins  = (int) (5 * scale + 0.5f);
          int padding = (int) (10 * scale + 0.5f);
          params.setMargins(margins, margins, margins, margins);
          itemText.setPadding(padding, padding, padding, padding);
          itemText.setLayoutParams(params);
      
          /*
           * Generate random shapes/corners and
           * applying this changes to the view
           */
          Random random = new Random();
          int r = random.nextInt(100);
          float[] outerR = new float[] {r, r, r, r, r, r, r, r};
          ShapeDrawable shape = new ShapeDrawable(new RoundRectShape(outerR, null, null));
          shape.getPaint().setColor(Color.argb(255, random.nextInt(256),
                  random.nextInt(256), random.nextInt(256)));
      
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
              itemText.setBackground(shape);
          } else {
              itemText.setBackgroundDrawable(shape);
          }
          itemText.setText(text);
          addRandomTextInLine((LinearLayout) group, itemText);
      }
      

      }

    2. 呼叫,无论您需要您的方法。这将返回随机颜色和形状 TextView。

      ViewGroup viewGroup = (ViewGroup) findViewById(R.id.main_text_holder);
      for (int i = 0; i < 15; i++) {
          addRandomCornersText(viewGroup, LoremIpsum.getInstance().getWords(1, 4));
      }
      

    然后你会看到类似下面的东西。但也有一些额外的改进,比如为 TextView 文本颜色添加反转颜色,一些宽度设置等。

    示例

    【讨论】:

    • 嘿,非常感谢您抽出宝贵的时间来写这篇文章。我有类似的东西,但我遇到的问题是,如果 TextView 没有填满整个宽度,则不会启动新的。这就是我想要完成的。一旦占据了完整的宽度,TextView 应该在下一行继续。
    • @user2988879 但问题是什么?计算屏幕宽度,如果大于预期,则拆分为新的线性布局?有问题吗?
    【解决方案3】:

    您可以通过使用背景属性将生成的自定义形状用于您的 textView。使用自定义形状的主要好处是通过使用渐变来增强外观。

    步骤:

    1. 在可绘制目录中为您的视图创建自定义形状资源布局文件。

      <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <stroke android:width="2dp" android:color="@android:color/holo_purple"/> <gradient android:angle="90" android:startColor="@color/colorPrimary" android:endColor="@android:color/holo_green_dark"/> <corners android:radius="50dp"/> <padding android:left="2dp" android:bottom="2dp" android:right="2dp" android:top="2dp"/> </shape>

    2. 在 TextView 的 Layout 文件中,添加属性 android:background="@drawable/yourshape"

      <TextView android:textSize="50sp" android:textColor="@android:color/white" android:gravity="center_horizontal|center_vertical" android:text="Hello World!" android:layout_width="300dp" android:layout_height="200dp" android:background="@drawable/shape1"/>

    3. 此布局创建了以下输出,.

    【讨论】:

      【解决方案4】:

      您可以使用android自定义按钮生成器,根据您的选择为按钮设置背景

      【讨论】:

        猜你喜欢
        • 2021-05-06
        • 1970-01-01
        • 2020-03-28
        • 2013-07-26
        • 1970-01-01
        • 2015-07-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多