Day 28 - [Android APP] 06-RecyclerView与资料显示

这几天我们已经从 API 取得资料到包装成物件,再来就是资料显示罗。

这两天的范例会以对话页面为主,也会用到之前设计的 Chat 物件。今天要介绍把对话资料显示到 RecyclerView 上面。

View

Activity 和 Adapter 在 MVVM 属於 View 的范畴,用来显示资料,不过他们负责的部分还是有点差别。Activiy 负责跟ViewModel 取得资料,把 List 的资料给 Adapter,还有所有点击的监听器。Adapter 只负责将接到的资料显示到 RecyclerView 上。

物件间的关系图,可以参考 [[Android APP] 01-架构介绍-MVVM]。

ChatActivity

OptionClickCallback optionClickCallback = new OptionClickCallback() {
    @Override
    public void onOptionClick(Option option) {
        mViewModel.sendOptionMessage(option, categoryId);
    }

    @Override
    public void noneOfAbove(Option option) {
        mViewModel.sendOptionMessage(option, categoryId);
    }
};
ChatAdapter mChatAdapter = new ChatAdapter(ChatActivity.this, chatArrayList,
        optionClickCallback);
mRecyclerView.setLayoutManager(new LinearLayoutManager(ChatActivity.this));
mRecyclerView.setAdapter(mChatAdapter);
mRecyclerView.scrollToPosition(mChatAdapter.getItemCount() - 1);

new ChatAdapter(ChatActivity.this, chatArrayList, optionClickCallback); 这行就是要将整包的资料设置给 Adapter,并且把「回馈按钮」的监听器也一起给 Adapter。

ChatAdapter

private final Context mContext;
private final ArrayList<Chat> mChatList;
private final OptionClickCallback mOptionClickCallback;

public ChatAdapter(Context context, ArrayList<Chat> chatList, OptionClickCallback optionClickCallback) {
    this.mContext = context;
    this.mChatList = chatList;
    this.mOptionClickCallback = optionClickCallback;
}

一开始,我们需要一些变数和建构子(Constructor)储存资料。

private static class RecyclerViewViewHolder extends RecyclerView.ViewHolder {
    ImageView icon;
    TextView text, option_message;
    ConstraintLayout constraintLayout;
    LinearLayout optionsArea, options;
    Button opt1, opt2, opt3;

    public RecyclerViewViewHolder(@NonNull View itemView) {
        super(itemView);

        icon = itemView.findViewById(R.id.img);
        text = itemView.findViewById(R.id.text);
        option_message = itemView.findViewById(R.id.option_message);
        constraintLayout = itemView.findViewById(R.id.constraint_layout);
        optionsArea = itemView.findViewById(R.id.options_area);
        options = itemView.findViewById(R.id.options);
        opt1 = itemView.findViewById(R.id.option1);
        opt2 = itemView.findViewById(R.id.option2);
        opt3 = itemView.findViewById(R.id.option3);
    }
}

还需要一个 ViewHoder 用来 bind RecyclerView item 里的物件。

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
    Chat chat = mChatList.get(position);
    RecyclerViewViewHolder viewHolder = (RecyclerViewViewHolder) holder;

    viewHolder.icon.setImageResource(chat.getIcon());
    viewHolder.text.setText(chat.getText());

    // 奇数列,底色改灰色
    if (position % 2 != 0) {
        viewHolder.constraintLayout.setBackgroundColor(ContextCompat.getColor(mContext, R.color.list_background));
    }

    // 有选项的 Chat,才显示 Option 区块
    if (mChatList.get(position).getOptions().size() < 1) {
        viewHolder.optionsArea.setVisibility(View.GONE);
    } else {
        // 取得所有 Option
        ArrayList<Option> options = mChatList.get(position).getOptions();

        // 设置选项的文字
        viewHolder.opt1.setText(options.get(0).getQuestion());
        viewHolder.opt2.setText(options.get(1).getQuestion());
        viewHolder.opt3.setText(options.get(2).getQuestion());

        // 设置三个选项的监听器
        viewHolder.opt1.setOnClickListener(v -> mOptionClickCallback.onOptionClick(options.get(0)));
        viewHolder.opt2.setOnClickListener(v -> mOptionClickCallback.onOptionClick(options.get(1)));
        viewHolder.opt3.setOnClickListener(v -> mOptionClickCallback.noneOfAbove(options.get(2)));

        // 选项显示的开关,预设 Gone
        viewHolder.option_message.setOnClickListener(v -> {
            if (viewHolder.options.getVisibility() == View.GONE) {
                viewHolder.options.setVisibility(View.VISIBLE);
            } else {
                viewHolder.options.setVisibility(View.GONE);
            }
        });
    }
}

最後把对话讯息的文字、回馈按钮的内容都设置上去,今天就完工罗!!


本文同步发布在: https://dreambo4.github.io/2021/10/12/Android-APP-06-RecyclerView%E8%88%87%E8%B3%87%E6%96%99%E9%A1%AF%E7%A4%BA/


<<:  JS 27 - 平滑滚动,让视窗不再是闪电侠!

>>:  Day 27 - 3D绘图篇 - 2D图片上面的3D物件是怎麽产生的? I - 成为Canvas Ninja ~ 理解2D渲染的精髓

Angular 转换 API 资料格式 (Adapter)

今天的内容属於设计模式的一种。 当我们从後端接到资料後,有时後资料格式往往不是如我们所想,所以会再加...

Golang 转生到web世界 - gin Middleware中间件

Golang Golang gin Middleware中间件 我第一次接触Middleware这个...

Day02 何谓Django?

我们都要谈Django了,总不能连他是什麽都不知道吧? 那既然你都诚心诚意地发问了,那我就大发慈悲地...

第4砍 - 蓄势待发

今晚我想来点... 麻而不辣的 linker script [叮咚] 您的外送餐点到瞜, 已经依照您...

【课程推荐】2021/3/13~3/14 软件需求塑模与需求规格文件撰写实务班

课程目标 了解系统分析实务、系统分析工具之应用、逻辑资料库设计技巧、系统分析产出文件、同仁审查等,以...