2017-12-15 40 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> 

끝 일부 인터넷 검색 및 독서 후

나는 조각 클래스 내부에 다음과 같은 코드를 구현 자,이 문제는 내가 ge t ImageView의 전체가 단색으로 채색되었습니다 (5, 0.5 및 0.1과 같은 R.dimen.default_scribble_point_radius에 대해 다른 반경 크기를 시도했지만 아무런 소용이 없었습니다).

전 :

Before clicking the image

후 : After clicking the image

내가 세 부분으로 질문이 있습니다

  1. 내가 잘못하고있는 중이 야 무엇을 내가 어떻게 얻을 수 있습니다 ~ 대신에 간단한 점 모양의 원 전체 ImageView가 파란색으로 바뀝니다.

  2. onTouch(View v, MotionEvent event) 방법은 매우 비효율적이라고 생각합니다. 추가 된 각 점에 대해 비트 맵을 다시 그리기 만하면됩니다. 동일한 작업을 수행하는 효율적인 방법이 있는지 궁금합니다.

  3. 드로잉이 수행되는 장소에 대한 transperent 뷰를 사용하면 문제가 발생하지 않을 것이며, 그렇다면 어떻게 달성 될 수 있습니까?

귀하의 의견과지도를 크게 소청합니다.

답변

1

ImageView 바로 위 (z 위주)에 배치 된 투명 View으로 가야합니다. 주된 이유는 성능입니다. 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

불행하게도, 난 당신이 파란색 이미지 뷰를 얻을 왜 아무 생각도 없어. 하지만 내 접근 방식은 (적어도 비트 맵을 처리하지 않기 때문에) 적어도 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)에 대한 두 답변이 꽤 잘 커버한다고 생각합니다. performClick() 일부 구성 요소 (예 : 내게 필요한 옵션 서비스)에서 호출하려고합니다. 그렇지 않으면 필요하지 않습니다. – 0X0nosugar