我如何旋转背景颜色没有锯齿的 Android 文本视图(需要消除锯齿)

How can I rotate an Android textview with background color that is not jagged (needs to be anti-aliased)

我有一个静态 xml 布局,我想以一定角度显示它的背景颜色(看起来像印刷标签)。我遇到的问题是背景的边缘看起来像是在 1980 年代渲染的(锯齿状 - 未消除锯齿)。

我怎样才能得到一个在一定角度下看起来像标签的文本视图,并且看起来不错(即抗锯齿)?

布局:

    <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clipChildren="false"
    android:clipToPadding="false"
    android:paddingRight="5dp"
    android:paddingTop="5dp"
    android:paddingBottom="5dp"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:includeFontPadding="false"
        android:maxLines="1"
        android:singleLine="true"
        android:text="Sample Text"
        android:textAllCaps="true"
        android:textColor="#ffffff"
        android:textSize="12sp"
        android:background="#3db8eb"
        android:rotation="-3"
        android:paddingTop="1dp"
        android:paddingBottom="1dp"
        android:paddingLeft="3dp"
        android:paddingRight="3dp"/>
</LinearLayout>

外观:

在尝试了一些不同的东西之后,我终于找到了一些有用的东西,尽管有点令人费解。以下是如何在具有纯色背景的旋转文本视图上获得平滑边缘:

第 1 步:创建具有颜色的可绘制资源(即 ColorDrawable 或类似矩形的 Shape)

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

第 2 步:将背景设置为该可绘制对象。

<TextView
  android:id="@+id/my_textview"
  ...
  android:background="@drawable/blue_rectangle" />

第 3 步:在代码调用中:

TextView textView = (TextView)findViewById(R.id.my_textview);
textView.getBackground().setFilterBitmap(true);

根据我的 related answersetFilterBitmap 不太适合我。部分原因是我使用的是 9patch 背景而不是颜色。

方法 #1:在视图上禁用硬件加速

有效的是为相关视图及其父视图禁用硬件加速(任何一个单独都不起作用):

private void fixAntiAlias(View viewFromThe80s) {
    if (Build.VERSION.SDK_INT > 10) {
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG | Paint.FILTER_BITMAP_FLAG);
        viewFromThe80s.setLayerType(View.LAYER_TYPE_SOFTWARE, p);
        ((View) viewFromThe80s.getParent()).setLayerType(View.LAYER_TYPE_SOFTWARE, p);
    }
}

编辑:[2/2/17] :我 运行 再次遇到这个问题,但这次只需要通过资源文件差异来修复它,而不是 code/logic差异

方法 #2:基于 XML 的修复

有时,您没有编辑视图逻辑的奢侈。例如,在我的例子中,两个视图共享相同的 RecyclerView.Adapter,一个有旋转视图,另一个没有。我需要 view/adapter 逻辑保持不变,但 XML 布局和资源可以不同。所以我采用了这种方法:

1.制作一个带有 t运行透明边框 的形状 src/main/res/drawable/background_rotatable_color.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- transparent 1px border -->
    <item>
        <shape>
            <solid android:color="@android:color/transparent"/>
            <size android:width="16dp" android:height="16dp"/>
        </shape>
    </item>
    <!-- main color : inset by 1px so the transparent layer below shows so that when antialiasing is done, it blends better -->
    <item android:top="1px" android:right="1px" android:left="1px" android:bottom="1px">
        <shape>
            <solid android:color="@color/red"/>
        </shape>
    </item>
</layer-list>

2。应用形状和(可选):使用着色将其设置为所需的颜色
src/main/res/layout-land/item_product_details.xml

<TextView
    android:id="@+id/text_savings_banner"
    . . .
    android:background="@drawable/background_rotatable_color"
    android:backgroundTint="@color/blue_accent" /> <!-- optional but handy if you need to do this in a lot of places with different colors -->