美文网首页
课程 3: 图片和外观改善

课程 3: 图片和外观改善

作者: HsuJin | 来源:发表于2017-12-25 21:04 被阅读0次

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

    • Add all the images to the app.
    • Display correct images for each word in the list.
    • Add visual polish.

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

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

    • 策略一:首先做风险最大、难度最高的更改,来验证整体概念的可行性。
      (Do the riskiest parts first to demonstrate proof of concept)
    • 策略二:根据目前拥有的资源或数据来安排,此时需要用到占位符数据。即在设计师给出最终图片、媒体文件、文本等资源(Assets)之前,使用虚拟数据放在 App 中大致了解更改的效果。
      (Implement what you can based on the available data. Use palceholder data / dummy data)

    针对 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 再回来看视频教程的,也在很多要求学员思考并写下来的小练习。这种主动学习会很有意思。

    相关文章

      网友评论

          本文标题:课程 3: 图片和外观改善

          本文链接:https://www.haomeiwen.com/subject/mnalgxtx.html