Değerli dost StackOverflower,Android'de Matrix kullanılarak döndürülen ImageView'ın yarısı nasıl gösterilir?
bu örneği izleyin (code.tutsplus [dot] com/öğreticiler/android-sdk-yaratan-a-dönen-çevirici - mobil-8868), ben oluşturmak açabiliyorum Matrix
kullanarak dönen bir ImageView
. mantık aşağıdaki gibidir:
- Yük
ImageView
- içine
Bitmap
dokunmatik etkinliğine yaptığı birMatrix
kullanılarakImageView
döndürün.
Bu, Bitmap
tekerleği her döndürdüğünde çekilmeyeceği için performansı garanti eder. Ancak, tekerleğin sadece yarısını görüntülemek istiyorum ve image'un içeriği dinamik olduğundan, görüntüyü ikiye böldükten sonra yukarıdaki adımları izleyerek döndürmek mümkün olmayacaktır.
Ben ancak anladığım kadarıyla, doğrudan bu yüzden geri (korkunç bir performansa sahiptir) yeniden çizme Bitmap
yöntemine düşmek, öldürürdüm o iş yapmak amacıyla kaynak Bitmap
kırpma oluyor, ClipDrawable
araştırılmıştır ettik.
ImageView
görüntüsünü sınırlamanın bir yolu var, bu yüzden yalnızca bir kısmı görüntülenecek mi? Şimdiye kadar ne yaptık
:
MyRotateWheel sınıfı: düzen fi olarak
public class MyMatrixHelper {
private Bitmap imageOriginal, imageScaled;
private Matrix matrix;
private int mImageHeight, mImageWidth;
public MyMatrixHelper(Resources res, int id){
// load the image only once
if (imageOriginal == null) {
imageOriginal = BitmapFactory.decodeResource(res, id);
}
// initialize the matrix only once
if (matrix == null) {
matrix = new Matrix();
} else {
// not needed, you can also post the matrix immediately to restore the old state
matrix.reset();
}
}
public boolean isNecessaryToScaleImage(int width, int height){
if (mImageWidth == 0 || mImageHeight == 0) {
mImageWidth = width;
mImageHeight = height;
// resize
Matrix resize = new Matrix();
resize.postScale((float) Math.min(mImageWidth, mImageHeight)/(float) imageOriginal.getWidth(), (float) Math.min(mImageWidth, mImageHeight)/(float) imageOriginal.getHeight());
imageScaled = Bitmap.createBitmap(imageOriginal, 0, 0, imageOriginal.getWidth(), imageOriginal.getHeight(), resize, false);
// translate to the image view's center
float translateX = mImageWidth/2 - imageScaled.getWidth()/2;
float translateY = mImageHeight/2 - imageScaled.getHeight()/2;
matrix.postTranslate(translateX, translateY);
//imageOriginal.recycle();
return true;
}else{
return false;
}
}
public Bitmap getImageScaled() {
return imageScaled;
}
public Matrix getMatrix() {
return matrix;
}
:
public class MyRotateWheelView extends ImageView {
private MyMatrixHelper mMatrixHelper;
private int mWheelHeight, mWheelWidth;
public MyRotateWheelView(Context context, AttributeSet attrs){
super(context, attrs);
loadImage(R.drawable.my_rotate_wheel);
initWheel();
}
public void loadImage(int id){
mMatrixHelper = new MyMatrixHelper(getResources(), id);
}
public void initWheel(){
setOnTouchListener(new MyOnTouchListener());
//Since we only know after measuring the layout how much space our ImageView fills, we add an OnGlobalLayoutListener.
//In the onGlobalLayout method, we can intercept the event that the layout has been drawn and query the size of our view.
getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// method called more than once, but the values only need to be initialized one time
if (mMatrixHelper.isNecessaryToScaleImage(getWidth(), getHeight())) {
mWheelWidth = getWidth();
mWheelHeight = getHeight();
setImageBitmap(mMatrixHelper.getImageScaled());
setImageMatrix(mMatrixHelper.getMatrix());
}
}
});
}
/**
* Simple implementation of an {@link View.OnTouchListener} for registering the mWheel's touch events.
*/
private class MyOnTouchListener implements View.OnTouchListener {
private double startAngle;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startAngle = getAngle(event.getX(), event.getY());
break;
case MotionEvent.ACTION_MOVE:
double currentAngle = getAngle(event.getX(), event.getY());
double delta = startAngle - currentAngle;
rotateDialer((float) delta); //rotate
startAngle = currentAngle;
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
}
/**
* @return The angle of the unit circle with the image view's center
*/
private double getAngle(double xTouch, double yTouch) {
double x = xTouch - (mWheelWidth/2d);
double y = mWheelHeight - yTouch - (mWheelHeight/2d);
switch (getQuadrant(x, y)) {
case 1:
return Math.asin(y/Math.hypot(x, y)) * 180/Math.PI;
case 2:
return 180 - Math.asin(y/Math.hypot(x, y)) * 180/Math.PI;
case 3:
return 180 + (-1 * Math.asin(y/Math.hypot(x, y)) * 180/Math.PI);
case 4:
return 360 + Math.asin(y/Math.hypot(x, y)) * 180/Math.PI;
default:
return 0;
}
}
/**
* @return The selected quadrant.
*/
private static int getQuadrant(double x, double y) {
if (x >= 0) {
return y >= 0 ? 1 : 4;
} else {
return y >= 0 ? 2 : 3;
}
}
/**
* Rotate the mWheel.
*
* @param degrees The degrees, the mWheel should get rotated.
*/
private void rotateDialer(int i, float degrees) {
mMatrixHelper.getMatrix().postRotate(degrees, mWheelWidth/2, mWheelHeight/2);
setImageMatrix(mMatrixHelper.getMatrix());
}
}
MyMatrixHelper sınıf le:
<.MyRotateWheelView
...
android:scaleType="matrix"/>
UPADTE 1:
Ben kısmen bu sorunu çözdük. Temas olayında güncellenmiş bir Matrix
kullanarak görüntüyü ImageView
içine çekmek için onDraw
10 yöntemini geçersiz kıldım. Bu garanti performansı, görüntü yeniden çizilmediğinden ve görüntü ImageView
'un içinde uygun kırpma ile dönüyor. Bununla birlikte, kalan sorun görüntü şu anda ImageView
'un merkezi etrafında döndürülüyor olmasıdır. Bu çözümün çalışması için, görüntünün merkezinin koordinasyonunu elde etmenin bir yolunu bulmaya ihtiyacım var. Herhangi bir öneri?
Kod pasajı:
private class MyOnTouchListener implements View.OnTouchListener {
private double startAngle;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
...
case MotionEvent.ACTION_MOVE:
double currentAngle = getAngle(event.getX(), event.getY());
double delta = startAngle - currentAngle;
updateMatrix((float)delta);
invalidate();
startAngle = currentAngle;
break;
...
}
return true;
}
}
private void updateMatrix(float delta){
matrix.postRotate(delta, getWidth()/2, getHeight()/2); //need to find out the coordination of the center of the image
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(originalImage, matrix, paint);
}
GÜNCELLEME 2:
Ben resmin merkezinin koordinatı nasıl hesaplanacağını anladım.Şu anda görüntünün ekrandan daha büyük olduğu varsayımını yapıyorum, bu yüzden her vaka düzgün bir şekilde ele alındığında tam çözüm gönderilecektir.
Maalesef başka bir sorunla karşılaşıyorum.
Ancak resim çizilir: my çözüm çalışmalarını yapmak amacıyla, görüntünün alt Resim A bunun olduğu gibi merkezli ImageView
ve düzgün alt ile uyumlu olmalıdır Resim B'daki gibi ImageView
içine.
Herhangi birinin, görüntünün altını görünümün tabanıyla doğru şekilde ortalayıp hizalamanın yolunu gösterebilirse çok minnettar olurum.