为什么Android没有明确声明它们时selectAppCompat组件?

我正在debugging我的应用程序,发现徘徊在一个ImageView引用,它是一个AppCompatImageView而不是一个ImageViewTextView (和AppCompatTextView )一样。

在这里输入图像说明

虽然我没有特别的问题,因为它的AppCompat毕竟,但是当检查开发人员的代码时,我看到extends Activity而不是AppCompatActivity ,我几乎把它标记为“坏习惯”。

另一方面,在处理vector图像时,我使用的是ImageView ,因为我没有使用AppCompatImageView并使用它是解决scheme:

ImageView在设备中无法正确显示

这种不一致的行为让我很难理解我应该遵循的做法。 我是否应该从现在开始的活动中延伸?

Solutions Collecting From Web of "为什么Android没有明确声明它们时selectAppCompat组件?"

简短的回答“我应该从现在开始的活动延伸?” 是否,您应该继续扩展AppCompatActivity因为它向旧设备提供了向后兼容的function。 在AppCompatImageView的情况下:

支持旧版本平台兼容function的ImageView,包括:

  • 通过ViewCompat中的背景色调方法允许其背景的dynamic色调。
  • 允许使用backgroundTint和backgroundTintMode设置背景色调。
  • 通过ImageViewCompat中的图像色调方法允许其图像的dynamic色调。
  • 允许使用tint和tintMode设置图像色调。

此外,它还增加了旧版Android版本的vector绘制兼容性。

关于不一致的解释

正如它在AppCompatImageView所解释的:

当您在布局中使用ImageView时,会自动使用此function,而顶级活动/对话框由appcompat提供。

所以,这并不意外。

怎么运行的

AppCompatActivity会安装一个LayoutInflater.Factory2来拦截某些视图的通货膨胀。 这个inflater的代码可以在AppCompatViewInflater.java中看到。

负责创buildViews的函数是AppCompatViewInflater#createView(View, String, Context, AttributeSet, boolean, boolean, boolean, boolean) ,正如你在这里看到的,它检查简单的视图名称(不包括它的前缀)创buildAppCompat*版本:

 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视图

因此,为了在仍然使用AppCompatActivity下强制创build常规的ImageView (无AppCompatImageView ),您需要指定完整的类名称,例如:

  <android.widget.ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/test"/> 

有关布局通货膨胀如何运作的更多信息,您可以看到由书法作者Chris Jenx所作的 “ LayoutInflater:朋友还是敌人?

我是否应该从现在开始的活动中延伸?

正常组件(Activity)或Compat组件(AppCompatActivity)之间的区别在于,Compat组件旨在支持旧版设备中的最新UI组件。 这是它提供了向后兼容性 ,所以如果你支持大量的设备,你将需要它。

虽然我不特别有这个问题,因为它的AppCompat毕竟

是的,你是正确的,当从一个AppCompatActivity中使用一个图像视图,一个正常的图像视图将被转换为AppCompatImageView。

AppCompatImageView

按照此链接阅读更多关于AppCompatImageView。

AppCompatImageView的工作方式与ImageView相同。 支持库AppCompat只是为了向后兼容。 所以,如果你想让你的应用程序向后兼容,你应该扩展AppCompat类。

appcompactActivity意味着你的应用程序代替使用设备本地库,它将使用编译后在你的应用程序中添加的支持库。 对自己没有图书馆的旧设备有好处。 当您使用支持库时,您可以轻松地将库添加到应用程序中,也可以在旧设备中运行。