Android - 从 onTouchEvent() 访问成员变量
Android - Accessing member variable from onTouchEvent()
首先我要明确的是,我看到了很多关于类似问题的问题,但没有人针对我的具体情况,所以我不得不问我自己的问题。
我正在尝试创建一个应用程序,在用户触摸视图时收集笔画。我创建了一个 class 名为 WritingView 的扩展视图。在此 class 中,我重写了 onTouchEvent() 方法来绘制笔划并将坐标收集到名为 currentStroke 的 ArrayList 中。它一直有效,直到我尝试访问包含 MainActivity 中坐标的数组的内容,当我单击一个按钮时,它始终为空。
这里是WritingView的代码class,我都给了以防万一,但我认为问题出在onTouchEvent上,剩下的就是绘制收集canvas和笔画了屏幕,有效:
public class WritingView extends View{
private Canvas drawCanvas;
private Bitmap bitmapCanvas;
private Path inkPath;
private Paint ink, inkCanvas;
private Context context;
private ArrayList<Float> currentStroke;
public WritingView(Context c) {
super(c);
init(c);
}
public WritingView(Context c, AttributeSet attrs) {
super(c, attrs);
init(c);
}
public WritingView(Context c, AttributeSet attrs, int defStyleAttr) {
super(c, attrs, defStyleAttr);
init(c);
}
public void init(Context c) {
this.inkPath = new Path();
this.ink = new Paint();
this.context = c;
this.currentStroke = new ArrayList<Float>();
// Get the screen size
WindowManager wm = (WindowManager) this.context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
// Set ink parameters
ink.setColor(0xFF660000);
ink.setAntiAlias(true);
ink.setStrokeWidth(15);
ink.setStyle(Paint.Style.STROKE);
ink.setStrokeJoin(Paint.Join.ROUND);
ink.setStrokeCap(Paint.Cap.ROUND);
this.inkCanvas = new Paint(Paint.DITHER_FLAG);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
this.bitmapCanvas = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
this.drawCanvas = new Canvas(bitmapCanvas);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmapCanvas, 0, 0, inkCanvas);
canvas.drawPath(inkPath, ink);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getX();
float touchY = event.getY();
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
inkPath.moveTo(touchX, touchY);
Log.d(TAG, "onTouchEvent: ACTION_DOWN_EVENT - X=" + touchX + ", Y=" + touchY );
break;
case MotionEvent.ACTION_MOVE:
inkPath.lineTo(touchX, touchY);
this.currentStroke.add(touchX);
this.currentStroke.add(touchY);
Log.d(TAG, "onTouchEvent: ACTION_MOVE_EVENT - X=" + touchX + ", Y=" + touchY );
break;
case MotionEvent.ACTION_UP:
drawCanvas.drawPath(inkPath, ink);
Log.d(TAG, "onTouchEvent: ACTION_UP_EVENT - X=" + touchX + ", Y=" + touchY );
inkPath.reset();
break;
default:
return false;
}
invalidate();
return true;
}
public ArrayList<Float> getCurrentStroke() {
Log.d(TAG, "getCurrentStroke: size : " + this.currentStroke.size());
return this.currentStroke;
}
}
以及 MainActivity 的代码:
public class MainActivity extends AppCompatActivity {
static final int RECO_REQUEST = 0;
private WritingView writingView;
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
writingView = new WritingView(this);
setContentView(R.layout.activity_main);
final Button button = (Button) findViewById(R.id.recognizeButton);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
startReco();
}
});
}
public void startReco() {
ArrayList<Float> coords = writingView.getCurrentStroke();
Log.d(TAG, "onClick: size : " + coords.size());
for(int i = 0; i < coords.size(); i++) {
Log.d(TAG, "onClick: " + i + " : " + coords.get(i));
}
}
}
正如我所说,当我尝试从 MainActivity 访问它时,数组似乎是空的,但我知道(我测试过)坐标是在 onTouchEvent 方法中放入它的。
感谢您的帮助。
此外,这里是 xml 文件,用于显示 activity 的显示,以及如何在其上添加 WritingView :
<TextView
android:id="@+id/textResult"
android:layout_width="578dp"
android:layout_height="146dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:text="Results :"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/recognizeButton"
android:text="Start recognition"
android:layout_width="300dp"
android:layout_height="80dp"
app:layout_constraintTop_toBottomOf="@+id/textResult"
app:layout_constraintBottom_toTopOf="@+id/writingView" />
<com.myscript.testapplication.WritingView
android:id="@+id/writingView"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:layout_weight="1"
android:background="#E3EAE7"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/recognizeButton"/>
您似乎有 2 个 WritingView。首先你的布局文件中有一个,你还在 Activity.
中创建一个新的
试试这个:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
writingView = (WritingView)findViewById(R.id.writingView);
....
}
或者,您可以从布局文件中删除 WritingView,然后使用 addView() 将其添加到主 activity。
首先我要明确的是,我看到了很多关于类似问题的问题,但没有人针对我的具体情况,所以我不得不问我自己的问题。
我正在尝试创建一个应用程序,在用户触摸视图时收集笔画。我创建了一个 class 名为 WritingView 的扩展视图。在此 class 中,我重写了 onTouchEvent() 方法来绘制笔划并将坐标收集到名为 currentStroke 的 ArrayList 中。它一直有效,直到我尝试访问包含 MainActivity 中坐标的数组的内容,当我单击一个按钮时,它始终为空。
这里是WritingView的代码class,我都给了以防万一,但我认为问题出在onTouchEvent上,剩下的就是绘制收集canvas和笔画了屏幕,有效:
public class WritingView extends View{
private Canvas drawCanvas;
private Bitmap bitmapCanvas;
private Path inkPath;
private Paint ink, inkCanvas;
private Context context;
private ArrayList<Float> currentStroke;
public WritingView(Context c) {
super(c);
init(c);
}
public WritingView(Context c, AttributeSet attrs) {
super(c, attrs);
init(c);
}
public WritingView(Context c, AttributeSet attrs, int defStyleAttr) {
super(c, attrs, defStyleAttr);
init(c);
}
public void init(Context c) {
this.inkPath = new Path();
this.ink = new Paint();
this.context = c;
this.currentStroke = new ArrayList<Float>();
// Get the screen size
WindowManager wm = (WindowManager) this.context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
// Set ink parameters
ink.setColor(0xFF660000);
ink.setAntiAlias(true);
ink.setStrokeWidth(15);
ink.setStyle(Paint.Style.STROKE);
ink.setStrokeJoin(Paint.Join.ROUND);
ink.setStrokeCap(Paint.Cap.ROUND);
this.inkCanvas = new Paint(Paint.DITHER_FLAG);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
this.bitmapCanvas = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
this.drawCanvas = new Canvas(bitmapCanvas);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmapCanvas, 0, 0, inkCanvas);
canvas.drawPath(inkPath, ink);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getX();
float touchY = event.getY();
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
inkPath.moveTo(touchX, touchY);
Log.d(TAG, "onTouchEvent: ACTION_DOWN_EVENT - X=" + touchX + ", Y=" + touchY );
break;
case MotionEvent.ACTION_MOVE:
inkPath.lineTo(touchX, touchY);
this.currentStroke.add(touchX);
this.currentStroke.add(touchY);
Log.d(TAG, "onTouchEvent: ACTION_MOVE_EVENT - X=" + touchX + ", Y=" + touchY );
break;
case MotionEvent.ACTION_UP:
drawCanvas.drawPath(inkPath, ink);
Log.d(TAG, "onTouchEvent: ACTION_UP_EVENT - X=" + touchX + ", Y=" + touchY );
inkPath.reset();
break;
default:
return false;
}
invalidate();
return true;
}
public ArrayList<Float> getCurrentStroke() {
Log.d(TAG, "getCurrentStroke: size : " + this.currentStroke.size());
return this.currentStroke;
}
}
以及 MainActivity 的代码:
public class MainActivity extends AppCompatActivity {
static final int RECO_REQUEST = 0;
private WritingView writingView;
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
writingView = new WritingView(this);
setContentView(R.layout.activity_main);
final Button button = (Button) findViewById(R.id.recognizeButton);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
startReco();
}
});
}
public void startReco() {
ArrayList<Float> coords = writingView.getCurrentStroke();
Log.d(TAG, "onClick: size : " + coords.size());
for(int i = 0; i < coords.size(); i++) {
Log.d(TAG, "onClick: " + i + " : " + coords.get(i));
}
}
}
正如我所说,当我尝试从 MainActivity 访问它时,数组似乎是空的,但我知道(我测试过)坐标是在 onTouchEvent 方法中放入它的。
感谢您的帮助。
此外,这里是 xml 文件,用于显示 activity 的显示,以及如何在其上添加 WritingView :
<TextView
android:id="@+id/textResult"
android:layout_width="578dp"
android:layout_height="146dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:text="Results :"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/recognizeButton"
android:text="Start recognition"
android:layout_width="300dp"
android:layout_height="80dp"
app:layout_constraintTop_toBottomOf="@+id/textResult"
app:layout_constraintBottom_toTopOf="@+id/writingView" />
<com.myscript.testapplication.WritingView
android:id="@+id/writingView"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:layout_weight="1"
android:background="#E3EAE7"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/recognizeButton"/>
您似乎有 2 个 WritingView。首先你的布局文件中有一个,你还在 Activity.
中创建一个新的试试这个:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
writingView = (WritingView)findViewById(R.id.writingView);
....
}
或者,您可以从布局文件中删除 WritingView,然后使用 addView() 将其添加到主 activity。