android - 部分重绘 -> 无效(矩形 矩形)

标签 android performance android-layout

在我的 onDraw 中,我拥有构建整个 View 所需的所有代码,但如何检测我是否只想执行部分重绘。 我想应该通过调用 canvas.invalidate(Rect rect); 来触发部分重绘。 正确的? 在我设备的开发人员设置中,我启用了“显示屏幕更新”,但这总是告诉我,我的整个屏幕已重绘......

下面您可以看到我的应用程序的屏幕截图:

Screenshot of app

如您所见,它是一个日历,我想在单击条目时向用户提供视觉反馈(假设周围有红色边框)...

我已经看过一些示例,但它们要么使用位图,要么使用大量成员变量来执行在 onDraw 中重绘特定区域所需的代码...

谁能告诉我实现此类功能的最佳方法是什么?

更新:

在我的第一次绘制中 Canvas.getClipBounds() 返回以下矩形:

Rect(0, 0 - 1200, 1800)

当我调用 invalidate(new Rect(304, 748 - 529, 902)) 并在 onDraw() 中再次检查 getClipBounds() 时> 它仍然具有相同的值。

更新2(我的代码):

@Override
public boolean onTouch(View v, MotionEvent event) {

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN: {
        _pTouchDown = new PointF(event.getX(), event.getY());

        downX = event.getX();
        downY = event.getY();

        entrySelected = hasTimeRecordAt(downX, downY);
        if (entrySelected != null) {
            Rect rInvalidate = new Rect((int) entrySelected.get_Selected().left, (int) entrySelected.get_Selected().top, (int) entrySelected.get_Selected().right,
                    (int) entrySelected.get_Selected().bottom);

            invalidate(rInvalidate);


        } 

        return false;
    }

更新3(我的布局):

<android.support.v4.widget.DrawerLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MultiDayCalendarActivity" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="vertical" >

        <RelativeLayout
            android:id="@+id/rlStatusline"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >

            <TextView
                android:id="@+id/tvStatusline1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:text="asdf" >
            </TextView>

            <TextView
                android:id="@+id/tvStatusline2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:text="1234" >
            </TextView>
        </RelativeLayout>

        <com.mxp.time.calendar.DayHeader
                android:id="@+id/dayHeader"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                 />

        <ScrollView
            android:id="@+id/m_svMultiRoot1"
            android:layout_width="match_parent"
            android:layout_height="0dip"
            android:layout_weight="1" >

            <com.mxp.time.calendar.Calendar
                android:id="@+id/calendar"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                 />
        </ScrollView>

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="1dp"
            android:background="@color/brushBackgroundLight" >
        </LinearLayout>

        <RelativeLayout
            android:id="@+id/rlMenu"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true" >

                <ImageButton
                    android:id="@+id/ibtCreateNewTimeRecord"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/menu" />

                <ImageButton
                    android:id="@+id/ibtCalendarStopwatch"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/stopwatch" />
            </LinearLayout>

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:orientation="horizontal" >

                <ImageButton
                    android:id="@+id/ibtCalendarBack"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/previous" />

                <ImageButton
                    android:id="@+id/ibtCalendarForward"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/next" />
            </LinearLayout>

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true" >

                <ImageButton
                    android:id="@+id/ibtCalendarToday"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/today" />

                <ImageButton
                    android:id="@+id/ibtGotoJobs"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/jobs" />
            </LinearLayout>
        </RelativeLayout>
    </LinearLayout>

    <FrameLayout
        android:id="@+id/drawer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start" >
    </FrameLayout>

</android.support.v4.widget.DrawerLayout>

更新4:

setContentView(R.layout.test_calendar);
        // _cal = (Calendar) findViewById(R.id.calendar);
        _cal = new Calendar(this);

        _dayHeader = (DayHeader) findViewById(R.id.dayHeader);

        final ScrollView sv = (ScrollView) findViewById(R.id.m_svMultiRoot1);
        sv.addView(_cal);

相同的结果:

我在 onTouch 中传递 Rect(172, 748 - 265, 902) ,在 onDraw 中得到 Rect(0, 0 - 720, 1800)

更新5:

package com.example.testclip;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

class V extends View {

private static final String TAG = "null";
Rect clip = new Rect();

public V(Context context) {
    super(context);
    int[] colors = { 0xff000000, 0xffff0000, 0xffffffff };
    Drawable d = new android.graphics.drawable.GradientDrawable(android.graphics.drawable.GradientDrawable.Orientation.TOP_BOTTOM, colors);
    setBackgroundDrawable(d);
}

@Override
public boolean onTouchEvent(MotionEvent event) {

    int x = (int) event.getX();
    int y = (int) event.getY();
    StringBuilder sb = new StringBuilder();

    sb.append("left: ");
    sb.append(x);
    sb.append(", top: ");
    sb.append(y);

    sb.append("right: ");
    sb.append(x + 10);
    sb.append(", bottom: ");
    sb.append(y + 10);

    Log.d(TAG, "onTouchEvent  clip rect: " + sb.toString());

    invalidate(x, y, x + 10, y + 10);

    return false;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int w = MeasureSpec.getSize(widthMeasureSpec);
    setMeasuredDimension(w, w * 4);
}

@Override
protected void onDraw(Canvas canvas) {
    canvas.getClipBounds(clip);
    StringBuilder sb = new StringBuilder();

    sb.append("left: ");
    sb.append(clip.left);
    sb.append(", top: ");
    sb.append(clip.top);

    sb.append("right: ");
    sb.append(clip.right);
    sb.append(", bottom: ");
    sb.append(clip.bottom);

    Log.d(TAG, "onDraw  clip rect: " + sb.toString());
}
}

Activity :

package com.example.testclip;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.ScrollView;

public class TestClipMainActivity extends Activity {

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

     ScrollView sv = new ScrollView(this);
        V v = new V(this);
        sv.addView(v);
        setContentView(sv);
}

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

}

此代码产生以下输出

02-15 10:47:54.011: D/OpenGLRenderer(833): 启用 Debug模式 0 02-15 10:47:54.926:D/dalvikvm(833):threadid = 1:撤消后仍挂起(sc = 1 dc = 1) 02-15 10:48:03.806:D/null(833):onDraw剪辑矩形:左:0,上:0右:720,下:2880 02-15 10:48:05.381:D/null(833):onDraw剪辑矩形:左:0,上:0右:720,下:2880 02-15 10:48:07.181:D/null(833):onTouchEvent剪辑矩形:左:409,顶部:358右:419,底部:368 02-15 10:48:09.806: D/null(833): onDraw 剪辑矩形:左:0,上:0右:720,下:2880

最佳答案

您一定做错了什么,请参阅此自定义 View :

class V extends View {

    Rect clip = new Rect();
    private int cnt = 20;

    public V(Context context) {
        super(context);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        cnt++;
        Log.d(TAG, "calling invalidate " + cnt);
        invalidate(10, 10, cnt, cnt);
        return false;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.getClipBounds(clip);
        Log.d(TAG, "onDraw clip " + clip);
    }
}

更新:ScrollView 内的自定义 View :

class V extends View {

    Rect clip = new Rect();

    public V(Context context) {
        super(context);
        int[] colors = {0xff000000, 0xffff0000, 0xffffffff};
        Drawable d = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors);
        setBackgroundDrawable(d);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();
        invalidate(x, y, x + 10, y + 10);
        return true;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int w = MeasureSpec.getSize(widthMeasureSpec);
        setMeasuredDimension(w, w * 4);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.getClipBounds(clip);
        Log.d(TAG, "onDraw clip height: " + clip.height());
    }
}

将其添加到 onCreate:

    ScrollView sv = new ScrollView(this);
    V v = new V(this);
    sv.addView(v);
    setContentView(sv);

关于android - 部分重绘 -> 无效(矩形 矩形),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21706208/

相关文章:

c# - C++ 与 C# 相比,计算速度提高了 15 倍,这是合法的吗?

android - 如何在通货膨胀期间从另一个控件中引用一个控件?

java - 在 fragment 上膨胀图像按钮

android localytics 4.5.1 崩溃 NoClassDefFoundError com.localytics.android.BackgroundService

android - fitSystemWindows 仅适用于选项卡的一个 fragment

android - 像硬件后退按钮一样启用操作栏后退按钮

java - 来自音频文件的 Android 基本 TTS 引擎

performance - Haskell 的严格折叠真的使用线性空间吗?

java - 在 if isDebugEnabled() : a good policy? 中包含对 debug() 的调用

android - 在水平 RecyclerView 中显示 ImageView 会在 Android 中的图像周围(?)放置较大的边距