我在调试我的应用程序时,将鼠标悬停在ImageView
引用上时发现,它是AppCompatImageView
而不是ImageView
。 TextView
(带有AppCompatTextView
)也发生了同样的情况。
尽管我的行为并没有特别的问题,因为毕竟它是AppCompat的,但是在检查其他开发人员的代码时,我看到的是extends Activity
而不是AppCompatActivity
,并且我几乎将其标记为“不好的做法”。
另一方面,在处理矢量图像时,我使用的是ImageView
,但由于没有使用AppCompatImageView
而使用了解决方案,因此出现了问题:
ImageView not displaying correctly in the device
这种不一致的行为确实使我对我应该遵循的做法感到困惑。从现在开始,我应该只是从一个 Activity 中扩展吗?
最佳答案
简短的回答:“从现在开始,我应该只是从一个 Activity 中扩展吗?”是,您应该继续扩展AppCompatActivity
,因为它为较旧的设备提供了向后兼容的功能。如果是 AppCompatImageView
:
此外,它还为旧版Android增加了与矢量可绘制对象的兼容性。
有关不一致的说明
如 AppCompatImageView
中所述:
因此,这并不意外。
工作原理AppCompatActivity
安装LayoutInflater.Factory2
来拦截某些 View 的膨胀。该充气机的代码可以在AppCompatViewInflater.java中看到。
负责创建Views
的函数是AppCompatViewInflater#createView(View, String, Context, AttributeSet, boolean, boolean, boolean, boolean)
,正如您在此处看到的那样,它检查简单的 View 名称(不带包前缀),并创建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 View
因此,为了在仍然使用
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”。
关于android - 当我没有明确声明它们时,为什么Android选择AppCompat组件?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45710962/