2016-11-01 3 views
0

J'utilise l'option "sous-échantillonnage de l'image dans mon application" et je souhaite ajouter de manière dynamique des repères à un PinView lorsque l'utilisateur clique longuement dessus. La broche de marqueur doit apparaître à la position cliquée.Ajout de repères à la position touchée à l'aide de l'échelle de sous-échantillonnage image

J'ai réalisé qu'une goupille apparaît après un long clic, mais dans une mauvaise position. Voici la méthode onCreateView de mon Fragment:

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 
    pinCounter=0; 

    View rootView = inflater.inflate(R.layout.fragment_edit_plan, container, false); 
    src = getArguments().getString("src"); 
    imageView = (PinView)rootView.findViewById(R.id.imageView); 

    imageView.setImage(ImageSource.uri(src)); 
    imageView.isLongClickable(); 
    imageView.isClickable(); 
    imageView.hasOnClickListeners(); 

    MapPins = new ArrayList(); 
    imageView.setPins(MapPins); 

    imageView.setOnLongClickListener(this); 
    imageView.setOnTouchListener(this); 

    return rootView; 
} 

Les Listener-Méthodes:

@Override 
public boolean onLongClick(View view) { 
    if (view.getId() == R.id.imageView) { 
     Toast.makeText(getActivity(), "Long clicked "+lastKnownX+" "+lastKnownY, Toast.LENGTH_SHORT).show(); 
     Log.d("EditPlanFragment","Scale "+imageView.getScale()); 
     MapPins.add(new MapPin(lastKnownX,lastKnownY,pinCounter)); 
     imageView.setPins(MapPins); 

     imageView.post(new Runnable(){ 
      public void run(){ 
       imageView.getRootView().postInvalidate(); 
      } 
     }); 

     return true; 
    } 
    return false; 
} 

@Override 
public boolean onTouch(View v, MotionEvent event) { 
    if (v.getId()== R.id.imageView && event.getAction() == MotionEvent.ACTION_DOWN){ 
     lastKnownX= event.getX(); 
     lastKnownY= event.getY(); 
    } 
    return false; 
} 

Mon XML-fichier:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:app="http://schemas.android.com/apk/res-auto" 
android:id="@+id/content" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:paddingTop="50dp" 
> 

<com.example.viktoriabock.phoenixversion1.PinView 
    android:id="@+id/imageView" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:longClickable="true" 

    /> 

Et la PinView Classe:

public class PinView extends SubsamplingScaleImageView { 

    private PointF sPin; 

    ArrayList<MapPin> mapPins; 
    ArrayList<DrawPin> drawnPins; 
    Context context; 
    String tag = getClass().getSimpleName(); 

    public PinView(Context context) { 
     this(context, null); 
     this.context = context; 
    } 

    public PinView(Context context, AttributeSet attr) { 
     super(context, attr); 
     this.context = context; 
     initialise(); 
    } 

    public void setPins(ArrayList<MapPin> mapPins) { 
     this.mapPins = mapPins; 
     initialise(); 
     invalidate(); 
    } 

    public void setPin(PointF pin) { 
     this.sPin = pin; 
    } 

    public PointF getPin() { 
     return sPin; 
    } 

    private void initialise() { 

    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 

     // Don't draw pin before image is ready so it doesn't move around during  setup. 
     if (!isReady()) { 
      return; 
     } 

     drawnPins = new ArrayList<>(); 

     Paint paint = new Paint(); 
     paint.setAntiAlias(true); 
     float density = getResources().getDisplayMetrics().densityDpi; 


     for (int i = 0; i < mapPins.size(); i++) { 
      MapPin mPin = mapPins.get(i); 
      //Bitmap bmpPin = Utils.getBitmapFromAsset(context, mPin.getPinImgSrc()); 
      Bitmap bmpPin = BitmapFactory.decodeResource(this.getResources(), R.drawable.pushpin_blue); 

      float w = (density/420f) * bmpPin.getWidth(); 
      float h = (density/420f) * bmpPin.getHeight(); 
      bmpPin = Bitmap.createScaledBitmap(bmpPin, (int) w, (int) h, true); 

      PointF vPin = sourceToViewCoord(mPin.getPoint()); 
      //in my case value of point are at center point of pin image, so we need to adjust it here 

      float vX = vPin.x - (bmpPin.getWidth()/2); 
      float vY = vPin.y - bmpPin.getHeight(); 

      canvas.drawBitmap(bmpPin, vX, vY, paint); 

      //add added pin to an Array list to get touched pin 
      DrawPin dPin = new DrawPin(); 
      dPin.setStartX(mPin.getX() - w/2); 
      dPin.setEndX(mPin.getX() + w/2); 
      dPin.setStartY(mPin.getY() - h/2); 
      dPin.setEndY(mPin.getY() + h/2); 
      dPin.setId(mPin.getId()); 
      drawnPins.add(dPin); 
     } 
    } 

    public int getPinIdByPoint(PointF point) { 
     for (int i = drawnPins.size() - 1; i >= 0; i--) { 
      DrawPin dPin = drawnPins.get(i); 
      if (point.x >= dPin.getStartX() && point.x <= dPin.getEndX()) { 
       if (point.y >= dPin.getStartY() && point.y <= dPin.getEndY()) { 
        return dPin.getId(); 
       } 
      } 
     } 
     return -1; //negative no means no pin selected 
    } 
} 

Répondre

0

Vous collectez les coordonnées d'écran de la pression longue, puis dans l'affichage personnalisé, vous les convertissez des coordonnées de la source en coordonnées d'écran. Vous devez convertir les coordonnées de l'événement en coordonnées source lorsque vous obtenez l'événement de frappe, en utilisant la méthode viewToSourceCoord de la vue.

Il existe un moyen plus simple d'effectuer cela que d'utiliser vos valeurs lastKnown - utilisez les vôtres GestureDetector.

Pour un exemple de fonctionnement complet d'un détecteur de mouvement à pression longue, voir AdvancedEventHandlingActivity sample class.