对于ViewPager重写的onDraw有时会黑屏 [英] Overriding onDraw for ViewPager sometimes gives black screen

查看:289
本文介绍了对于ViewPager重写的onDraw有时会黑屏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我扩展ViewPager有一个移动背景(似乎是一个<一href=\"http://stackoverflow.com/questions/4775650/android-moving-background-image-while-navigating-through-views/14713965\">fairly流行要求太)

这似乎是主要的工作,我的问题是,有时整个背景变为黑色。

当活动屏幕旋转后重新启动,它恢复ViewPager相同的 -

当我旋转屏幕,而不是第一个另一个页面上,并开始移动(它仍然是屏幕旋转后确定),这实际上明确发生页面,因为它以前。

整个code与应用是 GitHub上,但这里是类的兴趣。

 包com.matthieu;进口android.annotation.Sup pressLint;
进口android.content.Context;
进口android.graphics *。
进口android.os.Build;
进口android.support.v4.view.ViewPager;
进口android.util.AttributeSet;
进口android.util.Log;进口java.io.IOException异常;
进口的java.io.InputStream;公共类ViewPagerParallax扩展ViewPager {
    INT background_id = -1;
    INT background_saved_id = -1;
    INT saved_width = -1,saved_height = -1,saved_max_num_pages = -1;
    位图saved_bitmap;    INT MAX_NUM_PAGES = 0;
    INT imageHeight;
    INT imageWidth;
    浮zoom_level;    矩形R =新的矩形();    私人最终静态字符串变量=ViewPagerParallax;    公共ViewPagerParallax(上下文的背景下){
        超级(上下文);
    }    公共ViewPagerParallax(上下文的背景下,ATTRS的AttributeSet){
        超(背景下,ATTRS);
    }    @燮pressLint({NewApi})
    私人无效set_new_background(){
        如果(background_id == -1)
            返回;        如果(MAX_NUM_PAGES == 0)
            返回;        如果(的getWidth()== 0 ||的getHeight()== 0)
            返回;        如果((saved_height ==的getHeight())及及(saved_width ==的getWidth())及&放大器;
                (background_saved_id == background_id)及&放大器;
                (saved_max_num_pages == MAX_NUM_PAGES))
            返回;        InputStream为;        尝试{
            是=的getContext()getResources()openRawResource(background_id)。            BitmapFactory.Options选项=新BitmapFactory.Options();
            options.inJustDe codeBounds = TRUE;
            BitmapFactory.de codeStream(是,空,期权);            imageHeight = options.outHeight;
            imageWidth = options.outWidth;            zoom_level =((浮点)imageHeight)/的getHeight(); //我们总是在fitY模式
            is.reset();            如果(Build.VERSION.SDK_INT&GT; = Build.VERSION_ codeS.GINGERBREAD_MR1){
                Bitma pregionDe codeR BRD = Bitma pregionDe coder.newInstance(是真的);                options.inJustDe codeBounds = FALSE;
                r.set(0,0,Math.min((int)的(的getWidth()*((MAX_NUM_PAGES + 4.0)/ 10)* zoom_level),imageWidth),imageHeight);
                saved_bitmap = brd.de codeRegion(R,期权);
                brd.recycle();
            }其他{
                saved_bitmap = Bitmap.createBitmap(BitmapFactory.de codeStream(是),0,0,Math.min((INT)(的getWidth()*((MAX_NUM_PAGES + 4.0)/ 10)* zoom_level),imageWidth),imageHeight );
            }            is.close();
        }赶上(IOException异常五){
            Log.e(TAG,不能去code:+ e.getMessage());
            background_id = -1;
            返回;
        }        saved_height =的getHeight();
        saved_width =的getWidth();
        background_saved_id = background_id;
        saved_max_num_pages = MAX_NUM_PAGES;
    }    INT CURRENT_POSITION;
    浮current_offset;    @覆盖
    保护无效onPageScrolled(INT位置,浮抵消,诠释offsetPixels){
        super.onPageScrolled(位置,偏移,offsetPixels);
        CURRENT_POSITION =位置;
        current_offset =偏移;
    }    矩形SRC =新的矩形(),DST =新的矩形();    @覆盖
    保护无效的onDraw(帆布油画){
        super.onDraw(画布);        src.set((int)的(((CURRENT_POSITION + current_offset)*的getWidth()* zoom_level)/ 5),0,
                (中间体)((((CURRENT_POSITION + current_offset)*的getWidth()* zoom_level)/ 5)+(的getWidth()* zoom_level)),imageHeight);        dst.set((int)的((CURRENT_POSITION + current_offset)*的getWidth()),0,(int)的((CURRENT_POSITION + current_offset)*的getWidth())+ canvas.getWidth(),canvas.getHeight());
        //仍然困惑,为什么我们还需要在目标画布转移        canvas.drawBitmap(saved_bitmap,SRC,DST,NULL);
    }    公共无效set_max_pages(INT num_max_pages){
        MAX_NUM_PAGES = num_max_pages;
        set_new_background();
    }    公共无效setBackgroundAsset(INT RES_ID){
        background_id = RES_ID;
        set_new_background();
    }    @覆盖
    保护无效onLayout(布尔变化,诠释L,INT T,INT R,INT B){
        super.onLayout(改,L,T,R,B);
        set_new_background();
    }
}


解决方案

在基于第一页上计算了帆布偏移正在绘制...固定在$ C $ GitHub上的合作,现在只是希望这是不是东西,完全依赖于实现,后来改变...

I extended ViewPager to have a moving background (seems to be a fairly popular request too)

It seems to be mostly working, the problem I have is that sometimes the whole background turns black.

This actually specifically occurs when I rotate the screen while on another page than the first one and start moving (it is still ok after the screen rotation) - when the activity restarts after the screen rotation, it restores the ViewPager to the same page as it was before.

The whole code with application is on GitHub, but here is the class of interest.

package com.matthieu;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.*;
import android.os.Build;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;

import java.io.IOException;
import java.io.InputStream;

public class ViewPagerParallax extends ViewPager {
    int background_id =-1;
    int background_saved_id =-1;
    int saved_width=-1, saved_height=-1, saved_max_num_pages =-1;
    Bitmap saved_bitmap;

    int max_num_pages=0;
    int imageHeight;
    int imageWidth;
    float zoom_level;

    Rect r = new Rect();

    private final static String TAG="ViewPagerParallax";

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

    public ViewPagerParallax(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @SuppressLint({"NewApi"})
    private void set_new_background() {
        if (background_id == -1)
            return;

        if (max_num_pages == 0)
            return;

        if (getWidth()==0 || getHeight()==0)
            return;

        if ((saved_height == getHeight()) && (saved_width == getWidth()) &&
                (background_saved_id==background_id) &&
                (saved_max_num_pages == max_num_pages))
            return;

        InputStream is;

        try {
            is = getContext().getResources().openRawResource(background_id);

            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(is, null, options);

            imageHeight = options.outHeight;
            imageWidth = options.outWidth;

            zoom_level = ((float) imageHeight) / getHeight();  // we are always in 'fitY' mode
            is.reset();

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD_MR1) {
                BitmapRegionDecoder brd = BitmapRegionDecoder.newInstance(is, true);

                options.inJustDecodeBounds = false;
                r.set(0, 0, Math.min((int) (getWidth() * ((max_num_pages + 4.0) / 5) * zoom_level), imageWidth), imageHeight);
                saved_bitmap = brd.decodeRegion(r, options);
                brd.recycle();
            } else {
                saved_bitmap = Bitmap.createBitmap(BitmapFactory.decodeStream(is), 0, 0, Math.min((int) (getWidth() * ((max_num_pages + 4.0) / 5) * zoom_level), imageWidth), imageHeight);
            }

            is.close();
        } catch (IOException e) {
            Log.e(TAG, "Cannot decode: " + e.getMessage());
            background_id = -1;
            return;
        }

        saved_height = getHeight();
        saved_width = getWidth();
        background_saved_id = background_id;
        saved_max_num_pages = max_num_pages;
    }

    int current_position;
    float current_offset;

    @Override
    protected void onPageScrolled(int position, float offset, int offsetPixels) {
        super.onPageScrolled(position, offset, offsetPixels);
        current_position = position;
        current_offset = offset;
    }

    Rect src = new Rect(), dst = new Rect();

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        src.set((int) (((current_position + current_offset) * getWidth() * zoom_level) / 5 ), 0,
                (int) ((((current_position + current_offset) * getWidth() * zoom_level) / 5)  + (getWidth() * zoom_level)), imageHeight);

        dst.set((int) ((current_position + current_offset) * getWidth()), 0, (int) ((current_position + current_offset) * getWidth()) + canvas.getWidth(), canvas.getHeight());
        // still confused why we need to shift also in the destination canvas

        canvas.drawBitmap(saved_bitmap, src, dst, null);
    }

    public void set_max_pages(int num_max_pages) {
        max_num_pages = num_max_pages;
        set_new_background();
    }

    public void setBackgroundAsset(int res_id) {
        background_id = res_id;
        set_new_background();
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        set_new_background();
    }
}

解决方案

The offset in the Canvas is calculated based on the first page being drawn... fixed the code o GitHub, now just hoping this is not something that is completely implementation dependent that would change later...

这篇关于对于ViewPager重写的onDraw有时会黑屏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆