0

I'm creating an alarm clock application that has a list of alarms on the MainActivity, much like the default Android Clock application. To do this, I've implemented a ListView, which is displaying well. However, I've been trying to set up an Update button on the ListView to allow me to update an alarm's details via my CreateAlarmActivity, using this as a guide: Intent in ListView. I've gone over it a few times, but when I press this button during testing, nothing happens. The activity simply remains where it is.

I'm sure it's probably something easy and stupid (it almost always is), but I can't seem to find my mistake. Perhaps I need something in the AlarmAdapter's onClick method, as well as the MainActivity's onItemClick?

Code:

MainActivity.java

public class MainActivity extends AppCompatActivity {

    ListView alarmListView;
    ArrayList<Alarm> alarmList = new ArrayList<Alarm>();
    AlarmAdapter alarmAdapter;

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

        alarmListView = findViewById(R.id.alarmListView);

        // Credit to Mitch Woodbright for helping with this section, and other try/catch blocks.
        try
        {
            ArrayList<Alarm> alarm = (ArrayList<Alarm>) getIntent().getSerializableExtra("alarmList");
            for(Alarm elements : alarm){
                alarmList.add(elements);
            }
        }
        catch (NullPointerException e){
            //error handling code
        }

        alarmAdapter = new AlarmAdapter(MainActivity.this, alarmList);
        alarmListView.setAdapter(alarmAdapter);
        alarmAdapter.notifyDataSetChanged();

        alarmListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Intent updateAlarmIntent = new Intent(MainActivity.this, CreateAlarmActivity.class);
                updateAlarmIntent.putExtra("alarmList", alarmList);
                updateAlarmIntent.putExtra("position", position);
                startActivity(updateAlarmIntent);


            }
        });
    }

    // Create alarm when user presses FAB on activity_main.xml.
    public void createNewAlarm(View view) {
        Intent createAlarmIntent = new Intent(this, CreateAlarmActivity.class);
        createAlarmIntent.putExtra("alarmList", alarmList);
        startActivity(createAlarmIntent);
    }


    public void testAlarmActivated(View view){
        Intent activateAlarmIntent = new Intent(this, AlarmActivatedActivity.class);
        startActivity(activateAlarmIntent);
    }
}

CreateAlarmActivity.java

public class CreateAlarmActivity extends AppCompatActivity {

    // If the alarm is being created, position = -1.
    int position = -1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_create_alarm);
        alarmList = (ArrayList<Alarm>)getIntent().getSerializableExtra("alarmList");

        try {
            // If we're updating an alarm, return the position of the alarm to update.
            position = (int)getIntent().getSerializableExtra("position");
        }
        // Else, keep going.
        catch (NullPointerException e){

        }
    }

    int alarmHour = 6;
    int alarmMinute = 0;
    boolean isPm = false;
    int snoozeTimer = 10;
    int [] daysActive = new int[] {0, 0, 0, 0, 0, 0, 0};

    ArrayList<Alarm> alarmList = new ArrayList<Alarm>();

    // Add one to the hour of the alarm.
    public void changeHour(View view) {
        Button btn = findViewById(R.id.buttonHours);

        if (alarmHour == 12){
            alarmHour = 0;
        }
        else {
            alarmHour++;
        }

        btn.setText(Integer.toString(alarmHour));

    }

    // Add one to the minute of the alarm.
    public void changeMinute(View view) {
        Button btn = findViewById(R.id.buttonMinutes);

        if (alarmMinute == 59) {
            alarmMinute = 0;
        }
        else {
            alarmMinute++;
        }

        if (alarmMinute < 10) {
            // Ensure minute 1 becomes 01, e.g, 6:01 am.
            btn.setText("0" + Integer.toString(alarmMinute));
        }
        else {
            btn.setText(Integer.toString(alarmMinute));
        }
    }

    public void changeAmPm(View view) {
        Button btn = findViewById(R.id.buttonAmPm);
        if (isPm == true) {
            isPm = false;
            btn.setText("am");
        }
        else {
            isPm = true;
            btn.setText("pm");
        }
    }

    public void changeSnoozeTimer(View view) {
        Button btn = findViewById(R.id.buttonSnoozeTimer);
        if (snoozeTimer == 15){
            snoozeTimer = 1;
        }
        else {
            snoozeTimer++;
        }
        btn.setText(Integer.toString(snoozeTimer));
    }

    public void finishAlarm(View view){
        EditText alarmName = findViewById(R.id.alarmName);
        String name = alarmName.getText().toString();
        Alarm alarm = new Alarm(name, alarmHour, alarmMinute, isPm, daysActive, snoozeTimer);

        // If we're creating an alarm.
        if (position == -1) {

            try {
                alarmList.add(alarm);
            } catch (Exception e) {

            }
        }

        // Else, we're updating one.
        else {
            try {
                // Set the alarm we're updating to the new alarm.
                alarmList.set(position, alarm);
            } catch (Exception e) {

            }
        }
        Intent finishAlarmIntent = new Intent(this, MainActivity.class);
        finishAlarmIntent.putExtra("alarmList", alarmList);
        startActivity(finishAlarmIntent);
    }


    public void cancelAlarm(View view){
        Intent cancelAlarmIntent = new Intent(this, MainActivity.class);
        cancelAlarmIntent.putExtra("alarmList", alarmList);
        startActivity(cancelAlarmIntent);
    }

    public void deleteAlarm(View view) {

        // If creating a new alarm, deleting is the same as cancelling.
        if (position == -1) {
            cancelAlarm(view);
        }
        else {
            // Remove the alarm.
            alarmList.remove(position);
            // Move each other alarm down one in the list.
            for (int i = position; i < alarmList.size() - 1; i++){
                Alarm tempAlarm = alarmList.get(i + 1);
                alarmList.set(i, tempAlarm);
            }
            // Eliminate last item in the list, preventing duplicates.
            alarmList.remove(alarmList.size() - 1);
        }
    }

    public void changeSunday(View view) {
        Button btn = findViewById(R.id.buttonSunday);
        if (daysActive[0] == 0){
            daysActive[0] = 1;
            // Source: https://stackoverflow.com/questions/2173936/how-to-set-background-color-of-a-view
            // Credit goes to EddieB for the below line.
            btn.getBackground().setColorFilter(Color.parseColor("#00ff00"), PorterDuff.Mode.DARKEN);
        }
        else {
            daysActive[1] = 0;
            // Source: https://stackoverflow.com/questions/14802354/how-to-reset-a-buttons-background-color-to-default
            // Credit goes to Ivo for the below line.
            btn.getBackground().clearColorFilter();
        }
    }

    public void changeMonday(View view) {
        Button btn = findViewById(R.id.buttonMonday);
        if (daysActive[1] == 0){
            daysActive[1] = 1;
            btn.getBackground().setColorFilter(Color.parseColor("#00ff00"), PorterDuff.Mode.DARKEN);
        }
        else {
            daysActive[1] = 0;
            btn.getBackground().clearColorFilter();
        }
    }

    public void changeTuesday(View view) {
        Button btn = findViewById(R.id.buttonTuesday);
        if (daysActive[2] == 0){
            daysActive[2] = 1;
            btn.getBackground().setColorFilter(Color.parseColor("#00ff00"), PorterDuff.Mode.DARKEN);
        }
        else {
            daysActive[2] = 0;
            btn.getBackground().clearColorFilter();
        }
    }

    public void changeWednesday(View view) {
        Button btn = findViewById(R.id.buttonWednesday);
        if (daysActive[3] == 0){
            daysActive[3] = 1;
            btn.getBackground().setColorFilter(Color.parseColor("#00ff00"), PorterDuff.Mode.DARKEN);
        }
        else {
            daysActive[3] = 0;
            btn.getBackground().clearColorFilter();
        }
    }

    public void changeThursday(View view) {
        Button btn = findViewById(R.id.buttonThursday);
        if (daysActive[4] == 0){
            daysActive[4] = 1;
            btn.getBackground().setColorFilter(Color.parseColor("#00ff00"), PorterDuff.Mode.DARKEN);
        }
        else {
            daysActive[4] = 0;
            btn.getBackground().clearColorFilter();
        }
    }

    public void changeFriday(View view) {
        Button btn = findViewById(R.id.buttonFriday);
        if (daysActive[5] == 0){
            daysActive[5] = 1;
            btn.getBackground().setColorFilter(Color.parseColor("#00ff00"), PorterDuff.Mode.DARKEN);
        }
        else {
            daysActive[5] = 0;
            btn.getBackground().clearColorFilter();
        }
    }

    public void changeSaturday(View view) {
        Button btn = findViewById(R.id.buttonSaturday);
        if (daysActive[6] == 0){
            daysActive[6] = 1;
            btn.getBackground().setColorFilter(Color.parseColor("#00ff00"), PorterDuff.Mode.DARKEN);
        }
        else {
            daysActive[6] = 0;
            btn.getBackground().clearColorFilter();
        }
    }

}

AlarmAdapter.java

public class AlarmAdapter extends BaseAdapter{

    private Context alarmContext;
    private ArrayList<Alarm> alarmList;

    public AlarmAdapter(Context context, ArrayList arrayList) {
        super();
        alarmContext = context;
        alarmList = arrayList;
    }

    public int getCount() {
        try{
            return alarmList.size();
        }catch(Exception e){
            return 0;
        }

    }

    // getView method is called for each item of ListView
    public View getView(int position, View view, ViewGroup parent) {
        // inflate the layout for each item of listView
        LayoutInflater inflater = (LayoutInflater) alarmContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.alarm_row, parent, false);


        // get the reference of textView and button
        TextView alarmName = (TextView) view.findViewById(R.id.listRowAlarmName);
        TextView alarmTime = view.findViewById(R.id.listRowAlarmTime);
        TextView alarmAmPm = view.findViewById(R.id.listRowAlarmAmPm);
        TextView alarmDaysActive = view.findViewById(R.id.listRowAlarmDaysActive);
        TextView alarmSnoozeTimer = view.findViewById(R.id.listRowAlarmSnoozeTimer);

        Button updateButton = (Button) view.findViewById(R.id.listRowAlarmUpdate);

        // Set the title and button name
        Alarm tempAlarm = alarmList.get(position);
        alarmName.setText(tempAlarm.name);

        // Set minute if 0-9 to 00-09.
        String minute = Integer.toString(tempAlarm.minute);
        if (tempAlarm.minute < 10){
            minute = "0" + minute;
        }
        alarmTime.setText(tempAlarm.hour + ":" + minute);

        // Set AM or PM based on Boolean.
        if (tempAlarm.isPm == true){
            alarmAmPm.setText("PM");
        }
        else {
            alarmAmPm.setText("AM");
        }
        // Figure out best way to change color of letters in text based on daysActive.
        alarmSnoozeTimer.setText("Snooze Timer: " + tempAlarm.snoozeTimer + " minutes");
        //updateButton.setText("Action " + position);

        // Click listener of button
// Do I need this, since I'm overriding it in MainActivity? Find out.
        updateButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Logic goes here.
            }
        });

        return view;
    }

    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return position;
    }}

alarm_row.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="96dp"
    android:orientation="horizontal"
    android:padding="5dip">

    <TextView
        android:id="@+id/listRowAlarmName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignParentEnd="true"
        android:layout_marginStart="10dp"
        android:layout_marginTop="5dp"
        android:layout_toEndOf="@+id/listRowAlarmAmPm"
        android:text="Name of Alarm"
        android:textSize="18sp" />

    <TextView
        android:id="@+id/listRowAlarmTime"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_marginStart="8dp"
        android:layout_marginTop="4dp"
        android:text="TIME"
        android:textSize="28sp" />

    <TextView
        android:id="@+id/listRowAlarmDaysActive"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/listRowAlarmName"
        android:layout_marginStart="10dp"
        android:layout_toEndOf="@+id/listRowAlarmAmPm"
        android:text="S M T W T F S"
        android:textSize="18sp" />

    <TextView
        android:id="@+id/listRowAlarmAmPm"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginStart="8dp"
        android:layout_marginTop="4dp"
        android:layout_toEndOf="@+id/listRowAlarmTime"
        android:text="PM"
        android:textSize="28sp" />

    <TextView
        android:id="@+id/listRowAlarmSnoozeTimer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/listRowAlarmDaysActive"
        android:layout_marginStart="10dp"
        android:layout_toEndOf="@+id/listRowAlarmAmPm"
        android:text="Snooze Timer: N minutes"
        android:textSize="16sp" />

    <Button
        android:id="@+id/listRowAlarmUpdate"
        android:layout_width="133dp"
        android:layout_height="42dp"
        android:layout_below="@+id/listRowAlarmName"
        android:layout_marginTop="13dp"
        android:layout_marginEnd="-52dp"
        android:layout_toStartOf="@+id/listRowAlarmAmPm"
        android:text="Update"
        android:textSize="16sp" />

</RelativeLayout>
  • 1
    Jay, remove that button click listener from Adapter class and try to click on row not on button. Please check if row click allows you to move to next activity. Please check. – Parul Oct 05 '18 at 04:45
  • Hi Parul. Having commented out the listener from the Adapter class, clicking on the row (and the button) does not allow me to move to the next activity. – Jay Bailey Oct 05 '18 at 05:15

2 Answers2

0

Please Remove alarmListView.setOnItemClickListener as said @Parul

and Replace updateButton by whole view in adapter.

 view.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent updateAlarmIntent = new Intent(MainActivity.this, CreateAlarmActivity.class);
            updateAlarmIntent.putExtra("alarmList", alarmList);
            updateAlarmIntent.putExtra("position", position);
            startActivity(updateAlarmIntent);
        }
    });
Abhay Koradiya
  • 2,068
  • 2
  • 15
  • 40
  • Hi Abhay. I'm a little confused at these instructions. Parul asked me to remove the updateButton.setOnClickListener from the Adapter Class, which is different from the alarmListView.setOnItemClickListener in the MainActivity class. I did try removing the alarmListView from the MainActivity, and replace updateButton with view in the AlarmAdapter as you mentioned. But this caused a fair few errors. startActivity won't resolve. MainActivity.this is not an enclosing class. position won't work as it's accessed from an inner class. I feel I've misunderstood the instructions. – Jay Bailey Oct 05 '18 at 05:20
  • @JayBailey for position issue you want to implement `viewholder pattern`. – Abhay Koradiya Oct 05 '18 at 05:28
0

If you want to do action only on update button then do this.

in your getView() method in adapter:

updateButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            // Logic goes here.
           onUpdateClick(position, alarmList); // public method in adapter
        }
    });

then create public method in adapter:

public void onUpdateClick(int position, ArrayList<alarm> alarmList){

}

Now override this method in activity when you initialize adapter:

alarmAdapter = new AlarmAdapter(MainActivity.this, alarmList){
    @Override
    public void onUpdateClick(int position, ArrayList<alarm> alarmList) {
                super.onUpdateClick(position, alarmList);
                Intent updateAlarmIntent = new Intent(MainActivity.this, 
                            CreateAlarmActivity.class);
                updateAlarmIntent.putExtra("alarmList", alarmList);
                updateAlarmIntent.putExtra("position", position);
                startActivity(updateAlarmIntent);
      }
};
DB377
  • 403
  • 4
  • 11