簡體   English   中英

Android view.invalidate()的異常行為

[英]Strange behavior with Android view.invalidate()

我在LinearLayout中垂直放置了3個自定義視圖,它們用於顯示不同的動態信息,因此應該假定它們在不同的時間無效並重新繪制。 但是我發現視圖失效超出了通常的期望,即:如果使頂視圖失效,則所有3個視圖同時失效;如果使中間視圖失效,則中間視圖和底部視圖失效,前一個失效。不是,如果您使底視圖無效,那么只有底視圖本身無效,這就是我想要的,那么前兩種情況發生了什么? 我搜索了類似的問題:

https://stackoverflow.com/questions/26192491/invalidate-one-view-force-other-views-invalidate-too-how-separating-that

Android Invalidate()僅單個視圖

但似乎沒有確切答案。 我在這里發布我的代碼,任何評論表示贊賞。


package com.vrb.myview;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;


public class TestView extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    public void onTest(View view){
        MyView1 mv1 = (MyView1)findViewById(R.id.mv1);
        MyView1 mv2 = (MyView1)findViewById(R.id.mv2);
        MyView1 mv3 = (MyView1)findViewById(R.id.mv3);

        mv1.invalidate(); // all 3 views are invalidated
    //  mv2.invalidate(); // mv2 and mv3 are invalidated
    //  mv3.invalidate(); // only mv3 is invalidated,this is what I want
    }
}

package com.vrb.myview;

import java.util.Random;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

public class MyView1 extends View {
    Rect rc=null;
    Paint p=null;
    Random r;
    public MyView1(Context ctx){
        super(ctx);
        rc = new Rect();
        p = new Paint();
        r = new Random();
    }
    public MyView1(Context ctx, AttributeSet set){
        super(ctx, set);
        rc = new Rect();
        p = new Paint();
        r = new Random();
    }

    public void onDraw(Canvas canvas){
        if(canvas.getClipBounds(rc)){
            Log.d("MyView1","id="+getId()+" Rect: "+rc.left+","+rc.top+","+rc.right+","+rc.bottom);
            p.setColor(Color.argb(0xff, Math.abs(r.nextInt())%255, Math.abs(r.nextInt())%255, Math.abs(r.nextInt())%255));
            canvas.drawRect(rc, p);
        }else{
            Log.d("MyView1","id="+getId()+" Rect=null");        
        }       
    }
}

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/root"
    android:orientation="vertical"
    tools:context="com.vrb.myview.TestView" >

    <com.vrb.myview.MyView1
        android:layout_width="match_parent"
        android:layout_height="100px"
        android:id="@+id/mv1" />

    <com.vrb.myview.MyView1
        android:layout_width="match_parent"
        android:layout_height="100px"
        android:id="@+id/mv2" />

    <com.vrb.myview.MyView1
        android:layout_width="match_parent"
        android:layout_height="100px"
        android:id="@+id/mv3" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="Invalidate"
        android:onClick="onTest"
        android:id="@+id/btn" />

</LinearLayout>

您不應該依賴於onDraw()的計數或調用時間來獲取View的內部狀態。 p.setColor()調用移至單獨的公共方法,並在其末尾調用invalidate() 例如:

public class MyView1 extends View {
    ...
    public void changePaint() {
        p.setColor(Color.argb(0xff, Math.abs(r.nextInt()) % 255, Math.abs(r.nextInt()) % 255, Math.abs(r.nextInt()) % 255));
        invalidate();
    }
}

然后在您的onTest()方法中:

public void onTest(View view) {
    MyView1 mv1 = (MyView1)findViewById(R.id.mv1);
    ...
    mv1.changePaint();
    ...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM