Friday, May 23, 2014

Draw Path of polygon on canvas of custom View

This example works on last, to draw Path of equal-length polygon, on canvas.


MainActivity.java
package com.example.androiddrawpath;

import android.app.Activity;
import android.os.Bundle;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class MainActivity extends Activity {

 SeekBar radiusBar;
 MyView myView;
 
 SeekBar ptBar;
 TextView textPt;
 final static int MIN_PT = 3;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  radiusBar = (SeekBar) findViewById(R.id.radiusbar);
  myView = (MyView) findViewById(R.id.myview);
  float defaultRatio = (float) (radiusBar.getProgress())
    / (float) (radiusBar.getMax());
  myView.setShapeRadiusRatio(defaultRatio);

  radiusBar.setOnSeekBarChangeListener(radiusBarOnSeekBarChangeListener);
  
  textPt = (TextView)findViewById(R.id.pttext);
  ptBar = (SeekBar)findViewById(R.id.ptbar);
  ptBar.setOnSeekBarChangeListener(ptBarOnSeekBarChangeListener);

 };

 OnSeekBarChangeListener radiusBarOnSeekBarChangeListener = 
  new OnSeekBarChangeListener() {

  @Override
  public void onProgressChanged(SeekBar seekBar, int progress,
    boolean fromUser) {
   float ratio = (float) (radiusBar.getProgress())
     / (float) (radiusBar.getMax());
   myView.setShapeRadiusRatio(ratio);
   myView.invalidate();
  }

  @Override
  public void onStartTrackingTouch(SeekBar seekBar) {}

  @Override
  public void onStopTrackingTouch(SeekBar seekBar) {}

 };
 
 OnSeekBarChangeListener ptBarOnSeekBarChangeListener = 
  new OnSeekBarChangeListener() {

  @Override
  public void onProgressChanged(SeekBar seekBar, int progress,
    boolean fromUser) {
   int pt = progress + MIN_PT;
   textPt.setText("number of point in polygon: " + String.valueOf(pt));
   myView.setNumberOfPoint(pt);
   myView.invalidate();
  }

  @Override
  public void onStartTrackingTouch(SeekBar seekBar) {}

  @Override
  public void onStopTrackingTouch(SeekBar seekBar) {}

 };

}

MyView.java, our custom View.
package com.example.androiddrawpath;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;

public class MyView extends View {
 
 MyShape myShape;
 float ratioRadius;
 int numberOfPoint = 3; //default

 public MyView(Context context) {
  super(context);
  initMyView();
 }

 public MyView(Context context, AttributeSet attrs) {
  super(context, attrs);
  initMyView();
 }

 public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  initMyView();
 }
 
 public void initMyView(){
  myShape = new MyShape();
 }
 
 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  
  int w = getWidth();
  int h = getHeight();
  
  if((w==0) || (h==0)){
   return;
  }
  
  float x = (float)w/2.0f;
  float y = (float)h/2.0f;
  float radius;
  if(w > h){
   radius = h * ratioRadius;
  }else{
   radius = w * ratioRadius;
  }
  
  myShape.setPolygon(x, y, radius, numberOfPoint);
  canvas.drawPath(myShape.getPath(), myShape.getPaint());
 }
 
 public void setShapeRadiusRatio(float ratio){
  ratioRadius = ratio;
 }
 
 public void setNumberOfPoint(int pt){
  numberOfPoint = pt;
 }

}

MyShape.java, it is the object hold the Path and Paint to be drawn on our View.
package com.example.androiddrawpath;

import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;

public class MyShape {

 private Paint paint;
 private Path path;

 public MyShape() {
  paint = new Paint();
  paint.setColor(Color.BLUE);
  paint.setStrokeWidth(3);
  paint.setStyle(Paint.Style.STROKE);
  
  path = new Path();
 }

 public void setCircle(float x, float y, float radius, Path.Direction dir){
  path.reset();
  path.addCircle(x, y, radius, dir);
 }
 
 public void setPolygon(float x, float y, float radius, int numOfPt){
  
  double section = 2.0 * Math.PI/numOfPt;
  
  path.reset();
  path.moveTo(
   (float)(x + radius * Math.cos(0)), 
   (float)(y + radius * Math.sin(0)));
  
  for(int i=1; i<numOfPt; i++){
   path.lineTo(
    (float)(x + radius * Math.cos(section * i)), 
    (float)(y + radius * Math.sin(section * i)));
  }
  
  path.close();
  
 }
 
 public Path getPath(){
  return path;
 }
 
 public Paint getPaint(){
  return paint;
 }
 
}

/res/layout/activity_main.xml.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.androiddrawpath.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />
    
    <TextView 
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
        android:text="radius(%)"/>
    <SeekBar 
        android:id="@+id/radiusbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:progress="50" />
    <TextView 
        android:id="@+id/pttext"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
        android:text="number of point in polygon: 3"/>
    <SeekBar 
        android:id="@+id/ptbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="10"
        android:progress="0" />
    
    <com.example.androiddrawpath.MyView 
        android:id="@+id/myview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>


download filesDownload the files.

More examples of Draw Path on canvas of custom View.

3 comments:

Anonymous said...

Thank you for polygons function and nice explanation of drawing them.
Well done Mister :)

Anonymous said...

Very nice work you did there, helped me a lot, Thanks!

Harish said...

Thanks for your polygons concept. It helped me a lot.