Java 自定义视图调用了 setOnTouchListener 但不覆盖 performClick(类扩展 Activity NOT View)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32065086/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Custom view has setOnTouchListener called on it but does not override performClick (class extends Activity NOT View)
提问by Sinned
I have created an Android Activity implementing a bit of OpenCV. What it does is to simply create a Custom Camera View, and when the screen is touched, the photo will be saved.
我创建了一个 Android Activity 实现了一些 OpenCV。它所做的只是简单地创建一个自定义相机视图,当触摸屏幕时,照片将被保存。
My only problem is that the code mOpenCvCameraView.setOnTouchListener(MainActivity.this);
inside the BaseLoaderCallback contains a warning.
我唯一的问题是mOpenCvCameraView.setOnTouchListener(MainActivity.this);
BaseLoaderCallback 中的代码包含警告。
mOpenCvCameraView.setOnTouchListener(MainActivity.this);
warns about
mOpenCvCameraView.setOnTouchListener(MainActivity.this);
警告
Custom view com/example/zcameratestv2/Version2CameraView has setOnTouchListener called on it but does not override performClick
自定义视图 com/example/zcameratestv2/Version2CameraView 已调用 setOnTouchListener 但不会覆盖 performClick
Unlike other questions, my class extends an Activity not View, so when i try to override the function private boolean performClick() { ...super.performClick(); }
it is not recognized. Here are my classes
与其他问题不同,我的课程扩展了一个 Activity 而不是 View,因此当我尝试覆盖该函数时,private boolean performClick() { ...super.performClick(); }
它无法识别。这是我的课
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;
}
}
Previously the public boolean onTouch(View v, MotionEvent event)
event had a similar warning similar to the OnTouchListener, it displays that I should use a performClick(); method but I cant override it since I extend to an Activity
not a View
. And I have discovered that applying v.PerformClick();
fixes this.
以前该public boolean onTouch(View v, MotionEvent event)
事件有一个类似于 OnTouchListener 的类似警告,它显示我应该使用 performClick(); 方法,但我无法覆盖它,因为我扩展到了一个Activity
not a View
。我发现应用可以v.PerformClick();
解决这个问题。
This other class handles the camera processes
另一个类处理相机进程
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);
}
}
}
I have included the required permissions in the Manifest File such as the CAMERA and the WRITE_EXTERNAL_STORAGE
我已经在清单文件中包含了所需的权限,例如 CAMERA 和 WRITE_EXTERNAL_STORAGE
Can someone determine the problem? Need your help. Thanks in advance!
有人可以确定问题吗?需要你的帮助。提前致谢!
采纳答案by skywall
onTouch()
method gets every touch event from underlying view that hasn't been marked as "processed". If your Version2CameraView
doesn't handle touch events, they are processed in Activity and your Version2CameraView
is passed as View v
parameter.
onTouch()
方法从未标记为“已处理”的底层视图中获取每个触摸事件。如果您Version2CameraView
不处理触摸事件,它们将在 Activity 中处理,并且您Version2CameraView
的将作为View v
参数传递。
Unfortunately, your JavaCameraView
doesn't override performClick()
, but you're trying call it on this view. Solution? Add this method to your Version2CameraView
class:
不幸的是,您JavaCameraView
没有覆盖performClick()
,但您正在尝试在此视图上调用它。解决方案?将此方法添加到您的Version2CameraView
类中:
@Override
public boolean performClick() {
// do what you want
return true;
}
回答by pigstacho
You need to add a method to handle the touch events since your view has called setOnTouchListener()
, add an override of the default method, be sure to call the super method inside to avoid errors like "Method does not override method from its superclass", you can leave it like my sample if you are not going to process the touch events in there:
您需要添加一个方法来处理触摸事件,因为您的视图已调用setOnTouchListener()
,添加默认方法的覆盖,一定要调用内部的超级方法以避免“方法不会覆盖其超类中的方法”之类的错误,您可以如果您不打算在那里处理触摸事件,请像我的示例一样保留它:
@Override
public boolean performClick() {
super.performClick();
return true;
}
回答by Teocci
I think it is a little bit late but the solution is simple. Classes like Button
, TextView
are subclasses of View
as well as SurfaceView
which is the parent of JavaCameraView
and Version2CameraView
subclasses.
我认为现在有点晚了,但解决方案很简单。像Button
,TextView
是子类View
以及SurfaceView
which 是JavaCameraView
和Version2CameraView
子类的父类。
Then what is the difference?The difference is that TextView
implements a 'ViewTreeObserver.OnPreDrawListener' interface. For this reason, Button (which is subclass of TextView
) can override the performClick()
method.
那么有什么区别呢?不同之处在于TextView
实现了“ViewTreeObserver.OnPreDrawListener”接口。因此,Button(它是 的子类TextView
)可以覆盖该performClick()
方法。
How can I do with my Version2CameraView
class?Just implement an interface to override the performClick()
method. Which one, 'ViewTreeObserver.OnPreDrawListener'? Nope, you should use SurfaceHolder.Callback
like this:
我的Version2CameraView
班级怎么办?只需实现一个接口来覆盖该performClick()
方法。哪一个,'ViewTreeObserver.OnPreDrawListener'?不,你应该这样使用SurfaceHolder.Callback
:
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;
}
...
}
This solution must remove the warning that you have.
此解决方案必须删除您的警告。