Draw and resize
Description
The following code shows how to Draw and resize.
Code revised from
Android Recipes:A Problem-Solution Approach
http://www.apress.com/9781430234135
ISBN13: 978-1-4302-3413-5
Example
res\drawable\box.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid
android:color="@android:color/transparent"/>
<stroke
android:width="3dp"
android:color="#F00" />
</shape>
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:orientation="vertical"
tools:context=".MainActivity" >
<TextView
android:id="@+id/textview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:text="Android Recipes" />
<RadioGroup
android:id="@+id/container_options"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#CCC">
<RadioButton
android:id="@+id/option_box"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Box" />
<RadioButton
android:id="@+id/option_arrow"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Arrow" />
</RadioGroup>
</LinearLayout>
MainActivity.java
import android.app.Activity;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RadioGroup;
/* w w w . ja v a2 s . c om*/
import java.util.ArrayList;
public class MainActivity extends Activity implements View.OnTouchListener {
private RadioGroup mOptions;
private ArrayList<Drawable> mMarkers;
private Drawable mTrackingMarker;
private Point mTrackingPoint;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Receive touch events for the view we want to draw on
findViewById(R.id.textview).setOnTouchListener(this);
mOptions = (RadioGroup) findViewById(R.id.container_options);
mMarkers = new ArrayList<Drawable>();
}
/*
* Touch events from the view we are monitoring
* will be delivered here.
*/
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (mOptions.getCheckedRadioButtonId()) {
case R.id.option_box:
handleEvent(R.id.option_box, v, event);
break;
case R.id.option_arrow:
handleEvent(R.id.option_arrow, v, event);
break;
default:
return false;
}
return true;
}
/*
* Process touch events when user has selected to draw a box
*/
private void handleEvent(int optionId, View v, MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Drawable current = markerAt(x, y);
if (current == null) {
//Add a new marker on a new touch
switch(optionId) {
case R.id.option_box:
mTrackingMarker = addBox(v, x, y);
mTrackingPoint = new Point(x, y);
break;
case R.id.option_arrow:
mTrackingMarker = addFlag(v, x, y);
break;
}
} else {
//Remove the existing marker
removeMarker(v, current);
}
break;
case MotionEvent.ACTION_MOVE:
//Update the current marker as we move
if (mTrackingMarker != null) {
switch(optionId) {
case R.id.option_box:
resizeBox(v, mTrackingMarker, mTrackingPoint, x, y);
break;
case R.id.option_arrow:
offsetFlag(v, mTrackingMarker, x, y);
break;
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
//Clear state when gesture is over
mTrackingMarker = null;
mTrackingPoint = null;
break;
}
}
private Drawable addBox(View v, int x, int y) {
Drawable box = getResources().getDrawable(R.drawable.box);
Rect bounds = new Rect(x, y, x, y);
box.setBounds(bounds);
mMarkers.add(box);
v.getOverlay().add(box);
return box;
}
private void resizeBox(View v, Drawable target, Point trackingPoint, int x, int y) {
Rect bounds = new Rect(target.getBounds());
if (x < trackingPoint.x) {
bounds.left = x;
} else {
bounds.right = x;
}
if (y < trackingPoint.y) {
bounds.top = y;
} else {
bounds.bottom = y;
}
//Update drawable bounds and redraw
target.setBounds(bounds);
v.invalidate();
}
/*
* Add a new flag marker at the given coordinate
*/
private Drawable addFlag(View v, int x, int y) {
//Make a new marker drawable
Drawable marker = getResources().getDrawable(R.drawable.flag_arrow);
//Create bounds to match image size
Rect bounds = new Rect(0, 0,
marker.getIntrinsicWidth(), marker.getIntrinsicHeight());
//Center marker bottom around coordinate
bounds.offset(x - (bounds.width() /2), y - bounds.height());
marker.setBounds(bounds);
//Add to the overlay
mMarkers.add(marker);
v.getOverlay().add(marker);
return marker;
}
/*
* Update the position of an existing flag marker
*/
private void offsetFlag(View v, Drawable marker, int x, int y) {
Rect bounds = new Rect(marker.getBounds());
//Move drawable bounds to the next align with the new coordinate
bounds.offset(x - bounds.left - (bounds.width() / 2),
y - bounds.top - bounds.height());
//Update and redraw
marker.setBounds(bounds);
v.invalidate();
}
/*
* Remove the requested marker item
*/
private void removeMarker(View v, Drawable marker) {
mMarkers.remove(marker);
v.getOverlay().remove(marker);
}
/*
* Find the first marker that contains the requested
* coordinate, if one exists.
*/
private Drawable markerAt(int x, int y) {
//Return the first marker found containing the given point
for (Drawable marker : mMarkers) {
if (marker.getBounds().contains(x, y)) {
return marker;
}
}
return null;
}
}