2017-12-15 25 views
2

私は、アクティビティから見たフラグメントに存在するImageView内のイメージを表示するアプリケーションを持っています。タッチイベントの座標を中心とした小さな点状の円を描いて、ImageViewのタッチイベントに反応したいと思います。効率的に画像上に描画するタッチイベントに応答してフラグメントの内部に存在するビュー

いくつかのグーグルの後、私はフラグメントのクラス内の次のコードを実装読み:

public class ImageViewFragment extends Fragment implements View.OnTouchListener 
{ 
    private ImageView mImageView; 
    private Bitmap mBitmap; 
    private List<Pair<Integer, Integer>> mScribblePointsCoords; 
    private Paint mPaint; 

public interface OnScribbleUpdate 
{ 
    void onNewScribblePoint(List<Pair<Integer, Integer>> coordinates); 

} 

@Override 
public boolean onTouch(View v, MotionEvent event) 
{ 
    v.onTouchEvent(event); 
    return true; 
} 
@Override 
public void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    mScribblePointsCoords = new ArrayList<>(); 
} 
@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
{ 
    View view = inflater.inflate(R.layout.image_view_fragment, container, false); 
    view.setOnTouchListener(new View.OnTouchListener() 
    { 
     @Override 
     public boolean onTouch(View v, MotionEvent event) 
     { 
      if(event.getAction() == MotionEvent.ACTION_DOWN) 
      { 
       int x = (int) event.getX(); 
       int y = (int) event.getY(); 
       mScribblePointsCoords.add(new Pair<>(x, y)); 
       Bitmap tempBitmap = mBitmap.copy(mBitmap.getConfig(), true); 
       Canvas canvas = new Canvas(tempBitmap); 
       canvas.drawCircle(x, y, R.dimen.default_scribble_point_radius, mPaint); 
       mImageView.setImageDrawable(new BitmapDrawable(getResources(), tempBitmap)); 
       mBitmap = tempBitmap; 
       return true; 
      } 
      return false; 
     } 
    }); 
    mPaint = new Paint(); 
    mPaint.setColor(Color.BLUE); 
    mImageView = view.findViewById(R.id.new_photo_view); 
    mImageView.setImageBitmap(mBitmap); 
    return view; 
} 

@Override 
public void onResume() 
{ 
    super.onResume(); 
    mImageView.setImageBitmap(mBitmap); 
} 

public void setImage(Bitmap bmp) 
{ 
    mBitmap = bmp.copy(bmp.getConfig(), false); 
    if(this.isResumed()) 
    { 
     mImageView.setImageBitmap(mBitmap); 
    } 
} 

public void clearScribble() 
{ 
    mScribblePointsCoords.clear(); 
} 

public List<Pair<Integer, Integer>> getScribbleCoordinates() 
{ 
    return mScribblePointsCoords; 
} 
} 

編集:編集の image_view_fragment.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
      xmlns:app="http://schemas.android.com/apk/res-auto" 
      xmlns:tools="http://schemas.android.com/tools" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      tools:context="cofproject.tau.android.cof.ImageViewFragment"> 

    <ImageView 
     android:id="@+id/new_photo_view" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:visibility="visible" 
     app:srcCompat="@android:color/background_dark"/> 
</FrameLayout> 

エンド

今、この問題は、私がImageViewの全体が青で塗りつぶされていました(5、0.5、0.1などR.dimen.default_scribble_point_radiusの異なる半径のサイズを試しましたが、役に立たなかった)。

前:

Before clicking the image

後:After clicking the image

は、私は3つの部分の質問があります。

  1. 私が間違っているのは何をして、私はどのように取得することができます単純なドット状の円ではなく、 ImageView全体が青色になります。

  2. 私の考えているonTouch(View v, MotionEvent event)の方法は、追加されたドットごとにビットマップを再描画する必要があり、同じことを達成する効率的な方法があるかどうか疑問に思っていました。

  3. 絵が描かれている場所が分かりにくいですが、どうすればそのようなことができますか?

あなたのご意見とご指摘は大変ありがたいです。

答えて

1

Viewは、ImageViewのちょうど上(z軸上)に配置してください。これの主な理由はパフォーマンスです。ImageViewは、小さな青い円を描く場合にはかなり重いタイプのViewです。

したがって、Viewというカスタムを作成し、図面を作成してImageViewの上に配置します。私はFrameLayoutの両方でそれらを置くことによって、これを達成:

<FrameLayout 
    android:layout_width="200dp" 
    android:layout_height="200dp"> 

    <ImageView 
     android:id="@+id/imageView" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent"/> 

    <com.example.paintingcircles.DottedView 
     android:id="@+id/dottedView" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent"/> 
</FrameLayout> 

私はあなたのセットアップに続き、匿名OnTouchListenerを使用しますが、もちろん、あなただけのようにもDottedViewオーバーライドonTouchEvent()を持つことができます。onCreate()

final DottedView dottedView = (DottedView) findViewById(R.id.dottedView); 
dottedView.setOnTouchListener(new View.OnTouchListener() 
{ 
    @Override 
    public boolean onTouch(View view, MotionEvent event) 
    { 
     if(event.getAction() == MotionEvent.ACTION_DOWN) 
     { 
      int x = (int) event.getX(); 
      int y = (int) event.getY(); 
      dottedView.addScribblePointsCoords(new Pair<>(x, y)); 
      dottedView.invalidate(); 
      return true; 
     } 
     return false; 
    } 
}); 

DottedView.java:

public class DottedView extends View 
{ 
    private ArrayList<Pair<Integer, Integer>> mScribblePointsCoords = new ArrayList<>(); 
    private int radius = 5; 
    private Paint mPaint; 

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

    public DottedView(Context context, @Nullable AttributeSet attrs) 
    { 
     super(context, attrs); 
     init(); 
    } 

    public DottedView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) 
    { 
     super(context, attrs, defStyleAttr); 
     init(); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) 
    { 
     super.onDraw(canvas); 
     for (Pair<Integer, Integer> pair: mScribblePointsCoords){ 
      canvas.drawCircle(pair.first, pair.second, radius, mPaint); 
     } 
    } 

    public void addScribblePointsCoords(Pair pair){ 
     mScribblePointsCoords.add(pair); 
    } 

    private void init() 
    { 
     mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 
     mPaint.setColor(Color.BLUE); 
    } 
} 
+0

残念ながら、私はあなたが青のImageViewのを取得する理由は考えてきません。しかし、私のアプローチは、少なくともLollipop(Android 5)とNougat(Android 7)を実行しているエミュレータで、ビットマップを処理しようとしないためにこの問題に遭遇していないと思われます。 – 0X0nosugar

+0

詳細な回答ありがとうございます。 私はこの警告を受け取りました: カスタムビュー '' DottedView''に 'setOnTouchListener'が呼び出されましたが、' performClick'をオーバーライドしません。 私はそれに関わるべきですか? –

+0

私は[このSOの投稿](https://stackoverflow.com/questions/27462468/custom-view-overrides-ontouchevent-but-not-performclick/32995457)の2つの答えはかなりうまくカバーすると思います:performClick()あなたがそれを呼び出すためのいくつかのコンポーネント(例えばアクセシビリティサービス)を期待している場合。それ以外の場合は必要ありません。 – 0X0nosugar

関連する問題