Custom View – Rating Star fills from left to right based on percentage – part 3(5 parts)

This is part 3 in the series of custom view tutorials. There was need of rating star in one of my app that fills from left to right based on percentage something like below.
Screenshot_2014-10-11-22-05-53

You got an idea…! I tried much more ways to achieve this but none of them worked for me. At last these steps I followed.
1) Draw star(inner) with Blue color (with paint FILL).
2) Draw a rect above this Star which hides inner star completely.
3) Based on percentage left side of the rect is modified from its original position.
4) Again an outer star with Gray color (with paint STROKE) is drawn.

Stars are drawn based on this blog post author made use of circles to draw stars.

Inner & Outer stars
Drawing is nothing moving Path based on calculations in a canvas (with specified bitmap to draw into). Here is the code. Inner star is drawn with FILL paint and Outer star is drawn with STROKE paint refer source code for more.

private void drawInnerFillStarInTempCanvas() {
bitmap = Bitmap.createBitmap(getWidth(),getHeight(),Bitmap.Config.ARGB_8888);
		tempCanvas = new Canvas(bitmap);
		
		int measuredWidth = getWidth();
		int measuredHeight = getHeight();

		int x = (measuredWidth / 2);
		int y = (measuredHeight / 2);
		int outerRadius = measuredWidth / 4;
		int innerRadius = outerRadius / 3;
		
		int points = 5, fillPercent = 1;

		if (points < 3)
			return;

		float a = (float) (Math.PI * 2) / (points * 2);
		int workingRadius = outerRadius;
		polyPath.reset();

		tempCanvas.translate(x, y);
		for (int j = 0; j < ((fillPercent < 1) ? 2 : 1); j++) {
			polyPath.moveTo(workingRadius, 0);
			for (int i = 1; i < points * 2; i++) {
				workingRadius = (workingRadius == outerRadius) ? innerRadius : outerRadius;
				float xPt = (float) (workingRadius * Math.cos(a * i));
				float yPt = (float) (workingRadius * Math.sin(a * i));
				polyPath.lineTo(xPt, yPt);
			}
			polyPath.close();
			outerRadius -= outerRadius * fillPercent;
			innerRadius = outerRadius / 2;
			a = -a;
		}

		float startAngle = 126;

		tempCanvas.rotate(startAngle);
		tempCanvas.drawPath(polyPath, innerStarPaint);	
}

Drawing Rect to hide inner star
This rect will hide the star which we drawn, by changing the left side of this rect we can show portion of star.

 private void formHidingRectAroundStar(int screenWidth, int screenHeight, int outerRadius) {		
		rectLeft = screenWidth - (screenWidth / 2 + outerRadius - 25);
		rectRight = (screenWidth / 2 + outerRadius) - 25;
		rectTop = screenHeight - (screenHeight / 2 + outerRadius);
		rectBottom = screenHeight / 2 + outerRadius;
		
		rectWidthIs = rectRight - rectLeft;
		
		rect.set(rectLeft, rectTop, rectRight, rectBottom);
	}

screenWidth, screenHeight, outerRadius, rectWidthIs are required attributes. Rect drawn when the view is instantiated as below.

@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		
		//	where as getWidth() / 4 is also outer radius of Outer circle of Star
		formHidingRectAroundStar(getWidth(),getHeight(),getWidth() / 4);
	}

From Activity this method is called periodically, which sets 4 sides of the rect.

//	from activity
	public void setRectLeftSideValue() {		
		int factor = rectWidthIs / 50; 
		rectLeft += factor;
		rect.set(rectLeft, rectTop, rectRight, rectBottom);
	}

OnDraw method

@Override
	protected void onDraw(Canvas canvas) {
		
		//	drawing innerStar using Canvas
		drawInnerFillStarInTempCanvas();
		canvas.drawBitmap(bitmap, 0,0, innerStarPaint);
		
                //      drawing hiding rect
		canvas.drawRect(rect, rectPaint);

		//	drawing outerStar using Canvas
		drawOuterStrokeStarInTempCanvas();
		canvas.drawBitmap(bitmap, 0,0, outerStarPaint);
	}

Runnable which is called from Activity

Runnable runnable = new Runnable() {
		
		@Override
		public void run() {
			if(value <= 50){
				
				if(value < 10){
					((TextView)findViewById(R.id.RatingTxtView)).setText("0."+value);
				}
				else{
					((TextView)findViewById(R.id.RatingTxtView)).setText(String.valueOf(value / 10)+"."+String.valueOf(value % 10));
				}
				
				ratingStar.setRectLeftSideValue();
				value++;
				ratingStar.invalidate();
				myHandler.postDelayed(this, 3);
			}
		}
	};

You can make use of my work if needed, after some time I may tweak it more to look & work better.
Source code is available at github.

Enjoy Happy coding!!!

Advertisements

Custom View – Circular view fills bottom to top like water – part2(5 parts)

Hi, this is part 2, while searching for a requirement I came across this at SO post. This is attractive, and thought why not I can make a view like this. It is nothing but view which fills from bottom to top like water fills in a container.
Screenshot_2014-09-27-19-52-18Do you like it?! concept behind is same as this view.

1) After extending a View class, I believe methods executed in following order(correct me if I am wrong!)
Constructor(with Context) -> Constructor(with Context and AttributeSet)(a special constructor gets executed when layout is inflated) -> onSizeChanged() etc…

2) More about onSizeChanged()

@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		
		centerPoint.x = getWidth() / 2;
		centerPoint.y = getHeight() / 2;
		
		radius = Math.min(getWidth(), getHeight()) / 2;
		circleRect.set(centerPoint.x - radius, centerPoint.y - radius, centerPoint.x + radius, centerPoint.y + radius);
		
		setPaths();
	}

x,y co ordinates marks to the middle of the screen and radius is decided based on minimum of width and height of screen(in order to fit both in portrait and landscape mode). A rect is set with left,top,right,bottom co ordinate values and then setPaths(setting x,y,startAngle and sweepAngle to Path).

3) Here is setPaths()

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

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

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

where mPath – instance of Path,circleRect – a rect. I am trying to understand the maths behind this.

4) Inside onDraw() path and circle needs to be drawn.

@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		
		mPaint.setDither(true);
		mPaint.setColor(Color.LTGRAY);
		mPaint.setStyle(Paint.Style.STROKE);
		mPaint.setStrokeWidth(15);
		
		mFillPaint.setColor(Color.parseColor("#33b5e5"));
		mFillPaint.setStyle(Paint.Style.FILL_AND_STROKE);
		mFillPaint.setStrokeWidth(5);
		
		canvas.drawPath(mPath,mFillPaint);
		canvas.drawCircle(centerPoint.x, centerPoint.y, radius, mPaint);
	}

5) And hence from Activity call this method at regular interval of time. This method sets the value, path and invalidates the view.

//	values to be sent from activity
	public void setFillValue(int value) {
		adjustValues(value);
		setPaths();
		invalidate();
	}

6) A runnable in Activity is as below,

Runnable runnable = new Runnable() {
		
		@Override
		public void run() {
			if(value <= 60){
				((TextView) findViewById(R.id.percentText)).setText(String.valueOf(value));
				bottomTopCircularView.setFillValue(value++);
				myHandler.postDelayed(this, 20);
			}
		}
	};

For source code github.

Enjoy! and Happy coding !!

Embedding Video in an Android app!

I was in need of embedding video in an app. Its pretty simple refer this.
Go ahead with my blog or else refer the link provided.
1) Create a res/raw/ folder
2) Paste video inside raw/ folder.
3) Create a layout file activity_main.xml

<RelativeLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.wordpress.smdaudhilbe.aembeddingvideoinapp.MainActivity"
    tools:ignore="MergeRootFrame" >

    <VideoView
        android:id="@+id/videoView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true" />

</RelativeLayout>

4)

public class MainActivity extends Activity {

	private VideoView videoView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		videoView = (VideoView)findViewById(R.id.videoView1);
		
//    refer Video
		String fileName = "android.resource://" + getPackageName() + "/" + R.raw.moto_x_review_2014;
		videoView.setVideoURI(Uri.parse(fileName));

//    start video
		videoView.start();
	}
}

Here screenshots,

Screenshot_2014-09-23-20-03-09

and
Screenshot_2014-09-23-20-03-46

Thats it! no need of any special permissions in manifest at all.
Source code is available at github.
Enjoy! Happy Coding!!!

CustomView – Circular ring which rotates based on given percentage – part 1(5 parts)

Hi, Welcome to part 1, Again after sometime in one of my project there was need to implement a circular view that increases its size based on the given percentage something like this discussed in SO. After a lot of research I made a widget (custom view) what I exactly needed. Here am going to discuss that in short and simple way.

1) extend a View class

public class CustomCircularRingView extends View

2) inside onDraw(), draw a gray circle as below

// Thin circle
canvas.drawCircle(width / 2, height / 2, radius, mPaint);

3) set four sides of created rect as below

// Thin circle
box.set(getWidth() / 2 - radius, getHeight() / 2 - radius, getWidth() / 2 + radius, getHeight() / 2 + radius);

4) set sweep angle and draw an arc as given below

float sweep = 360 * percent * 0.01f;
canvas.drawArc(box, 90, sweep, false, mPaint);

So simple, only trick is changing the “percent” variable at regular intervals.

5) method which changes the “percent” periodically is

public void changePercentage(int value) {
actualPercent = value;
}

I made periodic calls to this method from MainActivity by putting it inside a runnable as like below,

Runnable runnable = new Runnable() {

@Override
public void run() {

if (percent <= 80) {
((TextView) findViewById(R.id.percentText)).setText(String.valueOf(percent));
myView.changePercentage(percent++);
myView.invalidate();
handler.postDelayed(this, 10);
}
}
};

You can get source code of this project at gitHub.
Screen shot
Screenshot_2014-09-15-18-18-56

 

Stay tune for part 2 very soon.

Enjoy! Happy coding..!

How to create UIPageViewController(iOS) like in Android

In one of my app, there was in need of creating UIPageViewController like set up. It is nothing but dots which changes its colour based on navigation of pages in ViewPager. Un fortunately am not able to find any widgets in android SDK that can make my task simple. When I spoke about this to one of my colleague, he gave me a simple solution (Watta man!!!). I hope, I may use this same in my project too. Here it is, to help any of you.

I created simple ViewPager with 5 pages for demo purpose using PagerAdapter. More you can find in source code of this project. And trick begins now,

1) I created a dummy layout below ViewPager in layout file which contains relative and linear layout without any respective child.

<RelativeLayout
        android:id="@+id/viewPagerIndicator"
        android:layout_width="match_parent"
        android:layout_height="25dp"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="5dp"
        android:layout_marginTop="5dp">

        <LinearLayout
            android:id="@+id/viewPagerCountDots"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:orientation="horizontal>
        </LinearLayout>
</RelativeLayout>

2) Get number of pages in ViewPager, from its adapter

dotsCount = myViewPagerAdapter.getCount();

3) Create a TextView array as below

dots = new TextView[dotsCount];

4) Populate the TextView array with TextViews of gray colour and add them in dummy layout as shown below

dotsLayout.addView(dots[i]);
dots[0].setTextColor(getResources().getColor(R.color.app_green));

since 0th position of ViewPager is always selected, I made it green colour indicating as selected.

5) Now implementing PageChangeListeners,

@Override
public void onPageSelected(int position) {
    // making everything as un selected
    for (int i = 0; i &amp;amp;amp;amp;lt; dotsCount; i++){
     dots[i].setTextColor(getResources().getColor(android.R.color.darker_gray));
    }
    // only one selected
    dots[position].setTextColor(getResources().getColor(R.color.app_green));
}

Screenshots,

Portrait,

Screenshot_2014-08-17-19-44-58

Landscape,

Screenshot_2014-08-17-19-44-21

I hope code is self explanatory. You can find complete source code of this project at github.

Enjoy ..! Happy Coding …!

Tip to avoid un expected delay / hitches / glitches in your App

Many of us will face this surprising issue in our app, it seems like everything is ok with code but not aware of any glitch we are creating in it. AsyncTasks are one of those, it is very useful to do our job in background thread and produce required result. I faced this glitch when trying to download thumb nail image for a customised listview. And here is the issue, when I tried to navigate to next activity before finishing the thumb nail task, there occurs a glitch, I tried to make a server call while creating next activity it took much more un expected time to respond. Your app(UI thread) will do anything only after completing the AsyncTasks you started. And the simple solution for this is as below., 1. Create a Set (a collection that contains no duplicate value) of AsyncTasks

Set asyncTasks = Collections.synchronizedSet(new HashSet());

2. Add each AsyncTask class in Set(Collection) as you create in your app. You can do this onPreExecute() method of Task

@Override
protected void onPreExecute() {
asyncTasks.add(this); 
}

3. And finally you can cancel every asynctasks as below. I prefer to do this at onStop() method of activity

for (AsyncTask asyncTask : asyncTasks) { 
if (asyncTask != null)
   asyncTask.cancel(true); 
}

Hence you may avoid un wanted glitches / delays in your app. Enjoy …! useful link

JSON with GSON

Google has made a wonderful library called GSON that can convert any JSON into a class and vice versa. As an Android developer you may come across a situation to Parse a JSON and show its result in your app often. You can achieve this parsing by writing a separate JSON Parser class and achieve it. But it is not a good idea to write JSON parser class for different types of JSON you may face in your app. Hence by using GSON you are in no need to worry about JSON parsing at all. Here I may discuss how to use GSON open source library to achieve our task.

Step 1
Download the latest .zip of GSON library and include .jar in your libs/ folder of your project.

Step 2

This method will parse the JSON and result will be converted as per the given target class.

public static <T> T parseResponseUsingGSON(String response, Class<T> targetClass) {
Gson gson = new Gson();
T responseObj = null;
try {
responseObj = gson.fromJson(response, targetClass);
} catch(JsonSyntaxException e) {
e.printStackTrace();
} catch(Exception e) {
e.printStackTrace();
}
return responseObj;
}

Step 3

Create a POJO class with required getters and setters of its fields. For example if your JSON response is

{
"data": {
"a": "apple",
"b": "ball",
"c": "cat"
}
}

Resulting POJO class will be as like this.

Dummy.java

public class Dummy {
//as per the JSON
Result data;
/**
* @return the data
*/
public Result getData() {
return data;
}
/**
* @param data the data to set
*/
public void setData(Result data) {
this.data = data;
}
}

and the Result.java is

public class Result {
//as per the JSON
String a,b;
/**
* @return the a
*/
public String getA() {
return a;
}

/**
* @param a the a to set
*/
public void setA(String a) {
this.a = a;
}

/**
* @return the b
*/
public String getB() {
return b;
}

/**
* @param b the b to set
*/
public void setB(String b) {
this.b = b;
}

If you plan to re name the field of the POJO then you should include the following annotation above the field declaration.

@SerializedName("data")
Result myData;

Based upon the resulting JSON one can design the POJO class. After receiving the JSON from server it can be parse using the above mentioned method “parseResponseUsingGSON”, for example

Dummy dClass =  parseResponseUsingGSON(jsonStringFromServer,Dummy.java);

Hence JSON is converted to POJO class.

Image Blurring in Android

In one of my project there was a need to show previous activity contents(views) into the present activity., Any guess??! I had too many ideas to implement this but none worked. At last this SO discussion gave me a solution for this problem. Solutions is simple,

  1. Create a Bitmap from your activity’s overall layout
  2. Blur that bitmap with whatever method you want
  3. Add(or unhide) a View in your layout that covers everything. Set background to blurred Bitmap.
  4. Open your dialog/transparent activity
  5. When it closes, either remove the View, or setVisibility(GONE) if you’ll be using it again

Follow these steps.,

  • Converting Activity’s layout to bitmap
public class MainActivity extends Activity {
private RelativeLayout baseLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
baseLayout = (RelativeLayout)findViewById(R.id.container);
baseLayout.setDrawingCacheEnabled(true);
baseLayout.measure(MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED),MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED));
baseLayout.layout(0, 0,baseLayout.getMeasuredWidth(),baseLayout.getMeasuredHeight());
baseLayout.buildDrawingCache(true);
Bitmap bMap = Bitmap.createBitmap(baseLayout.getDrawingCache());
//    sending this image to secondActivity
startActivity(new Intent(this,SecondActivity.class).putExtra(&quot;image&quot;, bMap));
}
}

As a result of above code we can now get Image, but still it is not blurred.

  • Blur the image with any method

I tried much more methods as mentioned in internet, but none worked for me. At last I found this link which saved my life. I modified slightly it to fit as java code.

public class SecondActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Bitmap result = BlurImage((Bitmap)getIntent().getParcelableExtra(&quot;image&quot;));
((ImageView)findViewById(R.id.secondImage)).setImageBitmap(result);
}
@SuppressLint(&quot;NewApi&quot;)
private Bitmap BlurImage(Bitmap input) { 
RenderScript rsScript = RenderScript.create(getApplicationContext());
Allocation alloc = Allocation.createFromBitmap(rsScript, input);
ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(rsScript, alloc.getElement());
blur.setRadius(12);
blur.setInput(alloc);
Bitmap result = Bitmap.createBitmap(input.getWidth(), input.getHeight(), input.getConfig ());
Allocation outAlloc = Allocation.createFromBitmap(rsScript, result);
blur.forEach(outAlloc);
outAlloc.copyTo(result);
rsScript.destroy();
return result;
}
}

Source code of this project is at github.
MainActivity

Screenshot_2014-05-31-20-17-07

SecondActivity

Screenshot_2014-05-31-20-17-15

Enjoy ….!

Endless ListView Tutorial

In Android every thing is possible, I thought of writing this tutorial long ago. ListView is the popular widget we normally use in apps. I will discuss a simple procedure of creating a endless listview here. Normally this mechanism is very well suited for populating listview by getting it items from web and we don’t want to wait until all items in listview to be populated.

What you should know ?

1) To create a custom view

2) To create a custom listview with custom adapter for it. etc

Steps To Follow

a) Creating a custom view

I named it as EndlessListViewit should extend ListView and implement OnScrollListener, add one more interface(to communicate with activity which implements it) I gave a name EndLessListener.

Overrided onScroll method plays a vital role here,

It is called once the AbsListView is scrolled, we will implement our logic here. By comparing visible item count with total items available we may decide whether to load more items from web or not.

@Override
public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount){
if(getAdapter() == null)
     return;
if(getAdapter().getCount() == 0)
     return;

int l = visibleItemCount + firstVisibleItem;

if(l >= totalItemCount && !isLoading){
     //add footer layout
     this.addFooterView(footer);

     //set progress boolean
     isLoading = true;
     
     //call interface method to load new data
     listener.loadData();
 }
}

Whereas ‘footer’ is an view, ‘isLoading’ is the progress boolean flag and ‘loadData()’ is an interface method.
Source code available @ github
Here is the screen shot of required result
Screenshot_2014-03-23-14-38-18

Enjoy …! Happy Coding …!

LAMP server interaction with Android Device

During app development you may be interacting with local servers such as LAMP(Linux,Apache,MySQL,PHP). Every one knows how to interact with local server with computer. But weird thing is how to interact it using Android Device.

It is simple, go through steps below,

1) Get the ip address of your laptop / desktop by

$ sudo ifconfig

HINT : inet addr: 192.xxx.x.x is your ip address

2) Make sure your device has internet, and open any preferred browser in your android device, to start interacting with LAMP type address as below

http://192.xxx.x.x/test.php

NOTE : Make sure your device has Internet.

For more on LAMP server click here and here

Thats it.