Download the source project for this Color Picker Widget.

In the recent release Eva Clock HD, the setting screen is implemented with Android-Binding. In that setting screen, I need a color picker to let user select their preferred color to appear in the clock, here’s how it looks like:

It’s consisting of two parts. First, a TextView that the background color is the same as the selected color, and second, a color picker dialog, which shows when user tap on the TextView.

(disclaimer: The dialog’s code is modified from API Demo, please download from here)

We need only one custom attributes for the Color Picker, which is “color”. Here’s the intended xml markup for that widget:


    <com.gueei.evaClock.ColorPicker
style="@style/Setting_Group_ColorPicker"
android:text="HIGHLIGHT"
binding:color="Highlight" />

Where “color” is the Android-color-encoded Integer.

So, we start like any Android custom widget, we extend from TextView.

public class ColorPicker extends TextView implements
        IBindableView<ColorPicker>, View.OnClickListener,
        OnColorChangedListener {

	public ColorPicker(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	public ColorPicker(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public ColorPicker(Context context) {
		super(context);
		init();
	}

	private void init() {
		Binder.getMulticastListenerForView(this, OnClickListenerMulticast.class)
		        .register(this);
	}
}

We not only extends TextView, since we need to handle the onClick Event, we have to implement View.OnClickListener, and because we are working with Android-Binding, we need IBindableView as well (for detail, refer to this post). Note that in the init() code, we have to register itself to onClick listener, but since almost all Android’s Widgets can have only one subscriber, we need MulticastListener. MulticastListener is the construct of Android-Binding that allows multiple listeners for one event. For example, we are getting the “OnClickListenerMulticast” in the above code, when we register to it, whenever the onClick event is raised in this widget, all listeners will be notified.

So, we setup the base, now we move to our custom attribute.

	@Override
	public ViewAttribute<? extends View, ?> createViewAttribute(String arg0) {
		if (arg0.equals("color"))
			return mColorAttr;
		return null;
	}

	@Override
	public void onClick(View v) {
		// Bring up dialog
		ColorPickerDialog dialog = new ColorPickerDialog(getContext(), this,
		        mColorAttr.get());
		dialog.show();
	}

	@Override
    public void colorChanged(int color) {
		mColorAttr.set(color);
    }

	private ColorAttribute mColorAttr = new ColorAttribute(this);

	public class ColorAttribute extends ViewAttribute<ColorPicker, Integer>{
		public ColorAttribute(ColorPicker view) {
	        super(Integer.class, view, "color");
        }

		private int mValue = 0;

		@Override
        protected void doSetAttributeValue(Object arg0) {
			if (arg0 instanceof Integer){
				getView().setBackgroundColor((Integer)arg0);
				mValue = (Integer)arg0;
				return;
			}
			mValue = 0;
			getView().setBackgroundColor(Color.TRANSPARENT);
        }

		@Override
        public Integer get() {
	        return mValue;
        }
	}

We have our “ColorAttribute” that reflects the XML attribute: “color”, and so it is of type Integer. Nothing really special in it, whenever it changes, the Background color of the TextView is changed to that color; note that the doSetAttributeValue accepts Object instead of Integer as parameter, so some kind of type checking is required. And in our case, if the input is not Integer, we simply set the background to transparent.

Just one last part is the “colorChanged” event, which is defined in the ColorPickerDialog, whenever the dialog sets the color and completes, that event is raised. This is where we notify our ColorAttribute about the change.

About these ads