Introduction
Agree, most of us use Android smartphones and some of us love coding. In this tip, I will share my concept on how to capture click event in Android in a specific chart created in canvas in Android. I've searched from the internet and most of the discussion is on how to create a bar chart with no specific function but a chart only. So, when I looked at the Android developer site, I started developing a custom gradient bar chart with click event capture. Upon learning about the output, it was good and looks to be functional.
So without much further ado, let's proceed with the Java coding...
Background
To be able to comprehend the Android Programming, you must have installed an Android Studio or equivalent. The IDE installer can be found here. Initially, it will be tough and challenging but over the course of time, it will become simpler and easier to do.
Using the Code
First, you should create a public
class and extend it to View. Then create an override for onDraw
, onSizeChanged
, onTouchListener
and onDraw
respectively.
package com.emer.myApp;
import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class StatisticGraph extends View{
private Paint paint;
private List<String> _name = new ArrayList<>();
private List<Float> _value = new ArrayList<>();
List<String> _position = new ArrayList<>();
private String title;
private List<Rect> mRect;
private Context mContext;
private int mViewH;
private int mViewW;
GradientDrawable gradientDrawable;
Rect rect;
Below is the default override called when a view is first created.
public StatisticGraph(Context context, List<Float> _value, String title,
List<String> _name,List<String>position) {
super(context);
mContext=context;
rect = new Rect();
mRect = new ArrayList<>();
gradientDrawable= new GradientDrawable();
this._value = _value;
this.title = title;
this._name = _name
this._position = position;
paint = new Paint();
Typeface tf = Typeface.createFromAsset(context.getAssets(),
FontService.getFontPath(Enums.Font.Regular));
paint.setTypeface(tf);
}
private float getMax() {
float L = Integer.MIN_VALUE;
for(Float f:_value){
if(f>L) L=f;
}
return L + (L/2);
}
Below is the code to capture touch event in Android.
@Override
public boolean onFilterTouchEventForSecurity(MotionEvent event) {
float x = event.getX();
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
int i=0;
for(Rect r:mRect){
if(((x>r.left) && x< (r.left+ r.width()))
)
{
String name =_name.get(i);
String voteCount = String.valueOf(Math.round(_value.get(i)));
if (Storage.isFileExist(mContext, name))
{
Object o = Storage.getImage(mContext, name);
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
View view = layoutInflater.inflate(R.layout.popup_image, null);
AlertDialog.Builder alertMessage = new AlertDialog.Builder(mContext);
TextView textView = (TextView)view.findViewById(R.id.popup_title);
Typeface tf = Typeface.createFromAsset(mContext.getAssets(),
FontService.getFontPath(Enums.Font.Regular));
textView.setTypeface(tf);
textView.setText(name + "\nVotes: " + voteCount);
ImageView image = (ImageView) view.findViewById(R.id.image_pop);
alertMessage.setCancelable(true);
alertMessage.setView(view);
if(o!=null){
try{
image.setImageBitmap((Bitmap)o);
}catch (NullPointerException e){
image.setImageBitmap(BitmapHelper.getBitmap(mContext,
R.drawable.no_picture));
}
}else{
image.setImageBitmap(BitmapHelper.getBitmap(mContext,
R.drawable.no_picture));
}
AlertDialog alertDialog = alertMessage.create();
alertDialog.show();
}
break;
}
i++;
}
break;
}
return super.onFilterTouchEventForSecurity(event);
}
Below is the code to capture the size of Android. It differs from every phone maker so be sure to include this parameter to measure the position of bar chart.
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mViewH =h;
mViewW=w;
}
int TextSize(Paint p,String text,float textSize){
float size;
if(mViewH<540){
p.setTextSize(textSize);
Rect rect =new Rect();
p.getTextBounds(text, 0, text.length(), rect);
size = ((textSize * ((float)mViewW)/(float)mViewH) / 2);
p.setTextSize(size);
}else{
float f =(mViewW/mViewH);
size =textSize * f;
p.setTextSize(size);
}
return (int)size;
}
void setRadius(GradientDrawable d, float r0,
float r1, float r2, float r3) {
d.setCornerRadii(new float[]{r0, r0, r1, r1,
r2, r2, r3, r3});
}
Here's the onDraw
code:
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
protected void onDraw(Canvas canvas) {
float _hgt = get_hgt();
float _wdth = get_wdth() - 1;
float _max = getMax();
float cBorder = 15f;
float _hRef = cBorder * 2;
float graph_hgt = _hgt - (2 * cBorder);
float graph_wdth = _wdth - (2 * cBorder);
paint.setAntiAlias(true);
paint.setColor(Color.BLUE);
int sz = TextSize(paint,"3.] PRES GRAPH",15f);
paint.setTextAlign(Paint.Align.LEFT);
canvas.drawText("1.] PRES GRAPH",10,sz*2+(cBorder*2),paint);
canvas.drawText("2.] VPRES GRAPH",10,sz*3+(cBorder*2),paint);
canvas.drawText("3.] SEN GRAPH", 10, sz * 4 + (cBorder * 2), paint);
paint.setTextAlign(Paint.Align.CENTER);
paint.setFakeBoldText(true);
paint.setColor(Color.BLACK);
TextSize(paint, title, 30f);
if ((_max)>-1) {
canvas.drawText(title, (graph_wdth / 2) + _hRef, cBorder*2, paint);
float column_wdth = (_wdth - (2 * cBorder)) / _value.size();
_hRef=_hRef/2;
int length =_value.size();
for (int i = 0; i < length ; i++) {
float val = _value.get(i);
float rat = val / _max;
float h = graph_hgt * rat;
float r = 3;
paint.setDither(true);
paint.isAntiAlias();
rect.left =(int)((i * column_wdth) + _hRef+3);
rect.top =(int) ((cBorder - h)
+ graph_hgt);
rect.right =(int)(((i * column_wdth) + _hRef)
+ (column_wdth - 1));
rect.bottom =(int)(_hgt - (cBorder - 1));
mRect.add(new Rect(rect));
canvas.save();
switch(_position.get(i)){
case "PRES":
gradientDrawable.setOrientation(gradientDrawable.Orientation.LEFT_RIGHT);
gradientDrawable.setColors(new int[]{0xFF6762b2, 0xFFfff5fb, 0xFF6762b2});
gradientDrawable.setcBorderounds(rect);
gradientDrawable.setGradientType(gradientDrawable.LINEAR_GRADIENT);
setRadius(gradientDrawable, r, r, 0, 0);
gradientDrawable.draw(canvas);
paint.setColor(Color.BLACK);
break;
case "VPRES":
gradientDrawable.setOrientation(gradientDrawable.Orientation.LEFT_RIGHT);
gradientDrawable.setColors(new int[] { 0xFF25b235,0xFFfff5fb, 0xFF25b235 });
gradientDrawable.setcBorderounds(rect);
gradientDrawable.setGradientType(gradientDrawable.LINEAR_GRADIENT);
setRadius(gradientDrawable, r, r, 0, 0);
gradientDrawable.draw(canvas);
paint.setColor(Color.BLACK);
break;
case "SEN":
gradientDrawable.setOrientation(gradientDrawable.Orientation.LEFT_RIGHT);
gradientDrawable.setColors(new int[] { 0xFFba255b,0xFFfff5fb, 0xFFba255b });
gradientDrawable.setcBorderounds(rect);
gradientDrawable.setGradientType(gradientDrawable.LINEAR_GRADIENT);
setRadius(gradientDrawable, r, r, 0, 0);
gradientDrawable.draw(canvas);
paint.setColor(Color.BLACK);
break;
}
canvas.restore();
paint.setColor(Color.BLACK);
String s =_name.get(i);
sz = TextSize(paint,s,15f);
float y=(int) (((cBorder*2) - h)
+ graph_hgt);
for(char c: _name.get(i).split(" ")[0].toCharArray()) {
canvas.drawText(String.valueOf(c),
(i * column_wdth)+(_hRef+ cBorder)
,
y
,paint);
y += sz;
}
s =String.valueOf(Math.round(_value.get(i)));
paint.setColor(Color.BLUE);
TextSize(paint,s,15f);
canvas.drawText(s, (i * column_wdth) + _hRef + cBorder
,
graph_hgt + (cBorder-h)-5,paint);
}
}else{
paint.setColor(Color.RED);
canvas.drawText("NO_DATA_RETRIEVED", (graph_wdth / 2) + _hRef, graph_hgt/2, paint);
}
super.onDraw(canvas);
}
}
Points of Interest
This code is used in my current Android app. You should have familiarity in JAVA to understand the code better. If you have any further suggestions, you can post a comment below. Thanks.
History
- Initial release (Bar chart with gradient design)