我如何旋转背景颜色没有锯齿的 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 answer,setFilterBitmap
不太适合我。部分原因是我使用的是 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 -->
我有一个静态 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 answer,setFilterBitmap
不太适合我。部分原因是我使用的是 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 -->