Monday, May 26, 2014

Draw star on canvas

Show how to draw star on canvas of custom View. More examples of drawing Path on canvas of custom View HERE.


MainActivity.java
package com.example.androiddrawpath;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.RadioButton;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class MainActivity extends Activity {

 SeekBar radiusBar, innerRadiusBar;
 MyView myView;
 
 SeekBar ptBar;
 TextView textPt;
 final static int MIN_PT = 3;
 
 RadioButton optLayerTypeNone, optLayerTypeSoftware, optLayerTypeHardware;
 TextView textLayerInfo;

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

  radiusBar.setOnSeekBarChangeListener(radiusBarOnSeekBarChangeListener);
  innerRadiusBar.setOnSeekBarChangeListener(innerRadiusBarOnSeekBarChangeListener);
  
  textPt = (TextView)findViewById(R.id.pttext);
  ptBar = (SeekBar)findViewById(R.id.ptbar);
  ptBar.setOnSeekBarChangeListener(ptBarOnSeekBarChangeListener);
  
  optLayerTypeNone = (RadioButton)findViewById(R.id.typeNone);
  optLayerTypeSoftware = (RadioButton)findViewById(R.id.typeSoftware);
  optLayerTypeHardware = (RadioButton)findViewById(R.id.typeHardware);
  textLayerInfo = (TextView)findViewById(R.id.typeinfo);
  
  myView.passElements(textLayerInfo);
  myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

  optLayerTypeNone.setOnCheckedChangeListener(optLayerTypeOnCheckedChangeListener);
  optLayerTypeSoftware.setOnCheckedChangeListener(optLayerTypeOnCheckedChangeListener);
  optLayerTypeHardware.setOnCheckedChangeListener(optLayerTypeOnCheckedChangeListener);
 };
 
 OnCheckedChangeListener optLayerTypeOnCheckedChangeListener = 
  new OnCheckedChangeListener(){

   @Override
   public void onCheckedChanged(CompoundButton buttonView,
     boolean isChecked) {
    if(optLayerTypeNone.isChecked()){
     myView.setLayerType(View.LAYER_TYPE_NONE, null);
    }else if(optLayerTypeSoftware.isChecked()){
     myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }else{
     myView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
    }
    
    myView.invalidate();
   }};

 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 innerRadiusBarOnSeekBarChangeListener = 
  new OnSeekBarChangeListener() {

  @Override
  public void onProgressChanged(SeekBar seekBar, int progress,
    boolean fromUser) {
   float ratio = (float) (innerRadiusBar.getProgress())
     / (float) (innerRadiusBar.getMax());
   myView.setShapeInnerRadiusRatio(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
package com.example.androiddrawpath;

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

public class MyView extends View {
 
 MyShape myShape;
 float ratioRadius, ratioInnerRadius;
 int numberOfPoint = 3; //default
 
 //corresponding to UI element
 TextView textLayerInfo;

 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);
  
  long starting = System.nanoTime();
  
  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, innerRadius;
  if(w > h){
   radius = h * ratioRadius;
   innerRadius = h * ratioInnerRadius;
  }else{
   radius = w * ratioRadius;
   innerRadius = w * ratioInnerRadius;
  }
  
  myShape.setStar(x, y, radius, innerRadius, numberOfPoint);
  canvas.drawPath(myShape.getPath(), myShape.getPaint());
  
  long end = System.nanoTime();
  
  String info = "myView.isHardwareAccelerated() = " + isHardwareAccelerated() + "\n"
    + "canvas.isHardwareAccelerated() = " + canvas.isHardwareAccelerated() + "\n"
    + "processing time (reference only) : " + String.valueOf(end - starting) + " (ns)";
  textLayerInfo.setText(info);
  
 }
 
 public void setShapeRadiusRatio(float ratio){
  ratioRadius = ratio;
 }
 
 public void setShapeInnerRadiusRatio(float ratio){
  ratioInnerRadius = ratio;
 }
 
 public void setNumberOfPoint(int pt){
  numberOfPoint = pt;
 }
 
 public void passElements(TextView textLayerInfo){
  this.textLayerInfo = textLayerInfo;
 }

}

MyShape.java
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 setStar(float x, float y, float radius, float innerRadius, 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)));
  path.lineTo(
   (float)(x + innerRadius * Math.cos(0 + section/2.0)), 
   (float)(y + innerRadius * Math.sin(0 + section/2.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.lineTo(
     (float)(x + innerRadius * Math.cos(section * i + section/2.0)), 
     (float)(y + innerRadius * Math.sin(section * i + section/2.0)));
  }
  
  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:layout_width="match_parent"
        android:layout_height="wrap_content" 
        android:text="inner radius(%)"/>
    <SeekBar 
        android:id="@+id/innerradiusbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:progress="25" />
    <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" />
    
    <RadioGroup
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
     <RadioButton android:id="@+id/typeNone"
         android:layout_width="0dp"
         android:layout_weight="1"
         android:layout_height="wrap_content"
         android:text="LAYER_TYPE_NONE"/>
     <RadioButton android:id="@+id/typeSoftware"
         android:layout_width="0dp"
         android:layout_weight="1"
         android:layout_height="wrap_content"
         android:text="LAYER_TYPE_SOFTWARE"/>
     <RadioButton android:id="@+id/typeHardware"
         android:layout_width="0dp"
         android:layout_weight="1"
         android:layout_height="wrap_content"
         android:text="LAYER_TYPE_HARDWARE"/>
    </RadioGroup>
    
    <RelativeLayout 
        android:layout_width="match_parent"
        android:layout_height="match_parent">
     <TextView 
         android:id="@+id/typeinfo"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_alignParentBottom="true" />
     <com.example.androiddrawpath.MyView 
         android:id="@+id/myview"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
    </RelativeLayout>

</LinearLayout>


download filesDownload the files.

Next:
Draw rounded corner star on canvas

More example of Drawing Path on canvas of custom View.