Map the touch position with a mask, version II.

In the last exercise "Map the touch position with a mask", I tried to map a touched position from screen to a mask bitmap. It's difficult to align the image of a ImageView and the bitmap!

It's another more flexible approach: I create another invisible custom ImageView, MaskView. It have the same layout assigned for TouchView. It use the mask image as background. TouchView is resumed to use the display image as background. Such that I can get background color from MaskView to map with touch position in TouchView.

Doing so, I can easy to allocate it in any place, any size.

Map the touch position with a mask


Implement a custom ImageView, MaskView.java
package com.exercise.AndroidDetechTouch;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.widget.ImageView;

public class MaskView extends ImageView {

Bitmap bitmap;
double bmWidth, bmHeight;

public MaskView(Context context) {
super(context);
init();
}

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

public MaskView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}

private void init(){
bitmap = ((BitmapDrawable)getBackground()).getBitmap();
bmWidth = (double)bitmap.getWidth();
bmHeight = (double)bitmap.getHeight(); 
}

public int getColor(float x, float y){
if ( x < 0 || y < 0 || x > (float)getWidth() || y > (float)getHeight()){
return 0; //Invalid, return 0 
}else{
//Convert touched x, y on View to on Bitmap
int xBm = (int)(x * (bmWidth / (double)getWidth()));
int yBm = (int)(y * (bmHeight / (double)getHeight()));
return bitmap.getPixel(xBm, yBm); 
}
}

}


Modify TouchView.java, it get pixel color from MaskView indirectly.
package com.exercise.AndroidDetechTouch;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ImageView;

public class TouchView extends ImageView {

Bitmap bitmap, mask;
double bmWidth, bmHeight; 

String touchInfo;
float touchX, touchY;

String part;

public TouchView(Context context) {
super(context);
// TODO Auto-generated constructor stub
init();
}

public TouchView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init();
}

public TouchView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
init();
}

private void init(){

//bitmap = ((BitmapDrawable)getDrawable()).getBitmap();
//mask = BitmapFactory.decodeResource(getResources(), R.drawable.android_mask);
//bmWidth = (double)bitmap.getWidth();
//bmHeight = (double)bitmap.getHeight();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
MeasureSpec.getSize(heightMeasureSpec));
}

@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub

switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
touchX = event.getX();
touchY = event.getY();

//long maskColor = getColor(touchX, touchY);
long maskColor = getMaskColor(touchX, touchY);

//Match the color in Mask bitmap
if(maskColor == Color.RED){
touchInfo = "Heart";
}else if(maskColor == Color.GREEN){
touchInfo = "Head";
}else if(maskColor == Color.BLUE){
touchInfo = "Body";
}else if(maskColor == -256){
touchInfo = "Hand";
}else if(maskColor == -16711681){
touchInfo = "Foot";
}else{
touchInfo = "";
}

((AndroidDetechTouchActivity)getContext()).updateMsg(touchInfo, touchX, touchY, (int)maskColor);
return true;

default:
return false;
}

}

private long getMaskColor(float x, float y){
AndroidDetechTouchActivity parent = (AndroidDetechTouchActivity)(getContext());
return parent.getMaskColor(x, y);
}


private long getColor(float x, float y){

if ( x < 0 || y < 0 || x > (float)getWidth() || y > (float)getHeight()){
return 0; //Invalid, return 0
}else{
//Convert touched x, y on View to on Bitmap
int xBm = (int)(x * (bmWidth / (double)getWidth()));
int yBm = (int)(y * (bmHeight / (double)getHeight()));

return mask.getPixel(xBm, yBm);
}
}

}


Modify AndroidDetechTouchActivity.java
package com.exercise.AndroidDetechTouch;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.widget.ImageView;

public class AndroidDetechTouchActivity extends Activity {

TouchView myAndroid;
InfoView infoView;

MaskView myMask;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

myAndroid = (TouchView)findViewById(R.id.myandroid);
infoView = (InfoView)findViewById(R.id.infoview);
myMask = (MaskView)findViewById(R.id.mymask);

}

public void updateMsg(String t_info, float t_x, float t_y, int t_c){

infoView.updateInfo(t_info, t_x, t_y, t_c);

}

public void clearMsg(){

infoView.clearInfo();

}

public long getMaskColor(float x, float y){
return myMask.getColor(x, y);
}

}


Modify main.xml to add MaskView. Both MaskView and TouchView set android:background instead of android:src. Also set MaskView invisible.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
<LinearLayout 
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="bottom"
>
<FrameLayout 
android:layout_width="fill_parent"
android:layout_height="250dp"
>
<com.exercise.AndroidDetechTouch.MaskView
android:id="@+id/mymask"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/android_mask"
android:visibility="invisible"
/>
<com.exercise.AndroidDetechTouch.TouchView
android:id="@+id/myandroid"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/android"
/>
<com.exercise.AndroidDetechTouch.InfoView
android:id="@+id/infoview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>

</FrameLayout>
</LinearLayout>
</LinearLayout>


Download the files.

0 Response to "Map the touch position with a mask, version II."

Post a Comment