安卓学习日志 — Day04

概述

继续构建Miwok应用,上次已经成功在四个页面显示了 每个词汇的 两个语言版本

接下来将在每个列表项中为 词汇添加图片 ,最后,对页面进行一下美化,即 将每个页面中列表项的背景色改为 该页面的主题色

目标

  • 图片资源添加
  • 页面外观改善(列表项的背景色等)

最终的效果,是这样(Phrases 页面不需要添加图片,因为没有合适的图片来表达短语):

在这里插入图片描述

实现步骤

更改布局

修改列表项的布局,预留一个应用显示词汇图片的区域:

最终的列表项布局分为左右两部分,左边为该词汇的图片,右边则显示词汇的 Miwok 和 English 语言版本。

而右边的显示词汇部分,又可以分为上下两部分:上面是Miwok版本、下面是English版本。

因此可以考虑使用一个水平的线性布局,再嵌套一个垂直的线性布局来实现:

在这里插入图片描述

添加图片资源

首先,将所有的图片文件 放到 资源目录下 的 drawable 文件夹当中,这里就不再截图了。

每个单词都有一个对应的图片( Phrases 页面没有),那么将图片资源的id 封装的每个 Word对象当中是一个可行的策略。

这样 就可以根据每个 Word对象的 图片资源 id 来这 列表项中的图片了。

更改 Word 类如下:为其添加一个成员变量来记录图片资源的id ,以及该成员变量的 Getter 方法:

public class Word {
    
    
    
    // …………
    
    /**
     * Image resource is for the word
     */
    private int imageResourceId = NO_IMAGE_PROVIDED;

    /**
     * Constant value that represents no image was provided for this word
     */
    private static final int NO_IMAGE_PROVIDED = -1;
    
    /**
     * 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
     */
    public Word(String defaultTranslation, String miwokTranslation) {
    
    
        this.defaultTranslation = defaultTranslation;
        this.miwokTranslation = miwokTranslation;
    }
    
    /**
     * 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 associated with the word
     * @param audioResourceId    is the audio resource id with the word
     */
    public Word(String defaultTranslation, String miwokTranslation, int imageResourceId) {
    
    
        this.defaultTranslation = defaultTranslation;
        this.miwokTranslation = miwokTranslation;
        this.imageResourceId = imageResourceId;
    }
    
    /**
     * Get the image resource is for the word
     */
    public int getImageResourceId() {
    
    
        return imageResourceId;
    }
        
    /**
     * Returns whether or not there is an image for this word.
     */
    public boolean hasImage() {
    
    
        return imageResourceId != NO_IMAGE_PROVIDED;
    }
        
}       
        
  • 9 行,添加一个 int 类型 的成员变量,用于存储每个单词 的 图片资源ID,默认初始化为 常量 NO_IMAGE_PROVIDED
  • 14 行,常量 NO_IMAGE_PROVIDED,图片资源id的默认值 -1,用于表示没有图片
  • 23 ~ 26 行,原有的构造函数,接受 Miwok 和 English 的字符串参数
  • 37 ~ 41 行,新增的构造函数,将 图片资源id 加入到 Word 类的构造函数当中
  • 46 ~ 48 行,图片资源id 的 Getter 方法
  • 53 ~ 55 行,新增一个方法,用于判断该词汇有无图片资源需要被显示。

这里有两个构造函数,一个接收 图片资源id,而另一个不接收,因为 Phrases 页面不需要显示图片,而 其他几个页面需要显示图片。

现在 , 当我们创建一个 Word 对象时,即可传入该词汇的 图片id。

将每个页面的 onCreate 方法中 构建的数据来源 (ArrayList 对象),加入每个词汇 的 图片资源id:

比如在 NumbersActivity.java 文件的 onCreate 方法中为每个 Word 对象 传入 图片资源id:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_numbers);
        setContentView(R.layout.word_list);
        
        // Create a array list of words
        ArrayList<Word> words = new ArrayList<Word>();
        words.add(new Word("one", "lutti",
                R.drawable.number_one, R.raw.number_one));
        words.add(new Word("two", "otiiko",
                R.drawable.number_two, R.raw.number_two));
        words.add(new Word("three", "tolookosu",
                R.drawable.number_three, R.raw.number_three));
        words.add(new Word("four", "oyyisa",
                R.drawable.number_four, R.raw.number_four));
        words.add(new Word("five", "massokka",
                R.drawable.number_five, R.raw.number_five));
        words.add(new Word("six", "temmokka",
                R.drawable.number_six, R.raw.number_six));
        words.add(new Word("seven", "kenekaku",
                R.drawable.number_seven, R.raw.number_seven));
        words.add(new Word("eight", "kawinta",
                R.drawable.number_eight, R.raw.number_eight));
        words.add(new Word("nine", "wo’e",
                R.drawable.number_nine, R.raw.number_nine));
        words.add(new Word("ten", "na’aacha",
                R.drawable.number_ten, R.raw.number_ten));
        
        // …………
    }

修改适配器

现在数据来源的 每个 Word 对象当中已经有各自的图片资源id ,接下来就需要 让我们适配器通过其图片资源id 先对应的图片到列表项当中。

因此 在适配器 WordAdaptergetView 方法中添加以下代码:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
    
    
        
        // …………
        
        // Find the ImageView in the list_item.xml layout with the ID image.
        ImageView imageView = (ImageView) itemView.findViewById(R.id.image);
        // Check if an image is provided for this word or not
        if (currentWord.hasImage()) {
    
    
            // If an image is available, display the provided image based on the resource ID
            imageView.setImageResource(currentWord.getImageResourceId());
            // Make sure the view is visible
            imageView.setVisibility(View.VISIBLE);
        } else {
    
    
            // Otherwise hide the ImageView (set visibility to GONE)
            imageView.setVisibility(View.GONE);
        }
     
        return itemView;
    }
  • 7 行,获取用于显示图片的 视图对象
  • 9 行,判断 当前的词汇是否需要显示图片。
  • 11 ~ 13 行,获取要显示的图片资源id,并将其显示到对应的视图对象当中
  • 14 ~ 17 行,不需要显示图片,则将预留的图片显示区域隐藏起来(针对Phrases页面)

列表项图片的添加基本完成,并且在 9 ~ 17 行的 if-else 语句中通过判断是否有图片资源,来显示或隐藏显示图片的视图区域,这样就使得 Phrase 页面 和 其他页面 都能显示正确的内容。

列表项背景色

每个页面的列表项都有不同的背景颜色,而每个页面的列表项都是由单独 的适配器所控制,因此,可考虑将每个页面的背景色id 封装到 各自的 适配器当中,这样每个页面的适配器就可以根据各自的背景色id 来实现 每个页面各自的背景色。

因此 在适配器 WordAdaptergetView 方法中添加以下代码:

public class WordAdapter extends ArrayAdapter<Word> {
    
    

    /**
     * Resource ID for the background color for this list of words
     */
    private int colorResourceId;

    /**
     * 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
     */
    public WordAdapter(Activity 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 and an ImageView, the adapter is not
        // going to use this second argument, so it can be any value. Here, we used 0.
        super(context, 0, words);
        this.colorResourceId = colorResourceId;
    }
    
    /**
     * Provides a view for an AdapterView (ListView, GridView, etc.)
     *
     * @param position    The position in the list of data that should be displayed in the
     *                    list item view.
     * @param convertView The recycled view to populate.
     * @param parent      The parent ViewGroup that is used for inflation.
     * @return The View for the position in the AdapterView.
     */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
    
    
        
        // ………………

        // Set the theme color for the list item
        View textContainer = itemView.findViewById(R.id.text_container);
        // Find the color that the resource ID maps to
        int color = ContextCompat.getColor(getContext(), colorResourceId);
        // Set the background color of the text container View
        textContainer.setBackgroundColor(color);

        // Return the whole list item layout (containing 2 TextViews)
        // so that it can be shown in the ListView
        return itemView;
    }
}
  • 6 行,定义一个成员变量,用过存储每个页面 列表项背景色的 id
  • 16 ~ 23 行,修改构造函数,传入 每个页面 列表项背景色的 id 值
  • 40 行,获取用于设置背景色的视图对象,即列表项右边部分用于显示词汇的区域
  • 42 ~ 44 行,获取页面的 列表项背景色的id值,并显示到对应的区域。

至此,每个页面的列表项图片显示,与页面主题也就全部完成了。

最终完成效果也和,预想的一样:

在这里插入图片描述

总结

这次的学习并没有太多的新知识,更多的是 遇到问题后应该如何去解决它。

并且当我们在更改一个应用时,或许需要同时改动多个文件,这期间会出现各种各样的错误。

因此,可以尝试 先做应用中 风险最大的更改,这样,如果初始策略行不通,我们将能够及时的 更改策略。

参考

Using an ArrayAdapter with ListView

What Are Adapters in Android

Performance Tips for Android’s ListView

关于如何为你的类提供构造函数的文档

View.setVisibility(int)

猜你喜欢

转载自blog.csdn.net/weixin_45075891/article/details/112455142