web-dev-qa-db-fra.com

La vue personnalisée a appelé setOnTouchListener mais ne remplace pas performClick (la classe étend la vue Activité NON)

J'ai créé une activité Android implémentant un peu d'OpenCV. Cela consiste simplement à créer une vue de caméra personnalisée, et lorsque vous touchez l'écran, la photo est enregistrée.

Mon seul problème est que le code mOpenCvCameraView.setOnTouchListener(MainActivity.this); à l'intérieur de BaseLoaderCallback contient un avertissement.

mOpenCvCameraView.setOnTouchListener(MainActivity.this); met en garde sur

La vue personnalisée avec exemple/zcameratestv2/Version2CameraView a été appelée par setOnTouchListener mais ne remplace pas performClick

Contrairement à d'autres questions, ma classe étend une activité et non une vue. Par conséquent, lorsque j'essaie de remplacer la fonction private boolean performClick() { ...super.performClick(); }, elle n'est pas reconnue. Voici mes cours 

package com.example.zcameratestv2;

import Java.text.SimpleDateFormat;
import Java.util.Date;

import org.opencv.Android.BaseLoaderCallback;
import org.opencv.Android.OpenCVLoader;
import org.opencv.Android.CameraBridgeViewBase.CvCameraViewListener;
import org.opencv.Android.LoaderCallbackInterface;
import org.opencv.core.Mat;

import Android.annotation.SuppressLint;
import Android.app.Activity;
import Android.os.Bundle;
import Android.os.Environment;
import Android.util.Log;
import Android.view.Menu;
import Android.view.MenuItem;
import Android.view.MotionEvent;
import Android.view.SurfaceView;
import Android.view.View;
import Android.view.WindowManager;
import Android.view.View.OnTouchListener;
import Android.widget.Toast;

public class MainActivity extends Activity implements CvCameraViewListener, OnTouchListener {

private Version2CameraView mOpenCvCameraView;
private static final String TAG = "Version 2::Activity";

private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
    @Override
    public void onManagerConnected(int status) {
        switch (status) {
            case LoaderCallbackInterface.SUCCESS:
            {
                Log.i(TAG, "OpenCV loaded successfully");
                mOpenCvCameraView.enableView();
                mOpenCvCameraView.setOnTouchListener(MainActivity.this);
            } break;
            default:
            {
                super.onManagerConnected(status);
            } break;
        }
    }
};

public MainActivity() {
    Log.i(TAG, "Version 2 Class instantiated");
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

    setContentView(R.layout.activity_main);

    mOpenCvCameraView = (Version2CameraView) findViewById(R.id.Java_surface_view);

    mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);

    mOpenCvCameraView.setCvCameraViewListener(this);

}

public void onPause()
{
    super.onPause();
    if (mOpenCvCameraView != null)
        mOpenCvCameraView.disableView();
}

@Override
public void onResume()
{
    super.onResume();
    OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);
}

public void onDestroy() {
    super.onDestroy();
    if (mOpenCvCameraView != null)
        mOpenCvCameraView.disableView();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

@Override
public void onCameraViewStarted(int width, int height) {
    // TODO Auto-generated method stub

}

@Override
public void onCameraViewStopped() {
    // TODO Auto-generated method stub

}

@Override
public Mat onCameraFrame(Mat inputFrame) {
    // TODO Auto-generated method stub
    return null;
}

@SuppressLint("SimpleDateFormat")
@Override
public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        //some code....
        break;
    case MotionEvent.ACTION_UP:
        Log.i(TAG,"onTouch event");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
        String currentDateandTime = sdf.format(new Date());
        String fileName = Environment.getExternalStorageDirectory().getPath() +
                               "/sample_picture_" + currentDateandTime + ".jpg";
        mOpenCvCameraView.takePicture(fileName);
        Toast.makeText(this, fileName + " saved", Toast.LENGTH_SHORT).show();
        v.performClick();
        break;
    default:
        break;
    }
    return true;
 }


}

Auparavant, l'événement public boolean onTouch(View v, MotionEvent event) avait un avertissement similaire à celui de OnTouchListener. Il indique que je devrais utiliser un performClick (); méthode, mais je ne peux pas l’écarter car j’étends un Activity pas un View. Et j'ai découvert que l'application de v.PerformClick(); résout ce problème.

Cette autre classe gère les processus de la caméra 

package com.example.zcameratestv2;

import Java.io.FileOutputStream;

import org.opencv.Android.JavaCameraView;

import Android.content.Context;
import Android.hardware.Camera;
import Android.hardware.Camera.PictureCallback;
import Android.util.AttributeSet;
import Android.util.Log;

public class Version2CameraView extends JavaCameraView implements PictureCallback {

private static final String TAG = "Version2::CameraView";
private String mPictureFileName;

public Version2CameraView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public void takePicture(final String fileName) {
    Log.i(TAG, "Taking picture");
    this.mPictureFileName = fileName;
    // Postview and jpeg are sent in the same buffers if the queue is not empty when performing a capture.
    // Clear up buffers to avoid mCamera.takePicture to be stuck because of a memory issue
    mCamera.setPreviewCallback(null);

    // PictureCallback is implemented by the current class
    mCamera.takePicture(null, null, this);
}

@Override
public void onPictureTaken(byte[] data, Camera camera) {
    Log.i(TAG, "Saving a bitmap to file");
    // The camera preview was automatically stopped. Start it again.
    mCamera.startPreview();
    mCamera.setPreviewCallback(this);

    // Write the image in a file (in jpeg format)
    try {
        FileOutputStream fos = new FileOutputStream(mPictureFileName);

        fos.write(data);
        fos.close();

    } catch (Java.io.IOException e) {
        Log.e("PictureDemo", "Exception in photoCallback", e);
    }

}
}

J'ai inclus les autorisations requises dans le fichier manifeste, tel que CAMERA et WRITE_EXTERNAL_STORAGE

Quelqu'un peut-il déterminer le problème? Besoin de votre aide. Merci d'avance!

15
Sinned

La méthode onTouch() récupère chaque événement tactile de la vue sous-jacente qui n'a pas été marquée comme "traitée". Si votre Version2CameraView ne gère pas les événements tactiles, ils sont traités dans Activity et votre Version2CameraView est transmis en tant que paramètre View v

Malheureusement, votre JavaCameraView ne remplace pas performClick(), mais vous essayez de l'appeler dans cette vue. Solution? Ajoutez cette méthode à votre classe Version2CameraView:

@Override
public boolean performClick() {
    // do what you want
    return true;
}
6
skywall

Je pense que c'est un peu tard mais la solution est simple. Des classes telles que Button, TextView sont des sous-classes de View ainsi que SurfaceView qui est le parent des sous-classes JavaCameraView et Version2CameraView

Alors quelle est la différence? La différence est que TextView implémente une interface 'ViewTreeObserver.OnPreDrawListener'. Pour cette raison, Button (qui est la sous-classe de TextView) peut remplacer la méthode performClick().

Comment puis-je faire avec ma classe Version2CameraView? Il suffit d'implémenter une interface pour remplacer la méthode performClick(). Lequel 'ViewTreeObserver.OnPreDrawListener'? Non, vous devriez utiliser SurfaceHolder.Callback comme ceci:

public class Version2CameraView extends JavaCameraView implements PictureCallback, SurfaceHolder.Callback 
{
    ...
   /**
     * Process the MotionEvent.
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        synchronized (getHolder()) {
            // Do something
            ...
            return true;
        }
    }

    @Override
    public boolean performClick() {
        // Calls the super implementation, which generates an AccessibilityEvent
        // and calls the onClick() listener on the view, if any
        super.performClick();

        // Handle the action for the custom click here

        return true;
    }
    ...
}

Cette solution doit supprimer l'avertissement que vous avez.

0
Teocci

Vous devez ajouter une méthode pour gérer les événements tactiles car votre vue a appelé setOnTouchListener(), ajouter un remplacement de la méthode par défaut, assurez-vous d'appeler la super méthode à l'intérieur pour éviter des erreurs telles que "La méthode ne substitue pas la méthode à partir de sa super-classe". peut le laisser comme mon échantillon si vous n'allez pas traiter les événements tactiles qui s'y trouvent:

@Override
public boolean performClick() {
    super.performClick();
    return true;
}
0
pigstacho