2017-07-17 49 views
0

下面是我的小自定義視圖(自定義的ImageView)的目標:得到位圖像素的自定義視圖後旋轉

當我點擊自定義視圖,包含圖像(位圖+矩陣),我想得到像素並檢查像素顏色是否透明,然後我會做點什麼。

這是我的圖片,當應用程序啓動時,黑色是我自定義視圖的背景顏色,我的位圖(紅色箭頭)與圖像視圖具有相同的大小,因此所有黑色在我的位圖中都是透明的:

Image when app starts

的問題是,當我使用矩陣旋轉圖像,然後我點擊我的實際視圖的非透明區域,它打印,在「logcat的」,我點擊一個透明像素

這是我旋轉後的圖像:

Image after rotate

如果我點擊紅色十字標記位置將打印的「紅色」的,如果我點擊藍色十字標記位置它打印「透明」

我不想使用:

Bitmap tmp = Bitmap.createBitmap(img, 0, 0, img.width(), img.height(), matrix, true); 

因爲我使用OnTouchListener,如果我用我的每一個應用程序變得太慢時間前面的方法(laggy)

是任何其他的方法來解決我的問題(可能與數學),如果有人能夠幫助我提前感謝你。

我的佈局:

<LinearLayout 
    android:orientation="vertical" android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:gravity="center" 
    android:background="#fff"> 

    <CustomView 
     android:layout_width="300dp" 
     android:layout_height="300dp" 
     android:background="#000" 
     android:scaleType="matrix"/> 

</LinearLayout> 

我的自定義視圖(代碼只有有用的部分):SOLUTION

public class CustomView extends View { 

    private Bitmap arrow; 

    private RectF viewRect = new RectF(); 
    private PointF center = new PointF(); 

    private Matrix matrix = new Matrix(); 
    private Matrix inverted = new Matrix(); 

    private float angle = Float.NaN; 

    private boolean READY = false; 


    public CustomView(Context context) { 
     super(context); 

     init(); 
    } 

    public CustomView(Context context, @Nullable AttributeSet attrs) { 
     super(context, attrs); 

     init(); 
    } 

    private void init(){ 

     getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 
      @Override 
      public void onGlobalLayout() { 

       if(viewRect.width() == 0 && viewRect.height() == 0) { 
        viewRect = new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight()); 
        center = new PointF(viewRect.width()/2f, viewRect.height()/2f); 

        try { 
         InputStream ims = getContext().getAssets().open("imgs/arrow.png"); 
         arrow = BitmapFactory.decodeStream(ims); 
         arrow = Bitmap.createScaledBitmap(arrow, (int)viewRect.width(), (int)viewRect.height(), true); 
         ims.close(); 
        } catch (IOException ex) { 
         return; 
        } 

        READY = true; 

        setOnTouchListener(new CustomTouchListener()); 
       } 
      } 
     }); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     if(READY) { 
      canvas.drawBitmap(arrow, matrix, null); 
     } 
    } 

    private class CustomTouchListener implements OnTouchListener{ 

     @Override 
     public boolean onTouch(View v, MotionEvent event) { 

      switch (event.getAction()) { 

       case MotionEvent.ACTION_DOWN: 

        matrix.invert(inverted); 
        float[] pts = {event.getX(), event.getY()}; 
        inverted.mapPoints(pts); 
        int x = (int) pts[0]; 
        int y = (int) pts[1]; 
        return viewRect.contains(x, y) && arrow.getPixel(x, y) != 0; 

       case MotionEvent.ACTION_MOVE: 
        float tmpAngle = (float) Math.toDegrees(Math.atan2(event.getY() - center.y, event.getX() - center.x)); 
        if (Float.isNaN(angle)) angle = tmpAngle; 
        matrix.postRotate(tmpAngle - angle, center.x, center.y); 
        angle = tmpAngle; 
        invalidate(); 
        return true; 
      } 

      return false; 
     } 
    } 

} 
+0

請參閱'Matrix#mapPoints'方法 – pskink

+0

您不會獲得顏色,而是獲取映射點,文檔會說:*「將此矩陣應用於2D點的數組,並將轉換後的點寫回數組中」* – pskink

+0

複雜?一次調用'Matrix#mapPoints'很複雜?你試過什麼了? – pskink

回答

0

您需要翻譯點擊座標轉換成旋轉的系統。

x' = center.x + (x - center.x) * Cos(angle) - (y - center.y) * Sin(angle) 
y' = center.y + (x - center.x) * Sin(angle) + (y - center.y) * Cos(angle) 
+0

否不工作它仍然打印「透明」 –

+0

這是關於中心的旋轉。也許你必須改變角度標誌。 – MBo

0

我已經做了類似的事情,我認爲可能會幫助你。我使用abs來確保價值保持積極,因爲我們正在使用顏色。我只會加重相關的代碼

爲了您的自定義視圖,添加一個OnTouch監聽器是這樣的:如果

@Override 
public boolean onTouchEvent(MotionEvent event) 
{ 
    float xvalue = Math.abs(event.getX()); 
    float yvalue = Math.abs(event.getY()); 
    int point = arrow.getPixel((int)xvalue,(int) yvalue);// This will give you the color of the specific pixel on your bitmap. 

    //Here you can convert in to RGB 
    int red = Color.red(point); // Red value 0-255 of that pixel pixel. 
    int green = Color.green(point); // Green value 0-255 of that pixel pixel. 
    int blue = Color.blue(point); // Blue value 0-255 of that pixel pixel. 

    Log.d("Colours","R:" +red +" G:" + green + " B:" + blue); 

    return true; 
} 

不知道這會有幫助嗎?另外,請務必使用

invalidate(); 

刷新您的視圖後,您已完成輪換。