Thursday, 12 September 2013

customizing the zoomControls to be used as Stepper

The stepper is a widget which has two buttons, one to increase and the other one to decrease. In Android, the best approach I found is the ZoomControls, which has such button for zoom in and zoom out.

By reading the official documentation and the source code, it seems that there is not way to customize the buttons.

The problem is here:
private final ZoomButton mZoomIn;
private final ZoomButton mZoomOut;


public ZoomControls(Context context, AttributeSet attrs) {
    super(context, attrs);
    ...
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    inflater.inflate(R.layout.zoom_controls, this, // we are the parent
                          true);
    mZoomIn = (ZoomButton) findViewById(R.id.zoomIn);
    mZoomOut = (ZoomButton) findViewById(R.id.zoomOut);
}

Here is the source code of the layout:
<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <ZoomButton
         android:id="@+id/zoomOut"
          android:background="@drawable/btn_zoom_down"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content" />
     <ZoomButton
          android:id="@+id/zoomIn"
          android:background="@drawable/btn_zoom_up"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content" />
</merge>

This is, the both zoom in and zoom out buttons are private, and they use the background in the resource folder. Since there is not method to set or get those buttons, there is not way to customize them.

So, I found two approaches.

Approach 1: Create our one ZoomControl class
Since we have the source code, it is quite easy to create a new class called ZoomControls which has setters and getters for those buttons. In the layout, instead of using zoom control, we can use ZoomButtons.

Here is the sample code:
    textView1 = (TextView)findViewById(R.id.textView1);

    zoomInButton = (ZoomButton)findViewById(R.id.zoomIn);
    zoomOutButton = (ZoomButton)findViewById(R.id.zoomOut);

    zoomControls1 = new ZoomControls(this);
    zoomControls1.setZoomInButton(zoomInButton);
    zoomControls1.setZoomOutButton(zoomOutButton);

Here you can find the complete code:

The problem of this approach is to maintain the code. If in the future Google creates a new version of ZoomControl, our ZoomControl class will be deprecated.

Approach2: Use foreground
The second approach is using a foreground which draws over the default image. This will ensure the code to be easy maintainable.

Here is the sample code (xml):
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
       android:foreground="@drawable/myZoomControlAppereance"
>
    <ZoomControls
        android:id="@+id/zoomControl"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</FrameLayout>
The frameLayout has been introduced from API 1, so it is compatible with all the versions. The unique problem here is the coder must make sure that the new foreground has two buttons and each one of them covers the corresponding button in the ZoomControl.

Update: It seems that the zoomControls is not easily resizable, so be careful with the foreground image.

Source code:

Inspiration:

No comments:

Post a Comment