Create custom Dialog Listeners in Android

329 views Asked by At

I would like to create a custom timepicker dialog in Android by making use of number picker. How would I implement a listener?

Below are my code snippets:

    intervalEditText.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            final Calendar c = Calendar.getInstance();
            mYear = c.get(Calendar.YEAR);
            mMonth = c.get(Calendar.MONTH);
            mDay = c.get(Calendar.DAY_OF_MONTH);

            DurationPickerDialog durationPickerDialog = new DurationPickerDialog(getActivity(),
                    new DurationPickerDialog.onDurationSetlistener() {

                        @Override
                        public void onDurationSet(View v, int hour, int minute, int seconds) {
                            intervalEditText.setText(hour + ":" + minute + ":" + seconds);
                        }
                    });
            durationPickerDialog.show();
        }
    });

DurationPickerDialog.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/primaryColor"
    android:divider="@drawable/horizontal_divider_red"
    android:gravity="center"
    android:orientation="vertical"
    android:showDividers="middle">

    <com.identiv.utrust.sense.uielements.FLightTextView
        android:id="@+id/duration"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="12dp"
        android:textColor="@color/labelSetupText"
        android:text="Interval: 00:00:00"
        android:textSize="20sp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="6dp"
        android:gravity="center"
        android:orientation="horizontal">

        <NumberPicker
            android:id="@+id/numberPicker1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="6dp"
            android:layout_marginLeft="24dp"
            android:layout_marginRight="6dp"
            android:layout_marginTop="6dp"
            android:focusable="false"
            android:gravity="center" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=":" />

        <NumberPicker
            android:id="@+id/numberPicker2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="6dp"
            android:focusable="false"
            android:gravity="center" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=":" />

        <NumberPicker
            android:id="@+id/numberPicker3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="6dp"
            android:layout_marginLeft="6dp"
            android:layout_marginRight="24dp"
            android:layout_marginTop="6dp"
            android:focusable="false"
            android:gravity="center" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:divider="@drawable/vertical_divider_red"
        android:orientation="horizontal"
        android:showDividers="middle">

        <com.identiv.utrust.sense.uielements.FRomanButton
            android:id="@+id/cancel"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@null"
            android:text="Cancel"
            android:textColor="@color/labelSetupText"
            android:textSize="14sp" />

        <com.identiv.utrust.sense.uielements.FRomanButton
            android:id="@+id/set"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@null"
            android:text="Set"
            android:textColor="@color/labelSetupText"
            android:textSize="14sp" />

    </LinearLayout>

</LinearLayout>

DurationPickerDialog.java

public class DurationPickerDialog extends Dialog {

    private static NumberPicker hourPicker;
    private static NumberPicker minutesPicker;
    private static NumberPicker secondsPicker;
    private static Button cancelButton;
    private static Button setButton;
    private static TextView duration;

    private onDurationSetlistener listener;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.datepickerdialog);

        hourPicker = (NumberPicker)findViewById(R.id.numberPicker1);
        minutesPicker = (NumberPicker)findViewById(R.id.numberPicker2);
        secondsPicker = (NumberPicker)findViewById(R.id.numberPicker3);
        cancelButton = (Button)findViewById(R.id.cancel);
        setButton = (Button)findViewById(R.id.set);
        duration = (TextView)findViewById(R.id.duration);

        hourPicker.setMaxValue(9);
        hourPicker.setMinValue(0);
        setDividerColor(hourPicker);
        hourPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);

        minutesPicker.setMaxValue(59);
        minutesPicker.setMinValue(0);
        setDividerColor(minutesPicker);
        minutesPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);

        secondsPicker.setMaxValue(59);
        secondsPicker.setMinValue(0);
        setDividerColor(secondsPicker);
        secondsPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);

        cancelButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
            }
        });

        setButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                listener.onDurationSet(v, hourPicker.getValue(), minutesPicker.getValue(), secondsPicker.getValue());
            }
        });

        hourPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
            @Override
            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
                duration.setText("Interval: " + String.format("%02d", hourPicker.getValue()) + ":" + String.format("%02d", minutesPicker.getValue()) + ":" + String.format("%02d", secondsPicker.getValue()));
            }
        });

        minutesPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
            @Override
            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
                duration.setText("Interval: " + String.format("%02d", hourPicker.getValue()) + ":" + String.format("%02d", minutesPicker.getValue()) + ":" + String.format("%02d", secondsPicker.getValue()));
            }
        });

        secondsPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
            @Override
            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
                duration.setText("Interval: " + String.format("%02d", hourPicker.getValue()) + ":" + String.format("%02d", minutesPicker.getValue()) + ":" + String.format("%02d", secondsPicker.getValue()));
            }
        });

    }

    private void setDividerColor(NumberPicker picker) {

        java.lang.reflect.Field[] pickerFields = NumberPicker.class.getDeclaredFields();
        for (java.lang.reflect.Field pf : pickerFields) {
            if (pf.getName().equals("mSelectionDivider")) {
                pf.setAccessible(true);
                try {
                    pf.set(picker, getContext().getResources().getDrawable(R.drawable.horizontal_divider_red));
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (Resources.NotFoundException e) {
                    e.printStackTrace();
                }
                catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                break;
            }
        }
    }

    private void updateTitle(int hour, int min, int sec){
        duration.setText("Duration: " + hour + ":" + min + ":" + sec);
    }

    public DurationPickerDialog(Context context, onDurationSetlistener callBack) {
        super(context);
    }

    public static interface onDurationSetlistener {
        public abstract void onDurationSet (View v, int hour, int minute, int seconds);
    }
}

The above code causes the application to crash when set is clicked.. I would like to know what mistake did I make in creating custom dialogs. I want the time from dialog to be passed to the activity.

LogcatReport

Process: com.identiv.utrust.sense.temperaturetracker, PID: 27790
    java.lang.NullPointerException
            at com.identiv.utrust.sense.uielements.DurationPickerDialog$2.onClick(DurationPickerDialog.java:71)
            at android.view.View.performClick(View.java:4710)
            at android.view.View$PerformClick.run(View.java:19510)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:146)
            at android.app.ActivityThread.main(ActivityThread.java:5678)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
            at dalvik.system.NativeStart.main(Native Method)

I find the onDurationListener object to be null. Are my implementations correct?

2

There are 2 answers

0
Sharp Edge On BEST ANSWER

This is the line where you get NullPointerException

listener.onDurationSet(v, hourPicker.getValue(), minutesPicker.getValue(), secondsPicker.getValue());

Because listener is null, you haven't initialized it any where.

0
Britto On

In my code everything was right, except that I didn't assign the new listener object created during function call to the class member.

The wrong code

public DurationPickerDialog(Context context, onDurationSetlistener callBack) {
    super(context);
}

The correct code

public DurationPickerDialog(Context context, onDurationSetlistener callBack) 
{
    super(context);
    this.listener = callBack;
}