我正在调试我的应用程序,并在ImageView
引用时发现,它是AppCompatImageView
而不是ImageView
。 TextView
(AppCompatTextView
)也是如此。
虽然我没有特别对这种行为有问题,因为它的AppCompat毕竟在检查其他开发人员的代码时,我看到extends Activity
而不是AppCompatActivity
而我几乎已经标记了它是一种不良做法"。
另一方面,在处理矢量图像时,我使用了ImageView
并且出现了问题,因为我没有使用AppCompatImageView
并使用它是解决方案:< / p>
ImageView not displaying correctly in the device
这种不一致的行为让我对我应该遵循的做法感到困惑。我应该从现在开始延伸一个活动吗?
答案 0 :(得分:6)
简短回答“我应该从现在开始延伸活动吗?”不,你应该继续扩展AppCompatActivity
,因为它为旧设备提供了向后兼容的功能。如果是AppCompatImageView
:
ImageView支持旧版平台上的兼容功能,包括:
- 允许通过ViewCompat中的背景色调方法动态显示其背景色。
- 允许使用backgroundTint和backgroundTintMode设置背景色调。
- 允许通过ImageViewCompat中的图像色调方法动态着色其图像。
- 允许使用tint和tintMode设置图像色调。
此外,它还增加了与旧Android版本的矢量绘图兼容性。
有关不一致的说明
正如AppCompatImageView
中所述:
当您在布局中使用ImageView并且appcompat提供顶级活动/对话框时,将自动使用此选项。
所以,这并不意外。
工作原理
AppCompatActivity
安装LayoutInflater.Factory2
来拦截某些观点的通胀。可以在AppCompatViewInflater.java中看到此inflater的代码。
负责创建Views
的函数是AppCompatViewInflater#createView(View, String, Context, AttributeSet, boolean, boolean, boolean, boolean)
,正如您在此处所看到的,它检查简单的视图名称(没有前缀的包),并创建AppCompat*
版本代替:
public final View createView(View parent, final String name, @NonNull Context context,
@NonNull AttributeSet attrs, boolean inheritContext,
boolean readAndroidTheme, boolean readAppTheme, boolean wrapContext) {
final Context originalContext = context;
// ...
View view = null;
// We need to 'inject' our tint aware Views in place of the standard framework versions
switch (name) {
case "TextView":
view = new AppCompatTextView(context, attrs);
break;
case "ImageView":
view = new AppCompatImageView(context, attrs);
break;
case "Button":
view = new AppCompatButton(context, attrs);
break;
case "EditText":
view = new AppCompatEditText(context, attrs);
break;
case "Spinner":
view = new AppCompatSpinner(context, attrs);
break;
case "ImageButton":
view = new AppCompatImageButton(context, attrs);
break;
case "CheckBox":
view = new AppCompatCheckBox(context, attrs);
break;
case "RadioButton":
view = new AppCompatRadioButton(context, attrs);
break;
case "CheckedTextView":
view = new AppCompatCheckedTextView(context, attrs);
break;
case "AutoCompleteTextView":
view = new AppCompatAutoCompleteTextView(context, attrs);
break;
case "MultiAutoCompleteTextView":
view = new AppCompatMultiAutoCompleteTextView(context, attrs);
break;
case "RatingBar":
view = new AppCompatRatingBar(context, attrs);
break;
case "SeekBar":
view = new AppCompatSeekBar(context, attrs);
break;
}
if (view == null && originalContext != context) {
// If the original context does not equal our themed context, then we need to manually
// inflate it using the name so that android:theme takes effect.
view = createViewFromTag(context, name, attrs);
}
// ...
return view;
}
强制使用非AppCompat视图
因此,为了在使用ImageView
的同时强制创建常规AppCompatImageView
(无AppCompatActivity
),您需要指定完整的类名,例如:
<android.widget.ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/test"/>
有关布局通胀如何运作的更多信息,您可以通过LayoutInflater: Friend or Foe?的作者Chris Jenx看到令人惊叹的演讲“Calligraphy”。
答案 1 :(得分:1)
我应该从现在开始延伸一个活动吗?
否。普通组件(Activity)或Compat组件(AppCompatActivity)之间的区别在于Compat组件旨在支持旧设备中的最新UI组件。它提供了向后兼容性,因此如果您支持各种各样的设备,则需要它。
虽然我对这种行为没有特别的问题,因为它的AppCompat毕竟是
是的,你是对的,当在AppCompatActivity中使用Image视图时,普通的图像视图将被转换为AppCompatImageView。
请点击此链接阅读有关AppCompatImageView的更多信息。
答案 2 :(得分:-1)
AppCompatImageView的工作方式与ImageView相同。支持库AppCompat仅用于向后兼容。因此,如果您希望您的应用程序向后兼容,则应扩展AppCompat类。