课程 3: 图片和外观改善

2017-12-25  本文已影响0人  HsuJin

这节课是 Android 开发(入门)课程 的第二部分《多屏幕应用》的第三节课,导师依然是 Jessica Lin 和 Katherine Kuan,这节课完成了 Miwok App 的以下几点内容:

课程 3 的重点是灵活运用面对新需求时的代码变更策略

当 App 有新需求时,尤其是重大变更时,要养成逐步验证的习惯,不要等到多项修改,甚至完全改完再验证,如果此时发现 bug 将很难定位。既然要分步骤完成,那么作为开发者就应该知道如何安排代码变更的优先级。

针对 Miwok App 要增加图片的需求,分四个步骤来完成。

  1. 首先修改 list_item.xml,添加一个 ImageView,暂时使用 @mipmap/ic_launcher 作为占位符数据来查看效果。
  2. 等拿到图片 Assets 后,放到 app/res/drawable 目录下就把资源加入 App 工程中了,这里留意到 drawable 分为带后缀的几个目录,不同文件夹存放不同分辨率的图片,Android App 会针对不同屏幕分辨率的设备显示不同目录下的图片,如下图所示,中等分辨率的设备会对应显示 drawable-mdpi 目录下的图片文件。

在设计各个分辨率的图片时,可以参考以下独立像素 (dp) 与像素 (px) 的换算关系。

  1. 布局修改好,同时资源准备好后,修改 Word 类将图片相关的 state 和 method 添加进来,注意这里存储图片的 ID 比直接将图片存入 Word 会更节省资源,代码如下:
// 声明一个 private 内部变量(m)用于存储图片的 ID
private int mImageResourceId;
// 添加一个构造函数,名字与类完全相同,无返回值
// 因为 PhrasesActivity 不含图片,所以为其他三个 Activity 添加一个三个输入参数的构造函数
/**
* Create a new Word object.
*
* @param defaultTranslation is the word in a language that the user is already familiar with
*                           (such as English)
* @param miwokTranslation   is the word in the Miwok language
* @param imageResourceId    is the drawable resource ID for the image assets
*/
public Word(String defaultTranslation, String miwokTranslation, int imageResourceId) {
   mDefaultTranslation = defaultTranslation;
   mMiwokTranslation = miwokTranslation;
   mImageResourceId = imageResourceId;
}
// 图片 ID 对应的 getter method,访问修饰符为 public
public int getmImageResourceId() {
   return mImageResourceId;
}
  1. 最后修改 WordAdapter 将保存了图片 ID 的 Word 数据传入 WordAdapter 。在 getView method 内添加以下代码即可,用到了 setImageResource method。
// Find the ImageView in the list_item.xml layout with the ID image
ImageView imageView = listItemView.findViewById(R.id.image);
// Get the image resource ID from the current Word object and
// set this text on the image ImageView
imageView.setImageResource(currentWord.getmImageResourceId());

但是在 PhrasesActivity 中由于没有图片,所以视图会产生错误。修复此问题可以为 PhrasesActivity 新建一个 Adapter,与其他三个 Activity 的分开,但是如此一来两个 Adapter 的逻辑有较多重复。为了精简代码,所以修改 WordAdapter 适配两种 Activity 是更好的方案。通过 if/else 判断 Activity 是否含有图片,并利用 setVisibility 属性来控制图片的显示。

In Word.java

// 首先设置一个常量,默认无图片
// static 表示变量与类相关,而不是与类的对象相关,使用时格式例如 View.VISIBLE
// 修饰符 (modifier) final 表示值不可变,即常量,对此赋值 Java 会报错,在 Java 中大写
private static final int NO_IMAGE_PROVIDED = -1;

// 将 mImageResourceId 初始化为无图片
private int mImageResourceId = NO_IMAGE_PROVIDED;

// 新建一个 method 判断是否有图片
// 当图片 ID 不等于 -1 时,返回值 true,表示有图片
// 当图片 ID 等于 -1 时,返回值 false,表示无图片
/**
* Return whether or not there is an image for this word.
*/
public boolean hasImage() {
   return mImageResourceId != NO_IMAGE_PROVIDED;
}

In WordAdapter.java

// 调用 hasImage() 判断是否传入有图片
// 若真,将图片 ID 设置到 ImageView,同时设置 ImageView 为 VISIBLE
// 若假,设置 ImageView 为 GONE,不显示图片且不占位
// Find the ImageView in the list_item.xml layout with the ID image
ImageView imageView = listItemView.findViewById(R.id.image);
if (currentWord.hasImage()) {
   // Get the image resource ID from the current Word object and
   // set this text on the image ImageView
   imageView.setImageResource(currentWord.getmImageResourceId());
   // Make sure the view is visible
   imageView.setVisibility(View.VISIBLE);
} else {
   // Otherwise hide the ImageView to the image resource specified in the current Word.
   imageView.setVisibility(View.GONE);
}

至此,Miwok App 增加图片的需求分四个步骤完成了。

接下来介绍如何在应用同一个 Layout 的不同 Activity 实现不同的 Layout Attribute,针对 Miwok App 而言是修改四个 Activity 中 Text Container 的背景颜色。最恰当的方法是将颜色 ID 存在 WordAdapter 中,代码如下。

// 首先声明一个存储颜色 ID 的变量
private int mColorResourceId;
// 修改 WordAdapter 的构造函数,将颜色 ID 输入进来并赋值给相应变量
/**
* This is our own custom constructor (it doesn't mirror a superclass constructor).
* The context is used to inflate the layout file, and the list is the data we want
* to populate into the lists.
*
* @param context              The current context. Used to inflate the layout file.
* @param words                A List of Word objects to display in a list
* @param colorResourceId The background color ID of the LinearLayout of the two words in a list
*/
public WordAdapter(Context context, ArrayList<Word> words, int colorResourceId) {
   // Here, we initialize the ArrayAdapter's internal storage for the context and the list.
   // the second argument is used when the ArrayAdapter is populating a single TextView.
   // Because this is a custom adapter for two TextViews, the adapter is not
   // going to use this second argument, so it can be any value. Here, we used 0.
   super(context, 0, words);
   mColorResourceId = colorResourceId;
}
// 取得颜色 ID 后在 getView 中将它应用到相应的属性 setBackgroundColor 中
// Set the theme color for the list item
View textContainer = listItemView.findViewById(R.id.text_container);
// Find the color that the resource ID maps to
int color = ContextCompat.getColor(getContext(), mColorResourceId);
// Set the background color of the text container View
textContainer.setBackgroundColor(color);

这节课的内容不多,主要讲了面对新需求时的两种代码变更策略,并通过 Miwok App 实践了第二种策略。后续的课程也会延续这种思路,有越来越开放的趋势,包括有在讲解知识点之前要求学员自行找资料尝试 coding 再回来看视频教程的,也在很多要求学员思考并写下来的小练习。这种主动学习会很有意思。

上一篇下一篇

猜你喜欢

热点阅读