Статьи

Пример Android: разработка приложений для рисования и графики

В этом примере мы покажем вам, как создать простое приложение для рисования в Android. Вы можете изменить стиль и цвет пера в приложении. Вы также можете сохранить свой рисунок после покраски. Приложение в основном использует пакет android.graphics . Мы можем увидеть снимок экрана и исходный код здесь:

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.easyinfogeek.drawingpad"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.easyinfogeek.drawingpad.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Класс активности и класс представления
MainActivity.java

package com.easyinfogeek.drawingpad;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.view.Window;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {


 private DrawPadView hbView;

 private AlertDialog dialog;
 private View dialogView;
 private TextView shouWidth;
 private SeekBar widthSb;
 private int paintWidth;

 private void initView(){
  dialogView = getLayoutInflater().inflate(R.layout.dialog_width_set, null);
  shouWidth = (TextView) dialogView.findViewById(R.id.textView1);
  widthSb = (SeekBar) dialogView.findViewById(R.id.seekBar1);
  widthSb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

   @Override
   public void onStopTrackingTouch(SeekBar seekBar) {

   }

   @Override
   public void onStartTrackingTouch(SeekBar seekBar) {

   }

   @Override
   public void onProgressChanged(SeekBar seekBar, int progress,
     boolean fromUser) {
    shouWidth.setText("Current Width:"+(progress+1));
    paintWidth = progress+1;
   }
  });
  hbView = (DrawPadView)findViewById(R.id.drawPadView1);
  dialog = new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_info).setTitle("Set the size of your Pen").
    setView(dialogView).setPositiveButton("Confirm", new OnClickListener() {

     @Override
     public void onClick(DialogInterface dialog, int which) {
      hbView.setPaintWidth(paintWidth);
     }
    }).setNegativeButton("Cancel", null).create();
 }

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  requestWindowFeature(Window.FEATURE_NO_TITLE);
  setContentView(R.layout.activity_main);
  initView();
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  SubMenu colorSm = menu.addSubMenu(1, 1, 1, "Select Pen color");
  colorSm.add(2, 200, 200, "red");
  colorSm.add(2, 210, 210, "green");
  colorSm.add(2, 220, 220, "blue");
  colorSm.add(2, 230, 230, "purple");
  colorSm.add(2, 240, 240, "yellow");
  colorSm.add(2, 250, 250, "black");
  menu.add(1, 2, 2, "Set pen size");
  SubMenu widthSm = menu.addSubMenu(1, 3, 3, "Set Pen style");
  widthSm.add(3, 300, 300, "Stoke");
  widthSm.add(3, 301, 301, "Fill ");
  menu.add(1, 4, 4, "Clear Drawing");
  menu.add(1, 5, 5, "Save drawing");
  menu.add(1, 6, 6, "Exit");
  return true;
 }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
  int index = item.getItemId();
  switch(index){
  case 200:
   hbView.setColor(Color.RED);
   break;
  case 210:
   hbView.setColor(Color.GREEN);
   break;
  case 220:
   hbView.setColor(Color.BLUE);
   break;
  case 230:
   hbView.setColor(Color.MAGENTA);
   break;
  case 240:
   hbView.setColor(Color.YELLOW);
   break;
  case 250:
   hbView.setColor(Color.BLACK);
   break;
  case 2:
   dialog.show();
   break;
  case 300:
   hbView.setStyle(DrawPadView.PEN);
   break;
  case 301:
   hbView.setStyle(DrawPadView.PAIL);
   break;
  case 4:
   hbView.clearScreen();
   break;
  case 5:
   if(SaveViewUtil.saveScreen(hbView)){
    Toast.makeText(this, "Save drawing succeed!", 0).show();
   }else{
    Toast.makeText(this, "Save drawing fail. Please check your SD card", 0).show();
   }
   break;
  case 6:
   finish();
   break;
  }
  return true;
 }


}

DrawPadView.java

package com.easyinfogeek.drawingpad;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;



public class DrawPadView extends View {


 private Bitmap cacheBitmap;

 private Canvas cacheCanvas;

 private Paint paint;

 private Paint BitmapPaint;

 private Path path;

 private int height;

 private int width;

 /** Last saved X-coordinate */
 private float pX;
 /** Last saved Y-coordinate*/
 private float pY;

 /** Initial color */
 private int paintColor = Color.RED;

 private static Paint.Style paintStyle = Paint.Style.STROKE;
 /** Paint Point size */
 private static int paintWidth = 3;

 private Canvas canvas;


 /** get the height and width */
 @Override
 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  height = h;
  width = w;
  init();
 }

 private void init(){
  cacheBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
  cacheCanvas = new Canvas(cacheBitmap);
  paint = new Paint(Paint.ANTI_ALIAS_FLAG);
  path = new Path();
  BitmapPaint = new Paint();
  updatePaint();
 }

 private void updatePaint(){
  paint.setColor(paintColor);
  paint.setStyle(paintStyle);
  paint.setStrokeWidth(paintWidth);
 }

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

 public DrawPadView(Context context){
  super(context);
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
  int action = event.getAction();
  switch (action) {
  case MotionEvent.ACTION_DOWN:
   path.moveTo(event.getX(), event.getY());
   pX = event.getX();
   pY = event.getY();
   break;
  case MotionEvent.ACTION_MOVE:
   path.quadTo(pX, pY, event.getX(), event.getY());
   pX = event.getX();
   pY = event.getY();
   break;
  case MotionEvent.ACTION_UP:
   cacheCanvas.drawPath(path, paint);
   path.reset();
   break;
  }
  invalidate();

  return true;
 }

 @Override
 protected void onDraw(Canvas canvas) {
  this.canvas = canvas;
  BitmapPaint = new Paint();
  canvas.drawBitmap(cacheBitmap, 0,0, BitmapPaint);
  canvas.drawPath(path, paint);

 }


 public void setColor(int color){
  paintColor = color;
  updatePaint();
 }


 public void setPaintWidth(int width){
  paintWidth = width;
  updatePaint();
 }

 public static final int PEN = 1;
 public static final int PAIL = 2;


 public void setStyle(int style){
  switch(style){
  case PEN:
   paintStyle = Paint.Style.STROKE;
   break;
  case PAIL:
   paintStyle = Paint.Style.FILL;
   break;
  }
  updatePaint();
 }

 /** clear your drawing*/
 public void clearScreen(){
  if(canvas != null){
   Paint backPaint = new Paint();
   backPaint.setColor(Color.WHITE);
   canvas.drawRect(new Rect(0, 0, width, height), backPaint);
   cacheCanvas.drawRect(new Rect(0, 0, width, height), backPaint);
  }
  invalidate();
 }

}

Другой XML-файл для макета:
activity_main.xml

<RelativeLayout 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"
    tools:context=".MainActivity" >

    <com.example.huatuban.DrawPadView
        android:id="@+id/drawPadView1"
        android:background="#ffffffff"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

menu_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="setColor" />

    <RadioButton
        android:id="@+id/radioButton1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="blue"
        android:button="@null"
        android:background="@drawable/selector_blueselector"
         />

    <Button android:background="@drawable/menu_blue"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
        android:text="hehe"/>

</LinearLayout>

dialog_width_set.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Set the width" />

    <SeekBar
        android:id="@+id/seekBar1"
        android:layout_width="match_parent"
        android:max="9"
        android:progress="2"
        android:layout_height="wrap_content" />

</LinearLayout>

Класс
утилит для сохранения изображения SaveViewUtil.java

package com.easyinfogeek.drawingpad;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.os.Environment;
import android.view.View;

public class SaveViewUtil {

 private static final File rootDir = new File(Environment.getExternalStorageDirectory()+File.separator+"huaban/");

 /** Save picture to file */
 public static boolean saveScreen(View view){
  //determine if SDCARD is available
  if(!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())){
   return false;
  }
  if(!rootDir.exists()){
   rootDir.mkdir();
  }
  view.setDrawingCacheEnabled(true);
  view.buildDrawingCache();
  Bitmap bitmap = view.getDrawingCache();
  try {
   bitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream(new File(rootDir,System.currentTimeMillis()+".jpg")));
   return true;
  } catch (FileNotFoundException e) {
   e.printStackTrace();
   return false;
  }finally{
   view.setDrawingCacheEnabled(false);
   bitmap = null;
  }
 }
}