【问题标题】:Android - invalidate() doesn't call my onDraw in CustomViewAndroid - invalidate() 不会在 CustomView 中调用我的 onDraw
【发布时间】:2019-08-07 06:57:47
【问题描述】:

我有一个 content_main.xml:

<LinearLayout
    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"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".MainActivity"
    tools:showIn="@layout/activity_main">

    <com.example.CustomView
        android:id="@+id/customView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout >

在 MainActivity.java 中,在 onCreate 中我调用了 CustomView:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);
    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    customView = new CustomView(this, attributeSet);
    customView.init();
}

在 CustomView 中,我有一个 onDraw:

@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
    canvas.drawColor(Color.BLUE);
    drawValidMoves(canvas, squareSize);
}

在MainActivity中,onTouch

@Override
public boolean onTouchEvent(MotionEvent event) {
    if(event.getAction() == MotionEvent.ACTION_DOWN) {
        int x = (int)event.getX();
        int y = (int)event.getY();

        String text = customView.isTouched(x, y, customView.getSquareSize());
        Toast.makeText(this, text, Toast.LENGTH_LONG).show();
    }
    return super.onTouchEvent(event);
}

正在从 CustomView.java 调用一个方法 - isTouched 改变了绘制元素矩阵中的一些东西,然后,我正在做一些:

  setWillNotDraw(false);
  invalidate();

但我的游戏没有再次到达 onDraw... 如果我直接在 CustomView 中调用 onCreate,则无效:

customView = new CustomView(this, attributeSet);
customView.init();
setContentView(customView);

但我没有工具栏了,我需要它

稍后编辑:

content_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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:id="@+id/linearLayoutId"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".MainActivity"
    tools:showIn="@layout/activity_main">

    <com.example.clotz.CustomView
        android:id="@+id/customView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout >

MainActivity.java - onCreate - 我将数据从 init 方法移动到构造函数并摆脱 init。

public class MainActivity extends AppCompatActivity {

    CustomView customView;

    @SuppressLint("WrongViewCast")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        customView = findViewById(R.id.customView);
    }

但现在 onTouchEvent 中的 customView 为空:

@Override
public boolean onTouchEvent(MotionEvent event) {
    if(event.getAction() == MotionEvent.ACTION_DOWN) {
        int x = (int)event.getX();
        int y = (int)event.getY();

        String text = customView.isTouched(x, y, customView.getSquareSize());
        Toast.makeText(this, text, Toast.LENGTH_LONG).show();
    }
    return super.onTouchEvent(event);
}

【问题讨论】:

  • 将您的自定义 View 放入您的布局中,给它一个 ID,然后使用 findViewById() 像任何其他常规 View - stackoverflow.com/q/10410616 一样获取它。
  • setSupportActionBar() 调用后的所有内容替换为customView = findViewById(R.id.customView);。哦,除了customView.init(); 电话,我的意思是。你可能仍然想要那个。
  • 如果 findViewById() 返回 null,那么您上面显示的布局可能没有被加载。你确定你在activity_main 中还有一个&lt;include&gt; 用于content_main 吗?您是否可能有多个res/layout*/ 版本——例如,纵向和横向各一个——而其中一个版本没有您的&lt;CustomView&gt; 元素?另外,在您的CustomView 类中,在public CustomView(Context context, AttributeSet attrs) 构造函数中,您确定在super 调用中传递了attrs
  • 是的,问题出在 public CustomView(Context context, AttributeSet attributeSet) { 我有 super(context);现在可以了,非常感谢!!!
  • 哦,我很好。 :-) 只是一些常见问题。没什么大不了的。请随时自行发布答案,概述您为使事情顺利进行所做的工作。并且不要忘记在几天后接受它,当系统允许您时,这样这个问题就会显示为已回答。不过,谢谢。我很感激这个提议。真高兴你做到了。干杯!

标签: android


【解决方案1】:

@Mike M 帮我解决了这个问题,我在 content_main.xml 中放入了 linearLayout 的 id:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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:id="@+id/linearLayoutId"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".MainActivity"
    tools:showIn="@layout/activity_main">

    <com.example.clotz.CustomView
        android:id="@+id/customView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout >

在 MainActivity.java - onCreate(我将数据从 init 方法移动到构造函数并摆脱了 init)并使用 findViewById(R.id.customView) 创建了 customview;

public class MainActivity extends AppCompatActivity {

    CustomView customView;

    @SuppressLint("WrongViewCast")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        customView = findViewById(R.id.customView);
    }

问题出在CustomView.java中,我忘记将attributeSet传递给超类:

public CustomView(Context context, AttributeSet attributeSet) {
    super(context);

    initializeMovedMatrix();
    setInitialPositionForPieces();
    // create the Paint to set its color
    paint = new Paint();
    piecesMoves = new PiecesMoves(this);
}

把它,结合customView = findViewById(R.id.customView);

super(context, attributeSet);

解决了这个问题。 再次感谢 MikeM!

【讨论】:

    【解决方案2】:

    你不能在 onDraw 方法中删除super.onDraw(canvas)

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.BLUE);
        drawValidMoves(canvas, squareSize);
    }
    

    【讨论】:

    • 这不是真的,与当前问题无关。
    • 你是 "content_main.xml" 中的自定义视图 ID 吗?你的 MainActivity 内容是“setContentView(R.layout.activity_main)”。
    • 感谢 akiki,MikeM 的回答帮助我解决了这个问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-16
    • 1970-01-01
    • 1970-01-01
    • 2020-03-07
    相关资源
    最近更新 更多