Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Android Android Lists and Adapters (2015) Lists with RecyclerViews Using a Layout Manager

How to add "Now" in the timeLabel?

Hello Everyone!

I wanted to add a Now in the timeLabel for current time. Pretty much the same way we did for the Day class to add "Today". I tried to put the if-else block in the bindHour method but it doesn't have the position value.

Can anyone help me out?

1 Answer

Boban Talevski
Boban Talevski
24,793 Points

I see this didn't get an answer for a while and it's an interesting feature which I guess comes to mind naturally after implementing the same thing with the ListView, though it's a bit trickier here.

So, for anyone interested about this, I guess there are various solutions. The very simple but not so elegant one seems to be this: HourAdapter.java

package com.example.bobantalevski.stormy.adapters;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.bobantalevski.stormy.R;
import com.example.bobantalevski.stormy.weather.Hour;

import butterknife.BindView;
import butterknife.ButterKnife;

/**
 * Created by Boban Talevski on 9/20/2017.
 */

public class HourAdapter extends RecyclerView.Adapter<HourAdapter.HourViewHolder> {

    private Hour[] hours;

    public HourAdapter(Hour[] hours) {
        this.hours = hours;
    }

    @Override
    public HourViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.hourly_list_item, parent, false);
        HourViewHolder viewHolder = new HourViewHolder(view);

        return viewHolder;
    }

    @Override
    public void onBindViewHolder(HourViewHolder holder, int position) {
        if (position == 0) {
            holder.bindHourNow(hours[position]);
        } else {
            holder.bindHour(hours[position]);
        }
    }

    @Override
    public int getItemCount() {
        return hours.length;
    }

    public class HourViewHolder extends RecyclerView.ViewHolder {

        @BindView(R.id.timeLabel) TextView timeLabel;
        @BindView(R.id.summaryLabel) TextView summaryLabel;
        @BindView(R.id.temperatureLabel) TextView temperatureLabel;
        @BindView(R.id.iconImageView) ImageView iconImageView;

        public HourViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }

        public void bindHour(Hour hour) {
            timeLabel.setText(hour.getHour());
            summaryLabel.setText(hour.getSummary());
            temperatureLabel.setText(Integer.toString(hour.getTemperature()));
            iconImageView.setImageResource(hour.getIconId());
        }

        public void bindHourNow(Hour hour) {
            timeLabel.setText("Now");
            summaryLabel.setText(hour.getSummary());
            temperatureLabel.setText(Integer.toString(hour.getTemperature()));
            iconImageView.setImageResource(hour.getIconId());
        }
    }
}

So, we have to start at a point where we can access the index/position to check if it's zero. The only place where we have this option is in the onBindViewHolder method. Then, inside that method, we check for that condition and depending on whether it's zero or not, we either call the usual bindHour method inside the HourViewHolder class, or if it's indeed zero, we call a special newly created "bindHour type" method called bindHourNow, which exists only for this purpose (hence the not so elegant solution assumption). In that specific method we just set the timeLabel text to "Now" and set the other views as usual.

Now, this can be maybe improved in a way to modify the bindHour method to accept a second boolean argument (isZero) which we will pass from the onBindViewHolder method depending on whether the position is zero or not, and depending on that argument we set the timeLabel text to either "Now" or the actual value inside the hour object without the need for creating a special new method for this purpose.

Both of these options are working for this particular project and the data we have. This is the second (assumingly more elegant) way:

package com.example.bobantalevski.stormy.adapters;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.bobantalevski.stormy.R;
import com.example.bobantalevski.stormy.weather.Hour;

import butterknife.BindView;
import butterknife.ButterKnife;

/**
 * Created by Boban Talevski on 9/20/2017.
 */

public class HourAdapter extends RecyclerView.Adapter<HourAdapter.HourViewHolder> {

    private Hour[] hours;

    public HourAdapter(Hour[] hours) {
        this.hours = hours;
    }

    @Override
    public HourViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.hourly_list_item, parent, false);
        HourViewHolder viewHolder = new HourViewHolder(view);

        return viewHolder;
    }

    @Override
    public void onBindViewHolder(HourViewHolder holder, int position) {
        holder.bindHour(hours[position], position == 0);
    }

    @Override
    public int getItemCount() {
        return hours.length;
    }

    public class HourViewHolder extends RecyclerView.ViewHolder {

        @BindView(R.id.timeLabel) TextView timeLabel;
        @BindView(R.id.summaryLabel) TextView summaryLabel;
        @BindView(R.id.temperatureLabel) TextView temperatureLabel;
        @BindView(R.id.iconImageView) ImageView iconImageView;

        public HourViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }

        public void bindHour(Hour hour, boolean isZero) {
            timeLabel.setText(isZero ? "Now" : hour.getHour());
            summaryLabel.setText(hour.getSummary());
            temperatureLabel.setText(Integer.toString(hour.getTemperature()));
            iconImageView.setImageResource(hour.getIconId());
        }
    }
}

We just have to realize that (some of) these methods and arguments are not set in stone and one can assume that onBindViewHolder is called by the android system, so we probably can't mess with its arguments. But bindHour on the other hand, seems to exist only for the purpose of being called from onBindViewHolder and if we add a second method of that type, or change its arguments, we can do this as long as we don't break the core functionality which is to populate the views for a particular list item with the appropriate data from our data model.