Saturday, March 12, 2016

GsonFormat and Parcelable plugins for Android Studio -- HEAVILY RECOMENDED

Hello guys,

I am really excited to share two plugins with my fellow android developers which saves u a lot of time.

GsonFormat:

Note : This plugin is helpful if you are using Gson to convert Json file into Java model.

Recently I was trying to search for a plugin to autogenerate java model from the JSon file.Then, I got to know about GsonFormat plugin. Install the plugin from your studio preferences. Restart your studio, right click inside the java file --> generate --> GsonFormat. It asks for the Json file, copy- paste that -- > Boom, it does the rest for you.

Complete details here.

Parcelable:

Note: Assuming you are using parcelable in your projects to pass objects using intents.

While implementing parcelable, general mistakes will be the order of writing and reading objects. Some times we might miss some variables.

Solution - Use parcelable plugin which generates code for you.

I think Jetbrins site is down when i'm writing this post. Should be back shortly.

MUST TRY - HIGHLY RECOMMEDED PLUGINS.

Comment out any useful plugins you know :)

Cheers,
Sree

Android - CustomCountdown timer button

This post covers a custom button which displays timer in it . Button looks like the below video




To display this, we have to write down a custom implementation of the button. From the above view, we can see its still a button with text, but the additional thing we need to do is styling of button with rounded corners and paint the coundown timer color on the left side.

So my CustomButtonClass looks like 

public class CountDownTimerButton extends Button
{

    private boolean mIsSizeChanged;
    private Paint mPaint;
    private int mPercent ;
    private RectF mArcRect;
    Rect boundingRect = new Rect();

    private int mHeight;
    private int mCircleMargin;


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

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

    public CountDownTimerButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @SuppressLint("NewApi")
    public CountDownTimerButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init()
    {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);

        setBackgroundResource(R.drawable.selectable_background_button_accent);
    }

    /**
     * Set the percentage of the progress
     * @param percent
     */
    public void setPercent(int percent)
    {
        mPercent = percent;
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {

        super.onDraw(canvas);

        final float startAngle = 270f;
        final float drawTo =  (mPercent * 360/100);

        if(mArcRect == null || mIsSizeChanged)
        {
            getDrawingRect(boundingRect);
            mHeight = getHeight();

            //  Left circle which is drawn a bit inside to the button
            //  Offset is the value to move inside
            mCircleMargin = (int) (mHeight * 0.1);
            //  Arc which is drawn inside with a bit of margin
            //  Offset is the value to move inside
            int mArcMargin = (int) (mHeight * 0.2);

            mArcRect = new RectF();
            mArcRect.top = boundingRect.top + mArcMargin;
            mArcRect.bottom = boundingRect.top +  mHeight - mArcMargin;
            mArcRect.left =  boundingRect.left + mArcMargin;
            mArcRect.right =   boundingRect.left + mHeight - mArcMargin;

        }

        mPaint.setColor(Color.WHITE);
        canvas.drawCircle(boundingRect.left + mHeight/2, boundingRect.top + mHeight/2, mHeight/2 - mCircleMargin, mPaint);

        mPaint.setColor(getResources().getColor(R.color.colorAccentDisabled));
        canvas.drawArc(mArcRect, startAngle, drawTo, true, mPaint);

        //  Draw a line on Y-Axis, which might help user when progress is 0.
        canvas.drawLine(mArcRect.right - (mArcRect.right - mArcRect.left)/2,
                mArcRect.top,
                mArcRect.right - (mArcRect.right - mArcRect.left)/2,
                mArcRect.bottom - (mArcRect.bottom - mArcRect.top)/2,
                mPaint);

        mIsSizeChanged = false;

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        mIsSizeChanged = true;
        super.onSizeChanged(w, h, oldw, oldh);
    }

}


So, All the magic is in onDraw() method. If you closely look at the coundown view, we are drawing a white circle on the left of button and an arc on top of it. setPercent() method is used to update the countdown time. Whenever the text is changed, the cordinates are also changed, so I'm using onSizeChanged() method to determine that scenario and recalculating cordinates in onDraw().

I'm using this component in a fragment and updating the percent based on a timer. Code looks as below.

final int millisInterval = 300;
        final int totalMinutes = 1;
        final long totalMillis = totalMinutes * DateUtils.MILLIS_PER_MINUTE;

        // Countdown timer for updating the remaining time
        CountDownTimer timer = new CountDownTimer(totalMillis, millisInterval) {

            @Override
            public void onTick(long millisUntilFinished) {

                long millisCompleted = totalMillis - millisUntilFinished;
                float percent = ((millisCompleted ) / (float)(totalMillis)) * 100;
                mCoundowntimerBtn.setPercent((int) percent);


                String formattedTime = DateUtils.formatRemainingTimeToHHMMSS(millisUntilFinished);
                if(formattedTime != null)
                {
                    formattedTime = String.format(getString(R.string.time_remaining), formattedTime);
                    mCoundowntimerBtn.setText(formattedTime);
                }
            }

            @Override
            public void onFinish() {

            }

        };
        timer.start();


formatRemainingTimeToHHMMSS() is my custom method to render text on the button.

Apart from the mentioned things, I used additional shape background for rounded corners, I used the height of button exactly double to the corner radius to achieve exact semi circle shape.

Comment out if you have any queries.

Hope this helps you in some situations.

Cheers,
Sree