まさにこのような質問がたくさんありました。私はそれらを経験しましたが、それを機能させることができませんでした。
マイ アクティビティ
public class MainActivity extends Activity {
private static final String TAG = "GT:MA";
private ImageView imageView;
Bitmap original;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "in onCreate method");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) this.findViewById(R.id.image);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
int resId = getResources().getIdentifier("beerl", "drawable", "com.sivaprasadvarma.grabtouch");
original = BitmapFactory.decodeResource(getResources(), resId, options);
Log.i(TAG, "original size after decoding: "
+ String.valueOf(original.getWidth()) + " / "
+ String.valueOf(original.getHeight()));
imageView.setImageBitmap(original);
imageView.setOnTouchListener(myOnTouchSelectingListener);
}
// I've implemented diff methods in answers here
// http://stackoverflow.com/questions/4933612/how-to-convert-coordinates-of-the-image-view-to-the-coordinates-of-the-bitmap
OnTouchListener myOnTouchSelectingListener =
new OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
Log.i(TAG, "---------------------");
// 1st method
float eventX = event.getX();
float eventY = event.getY();
float[] eventXY = new float[] {eventX, eventY};
Log.i(TAG, "1: touched position: " + String.valueOf(eventX) + " / "
+ String.valueOf(eventY));
//2nd method
Matrix invertMatrix = new Matrix();
((ImageView)view).getImageMatrix().invert(invertMatrix);
invertMatrix.mapPoints(eventXY);
int x = Integer.valueOf((int)eventXY[0]);
int y = Integer.valueOf((int)eventXY[1]);
Log.i(TAG, "2: Inverted touch position by invMatrix: "
+ String.valueOf(x) + " / "
+ String.valueOf(y));
Drawable imgDrawable = ((ImageView)view).getDrawable();
Bitmap bitmap = ((BitmapDrawable)imgDrawable).getBitmap();
// make sure they are of same size
Log.i(TAG, "from getter drawable size: "
+ String.valueOf(bitmap.getWidth()) + " / "
+ String.valueOf(bitmap.getHeight()));
Log.i(TAG, "actual drawable size: "
+ String.valueOf(original.getWidth()) + " / "
+ String.valueOf(original.getHeight()));
//Limit x, y range within bitmap
if(x < 0){
x = 0;
}else if(x > bitmap.getWidth()-1){
x = bitmap.getWidth()-1;
}
if(y < 0){
y = 0;
}else if(y > bitmap.getHeight()-1){
y = bitmap.getHeight()-1;
}
// mapping them back to bitmap coordinates
Rect imageBounds = imgDrawable.getBounds();
//original height and width of the bitmap
int intrinsicHeight = imgDrawable.getIntrinsicHeight();
int intrinsicWidth = imgDrawable.getIntrinsicWidth();
Log.i(TAG, "intrinsic width / height: "
+ String.valueOf(intrinsicWidth) + " / "
+ String.valueOf(intrinsicHeight));
//height and width of the visible (scaled) image
int scaledHeight = imageBounds.height();
int scaledWidth = imageBounds.width();
//Find the ratio of the original image to the scaled image
//Should normally be equal unless a disproportionate scaling
float heightRatio = intrinsicHeight / scaledHeight;
float widthRatio = intrinsicWidth / scaledWidth;
// 3rd method
//get the distance from the left and top of the image bounds
int scaledImageOffsetX = Math.round(event.getX() - imageBounds.left);
int scaledImageOffsetY = Math.round(event.getY() - imageBounds.top);
//scale these distances according to the ratio of your scaling
//For example, if the original image is 1.5x the size of the scaled
//image, and your offset is (10, 20), your original image offset
//values should be (15, 30).
int originalImageOffsetX = Math.round(scaledImageOffsetX * widthRatio);
int originalImageOffsetY = Math.round(scaledImageOffsetY * heightRatio);
Log.i(TAG, "3: mapped position: "
+ String.valueOf(originalImageOffsetX) + " / "
+ String.valueOf(originalImageOffsetY));
//4th method
int inv_scaledImageOffsetX = x - imageBounds.left;
int inv_scaledImageOffsetY = y - imageBounds.top;
int inv_originalImageOffsetX = Math.round(inv_scaledImageOffsetX * widthRatio);
int inv_originalImageOffsetY = Math.round(inv_scaledImageOffsetY * heightRatio);
Log.i(TAG, "4: inv mapped position: "
+ String.valueOf(inv_originalImageOffsetX) + " / "
+ String.valueOf(inv_originalImageOffsetY));
int touchedRGB = bitmap.getPixel(x, y);
int org_touchedRGB = original.getPixel(x, y);
// 5th method
float[] point_coords = getPointerCoords((ImageView)view, event);
Log.i(TAG, "5: pointer coords position: "
+ String.valueOf(Math.round(point_coords[0])) + " / "
+ String.valueOf(Math.round(point_coords[1])));
Log.i(TAG, "getter touched color: " + "#" + Integer.toHexString(touchedRGB));
Log.i(TAG, "original touched color: " + "#" + Integer.toHexString(org_touchedRGB));
Log.i(TAG, "---------------------");
return true;
}
};
private final float[] getPointerCoords(ImageView view, MotionEvent e)
{
final int index = e.getActionIndex();
final float[] coords = new float[] { e.getX(index), e.getY(index) };
Matrix matrix = new Matrix();
view.getImageMatrix().invert(matrix);
matrix.postTranslate(view.getScrollX(), view.getScrollY());
matrix.mapPoints(coords);
return coords;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
マイレイアウト
<?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:gravity="center"
android:orientation="horizontal" >
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:contentDescription="@string/descImage"
android:src="@drawable/beerl" />
</LinearLayout>
基本的に、アクティビティでタッチされたピクセルの位置を取得する 5 つの方法を実装しました。それらをログに記録しています。レイアウトには ImageView しかありません。私の画像のサイズは 960x540 です。そのため、画像のほぼ中央に触れると、480/270 に近い値が得られるはずですが、画像の中央近くに触れると、ログに次のように表示されます
7-16 11:00:50.097: I/GT:MA(3273): ---------------------
07-16 11:00:50.097: I/GT:MA(3273): 1: touched position: 330.0 / 166.0
07-16 11:00:50.097: I/GT:MA(3273): 2: Inverted touch position by invMatrix: 330 / 166
07-16 11:00:50.097: I/GT:MA(3273): from getter drawable size: 960 / 540
07-16 11:00:50.097: I/GT:MA(3273): actual drawable size: 960 / 540
07-16 11:00:50.097: I/GT:MA(3273): intrinsic width / height: 640 / 360
07-16 11:00:50.097: I/GT:MA(3273): 3: mapped position: 330 / 166
07-16 11:00:50.097: I/GT:MA(3273): 4: inv mapped position: 330 / 166
07-16 11:00:50.097: I/GT:MA(3273): 5: pointer coords position: 330 / 166
07-16 11:00:50.097: I/GT:MA(3273): getter touched color: #ffcd7d27
07-16 11:00:50.097: I/GT:MA(3273): original touched color: #ffcd7d27
07-16 11:00:50.097: I/GT:MA(3273): ---------------------
画像の右下付近をクリックすると、ログに次のように表示されます
07-16 11:03:31.419: I/GT:MA(3273): ---------------------
07-16 11:03:31.419: I/GT:MA(3273): 1: touched position: 635.0 / 348.0
07-16 11:03:31.419: I/GT:MA(3273): 2: Inverted touch position by invMatrix: 635 / 348
07-16 11:03:31.419: I/GT:MA(3273): from getter drawable size: 960 / 540
07-16 11:03:31.419: I/GT:MA(3273): actual drawable size: 960 / 540
07-16 11:03:31.419: I/GT:MA(3273): intrinsic width / height: 640 / 360
07-16 11:03:31.419: I/GT:MA(3273): 3: mapped position: 635 / 348
07-16 11:03:31.419: I/GT:MA(3273): 4: inv mapped position: 635 / 348
07-16 11:03:31.429: I/GT:MA(3273): 5: pointer coords position: 635 / 348
07-16 11:03:31.429: I/GT:MA(3273): getter touched color: #ff242722
07-16 11:03:31.429: I/GT:MA(3273): original touched color: #ff242722
07-16 11:03:31.429: I/GT:MA(3273): ---------------------
プロジェクト全体はここ[zip] にあります。
組み込みの幅と組み込みの高さが BitmapDrawable の実際の幅と高さと異なるのはなぜですか。画像のサイズがintrinsicWidth XintrinsicHeightであると仮定すると、正しい値を取得しているように見えます。なぜそうなのですか?タッチされたピクセルの正しいビットマップ座標を取得する方法。