В этом примере мы покажем вам, как создать простое приложение для рисования в 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; } } }