Thursday 15 June 2017

HB Blog 138: Android Progress View With Water Filling Effect.

In my previous post, I showed how we can use seekbar to create vertical seekbar. For more details you can follow my blog  HB Blog 135: Android Vertical Seekbar Tutorial.
In this post, I will show how to create a progress view that represents water filling effect. Here, progress can be updated using vertical bar and water can gradually filled bottom to top.

There are four custom attributes that can be set in your layout xml:
  • fillColor, color - Sets the color of the fill area. Default is Color.WHITE.
  • strokeColor, color - Sets the color of the bounding circle. Default is Color.BLACK.
  • strokeWidth, float - Sets the thickness of the bounding circle. Default is 1.0.
  • value, integer: 0-100 - Sets the value for the fill area. Default is 0.
Refer the below link for complete sample code:-

Download Sample Code

Have a look on few code snippets,

//CustomFillView.java
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package com.harshalbenake.fillview.views;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import com.harshalbenake.fillview.R;

public class CustomFillView extends View {
    public static final int MIN_VALUE = 0;
    public static final int MAX_VALUE = 100;

    private PointF center = new PointF();
    private RectF circleRect = new RectF();
    private Path segment = new Path();
    private Paint strokePaint = new Paint();
    private Paint fillPaint = new Paint();

    private int radius;

    private int fillColor;
    private int strokeColor;
    private float strokeWidth;
    private int value;

    public CustomFillView(Context context) {
        this(context, null);
    }

    public CustomFillView(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.CircleFillView,
                0, 0);

        try {
            fillColor = a.getColor(R.styleable.CircleFillView_fillColor, Color.CYAN);
            strokeColor = a.getColor(R.styleable.CircleFillView_strokeColor, Color.BLACK);
            strokeWidth = a.getFloat(R.styleable.CircleFillView_strokeWidth, 1f);
            value = a.getInteger(R.styleable.CircleFillView_value, 0);
            adjustValue(value);
        } finally {
            a.recycle();
        }

        fillPaint.setColor(fillColor);
        strokePaint.setColor(strokeColor);
        strokePaint.setStrokeWidth(strokeWidth);
        strokePaint.setStyle(Paint.Style.STROKE);
    }

    public void setFillColor(int fillColor) {
        this.fillColor = fillColor;
        fillPaint.setColor(fillColor);
        invalidate();
    }

    public int getFillColor() {
        return fillColor;
    }

    public void setStrokeColor(int strokeColor) {
        this.strokeColor = strokeColor;
        strokePaint.setColor(strokeColor);
        invalidate();
    }

    public int getStrokeColor() {
        return strokeColor;
    }

    public void setStrokeWidth(float strokeWidth) {
        this.strokeWidth = strokeWidth;
        strokePaint.setStrokeWidth(strokeWidth);
        invalidate();
    }

    public float getStrokeWidth() {
        return strokeWidth;
    }

    public void setValue(int value) {
        adjustValue(value);
        setPaths();

        invalidate();
    }

    public int getValue() {
        return value;
    }

    private void adjustValue(int value) {
        this.value = Math.min(MAX_VALUE, Math.max(MIN_VALUE, value));
    }

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

        center.x = getWidth() / 2;
        center.y = getHeight() / 2;
        radius = Math.min(getWidth(), getHeight()) / 2 - (int) strokeWidth;
        circleRect.set(center.x - radius, center.y - radius, center.x + radius, center.y + radius);

        setPaths();
    }

    private void setPaths() {
        float y = center.y + radius - (2 * radius * value / 100 - 1);
        float x = center.x - (float) Math.sqrt(Math.pow(radius, 2) - Math.pow(y - center.y, 2));

        float angle = (float) Math.toDegrees(Math.atan((center.y - y) / (x - center.x)));
        float startAngle = 180 - angle;
        float sweepAngle = 2 * angle - 180;

        segment.rewind();
        segment.addArc(circleRect, startAngle, sweepAngle);
        segment.close();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvas.drawPath(segment, fillPaint);
        canvas.drawCircle(center.x, center.y, radius, strokePaint);
    }
}

//MainActivity.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.harshalbenake.fillview;

import android.app.Activity;
import android.os.Bundle;
import android.widget.SeekBar;
import com.harshalbenake.fillview.views.CustomFillView;
import com.harshalbenake.fillview.views.CustomVerticalSeekbar;

public class MainActivity extends Activity {

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

        CustomVerticalSeekbar customVerticalSeekbar = (CustomVerticalSeekbar) findViewById(R.id.customverticalseekbar);
        final CustomFillView customfillview = (CustomFillView) findViewById(R.id.customfillview);
        customVerticalSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean b) {
                customfillview.setValue(progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
    }
}

//activity_main.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:orientation="horizontal"
    android:background="@android:color/white"
    android:layout_height="match_parent">
    <com.harshalbenake.fillview.views.CustomFillView
        android:layout_width="250dp"
        android:layout_margin="16dp"
        android:id="@+id/customfillview"
       android:layout_height="match_parent" />
    <com.harshalbenake.fillview.views.CustomVerticalSeekbar
        android:layout_width="wrap_content"
        android:id="@+id/customverticalseekbar"
        android:layout_height="match_parent" />
</LinearLayout>

Thursday 1 June 2017

HB Blog 137: Android "O" Supports New Emoji With Unicode 10 Standard.

Emoji are ideograms and smileys used in electronic messages and Web pages. They are used much like emoticons and exist in various genres, including facial expressions, common objects, places and types of weather, and animals. The first emoji was created in 1999 in Japan by Shigetaka Kurita, who wanted to provide users with a way to communicate through images. Originating on Japanese mobile phones in the late 1990s, emoji have become increasingly popular worldwide since their international inclusion in Apple's iPhone, which was followed by similar adoption by Android and other mobile operating systems.
Apple was looking to expand its market in Japan. People had been using these characters to provide context to their communication, so Apple added a hidden feature in the iOS5 update. Suddenly, yellow faces and poop icons became a part of our lexicon.

Android "O" an upcoming release of the Android mobile operating system, supports new emoji that will be included in the Unicode 10 standard. A new emoji font was also introduced, which notably redesigns its face figures to use a traditional circular shape, as opposed to the "blob" design that was introduced on Android "KitKat".

One Emoji to Rule Them All Before an emoji can become an emoji it must be approved by the Unicode Consortium. Approval process typically takes 1 to 2 years.

Unicode Consortium Submission Process:-
1. Submit a proposal
2. Provide justification for its creation by proving a need.

Argue that the icon is already popular online and frequently searched. • Show that a currently existing family of emoji is missing this pivotal group member. • Prove that there is no other way to express this idea with an existing emoji combination.

Emoji communication problems(With Great Power Comes Great Responsibility) :-
Research has shown that emojis are often misunderstood. In some cases, this is related to how the actual emoji design is interpreted by the viewer, in other cases the emoji that was sent, was not shown in the same way at the receiving side.
The difference between these two problems is, that the first relates to the cultural or contextual interpretation of the smiley. When the author picks a smiley, the author thinks about the smiley in a certain way, but the same smiley may not trigger the same thoughts with the receiver. See also Models of communication.
The second problem is technological. When an author of a message picks a smiley from a list of smiley faces, this smiley is encoded in some way during the transmission, and if the author and the reader do not use the same software or operating system for their devices, the reader's device may visualize the same smiley in a different way.

Small changes to a smiley's look may completely alter its perceived meaning with the receiver.

...Keep Smiling 😊😊😊