Search code examples
android-studioandroid-recyclerviewtimepicker

TimePicker for each button inside RecyclerView


What I want to accomplish- The recyclerview has a list of apps and each row contains a button. When you click on the button, a timepicker shows up where you choose how long the countdown is for. Then the chosen time appears on the button. When you click the start button, countdowns begin and the time on the button counts down.

I have originally created a button in AppLimitScreen.java and accomplished the above without the button being inside recycler view:

public class AppLimitScreen extends AppCompatActivity {

private int numberOfInstalledApps;
private List<ApplicationInfo> apps;
private ArrayList<AppInfo> res;

//for countdown
static Button chooseTime;
static int Chour, Cminute;
static TimePickerDialog timePickerDialog;
DialogFragment dialogFragment;
private CountDownTimer mCountDownTimer;
static ImageView image;

private Button mButtonStart;

private List<AppLimit> appLimitList = new ArrayList<>();
private RecyclerView recyclerView;
private AppLimitAdapter alAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_app_limit_screen);

    numberOfInstalledApps = getPackageManager().getInstalledApplications(0).size();
    apps = getPackageManager().getInstalledApplications(0);
    res = new ArrayList<AppInfo>();

    mButtonStart = findViewById(R.id.startTimes);

    chooseTime = (Button) findViewById(R.id.app_button1);
    image = (ImageView) findViewById(R.id.imageView1);
    image.setVisibility(View.VISIBLE);
    Chour = 0;
    Cminute = 0;

    chooseTime.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            dialogFragment = new TimePickerclass();
            dialogFragment.show(getSupportFragmentManager(), "Time Picker");
        }
    });


    mButtonStart.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            startTimer();
        }
    });
    updateCountDownText();

    recyclerView = (RecyclerView) findViewById(R.id.recycler_view);

    alAdapter = new AppLimitAdapter(appLimitList);
    RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
    recyclerView.setLayoutManager(mLayoutManager);
    recyclerView.setItemAnimator(new DefaultItemAnimator());

    recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));

    recyclerView.setAdapter(alAdapter);

    prepareAppLimitData();
}

private static long START_TIME_IN_MILLIS = 0;
private static long mTimeLeftInMillis = START_TIME_IN_MILLIS;

public static class TimePickerclass extends DialogFragment implements TimePickerDialog.OnTimeSetListener {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState){

        timePickerDialog = new TimePickerDialog(getActivity(),
                AlertDialog.THEME_HOLO_LIGHT,this,Chour,Cminute,true);

        //  timePickerDialog4.setButton(DialogInterface.BUTTON_POSITIVE, "Start", timePickerDialog4);

        return timePickerDialog;
    }

    public void onTimeSet(TimePicker view, int hourOfDay, int minute){

        chooseTime.setText(hourOfDay + "h " + minute + "m" + " 00s");
        START_TIME_IN_MILLIS = (hourOfDay * 3600000) + (minute * 60000);
        mTimeLeftInMillis = START_TIME_IN_MILLIS;
        image.setVisibility(View.INVISIBLE);
    }
}

private void updateCountDownText() {

    int hours = (int) ((mTimeLeftInMillis / 1000) / 60) / 60;
    int minutes = (int) (mTimeLeftInMillis / 1000) / 60;
    int seconds = (int) (mTimeLeftInMillis / 1000) % 60;
    if (minutes > 59) {
        minutes = (minutes % 60);
        hours += (minutes / 60);
    }

    String timeLeftFormatted = String.format(Locale.getDefault(), "%02dh %02dm %02ds", hours, minutes, seconds);
    chooseTime.setText(timeLeftFormatted);

    if (hours != 0 || minutes != 0 || seconds != 0) {
        image.setVisibility(View.INVISIBLE);
        chooseTime.setClickable(false);
    }
    else {
        image.setVisibility(View.VISIBLE);
        chooseTime.setClickable(true);
        chooseTime.setText("");
    }
}


private void startTimer() {

    mCountDownTimer = new CountDownTimer(mTimeLeftInMillis, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            mTimeLeftInMillis = millisUntilFinished;
            updateCountDownText();
        }

        @Override
        public void onFinish() {}
    }.start();

}

private void prepareAppLimitData() {
    AppLimit appLimit;

    for (int i = 0; i < apps.size(); i++) {
        if (getPackageManager().getLaunchIntentForPackage(apps.get(i).packageName) != null) {
            // Non-System App
            ApplicationInfo p = apps.get(i);
            AppInfo newInfo = new AppInfo();
            newInfo.appname = p.loadLabel(getPackageManager()).toString();
            newInfo.icon = p.loadIcon(getPackageManager());
            res.add(newInfo);
            appLimit = new AppLimit(newInfo.appname, newInfo.icon);
            appLimitList.add(appLimit);
        } else {
            // System Apps
        }
    }

    alAdapter.notifyDataSetChanged();
} 
}

Then I created the recyclerview and included a button for each row. The code for the AppLimitAdapter is shown below:

public class AppLimitAdapter extends RecyclerView.Adapter<AppLimitAdapter.MyViewHolder> {
private List<AppLimit> appLimitList;
private Context context;

public AppLimitAdapter(Context context) {
    this.context = context;
}


public class MyViewHolder extends RecyclerView.ViewHolder { 
    public TextView name;
    public ImageView icon;
    public Button button;
    public ImageView image;


    public MyViewHolder(View view) {
        super(view);

        name = (TextView) view.findViewById(R.id.name);
        icon = (ImageView) view.findViewById(R.id.icon);
        image = (ImageView) view.findViewById(R.id.imageTimer);
        button = (Button) view.findViewById(R.id.button);
    }
}

public AppLimitAdapter(List<AppLimit> appLimitList) {
    this.appLimitList = appLimitList;
}


@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.app_limit_list_row, parent, false);

    return new MyViewHolder(itemView);
}

@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
    AppLimit appLimit = appLimitList.get(position);
    holder.name.setText(appLimit.getName());
    holder.icon.setImageDrawable(appLimit.getIcon());
    holder.button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            // when each button is clicked, action goes here

        }
    });

}


@Override
public int getItemCount() {
    return appLimitList.size();
}

@Override
public int getItemViewType(int position) {
    return position;
}
}

I have tried copying the code from AppLimitScreen.java and placing it inside onClick within onBindViewHolder, but I get errors and I'm sure there's a better way to do this.

How should I implement this?


Solution

  • What I want to accomplish- The recyclerview has a list of apps and each row contains a button. When you click on the button, a timepicker shows up where you choose how long the countdown is for. Then the chosen time appears on the button. When you click the start button, countdowns begin and the time on the button counts down.