关闭

在5.0系统上头像展示背景黑块的问题

标签: android移动
1338人阅读 评论(1) 收藏 举报
分类:

最近是比较懒了,时间是有,代码也不想碰了,开源项目也分析了几个, 断断续续的也没完成,哎。闲话少说了。


在开发过程中,遇到在Android5.0系统及以上的系统上,头像会有黑块的问题,就是在圆形头像的后面有个矩形的黑块,

通常的一些解决方法就是改为非硬加速等等,都试过了,没有效果。最后使用了RecyclingImageView解决了此问题,

具体原因没仔细查看, 应该是图片缓存的问题,没有及时释放。

这个demo源码可以在Android给的samples中找到,在AS中,可以直接导入这个demo。前提是得连外网,一般需要翻墙。

下面是关键代码:

/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.android.displayingbitmaps.ui;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.util.AttributeSet;
import android.widget.ImageView;

import com.example.android.displayingbitmaps.util.RecyclingBitmapDrawable;

/**
 * Sub-class of ImageView which automatically notifies the drawable when it is
 * being displayed.
 */
public class RecyclingImageView extends ImageView {

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

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

    /**
     * @see android.widget.ImageView#onDetachedFromWindow()
     */
    @Override
    protected void onDetachedFromWindow() {
        // This has been detached from Window, so clear the drawable
        setImageDrawable(null);

        super.onDetachedFromWindow();
    }

    /**
     * @see android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)
     */
    @Override
    public void setImageDrawable(Drawable drawable) {
        // Keep hold of previous Drawable
        final Drawable previousDrawable = getDrawable();

        // Call super to set new Drawable
        super.setImageDrawable(drawable);

        // Notify new Drawable that it is being displayed
        notifyDrawable(drawable, true);

        // Notify old Drawable so it is no longer being displayed
        notifyDrawable(previousDrawable, false);
    }

    /**
     * Notifies the drawable that it's displayed state has changed.
     *
     * @param drawable
     * @param isDisplayed
     */
    private static void notifyDrawable(Drawable drawable, final boolean isDisplayed) {
        if (drawable instanceof RecyclingBitmapDrawable) {
            // The drawable is a CountingBitmapDrawable, so notify it
            ((RecyclingBitmapDrawable) drawable).setIsDisplayed(isDisplayed);
        } else if (drawable instanceof LayerDrawable) {
            // The drawable is a LayerDrawable, so recurse on each layer
            LayerDrawable layerDrawable = (LayerDrawable) drawable;
            for (int i = 0, z = layerDrawable.getNumberOfLayers(); i < z; i++) {
                notifyDrawable(layerDrawable.getDrawable(i), isDisplayed);
            }
        }
    }

}

/**
 * A BitmapDrawable that keeps track of whether it is being displayed or cached.
 * When the drawable is no longer being displayed or cached,
 * {@link android.graphics.Bitmap#recycle() recycle()} will be called on this drawable's bitmap.
 */
public class RecyclingBitmapDrawable extends BitmapDrawable {

    static final String TAG = "CountingBitmapDrawable";

    private int mCacheRefCount = 0;
    private int mDisplayRefCount = 0;

    private boolean mHasBeenDisplayed;

    public RecyclingBitmapDrawable(Resources res, Bitmap bitmap) {
        super(res, bitmap);
    }

    /**
     * Notify the drawable that the displayed state has changed. Internally a
     * count is kept so that the drawable knows when it is no longer being
     * displayed.
     *
     * @param isDisplayed - Whether the drawable is being displayed or not
     */
    public void setIsDisplayed(boolean isDisplayed) {
        //BEGIN_INCLUDE(set_is_displayed)
        synchronized (this) {
            if (isDisplayed) {
                mDisplayRefCount++;
                mHasBeenDisplayed = true;
            } else {
                mDisplayRefCount--;
            }
        }

        // Check to see if recycle() can be called
        checkState();
        //END_INCLUDE(set_is_displayed)
    }

    /**
     * Notify the drawable that the cache state has changed. Internally a count
     * is kept so that the drawable knows when it is no longer being cached.
     *
     * @param isCached - Whether the drawable is being cached or not
     */
    public void setIsCached(boolean isCached) {
        //BEGIN_INCLUDE(set_is_cached)
        synchronized (this) {
            if (isCached) {
                mCacheRefCount++;
            } else {
                mCacheRefCount--;
            }
        }

        // Check to see if recycle() can be called
        checkState();
        //END_INCLUDE(set_is_cached)
    }

    private synchronized void checkState() {
        //BEGIN_INCLUDE(check_state)
        // If the drawable cache and display ref counts = 0, and this drawable
        // has been displayed, then recycle
        if (mCacheRefCount <= 0 && mDisplayRefCount <= 0 && mHasBeenDisplayed
                && hasValidBitmap()) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "No longer being used or cached so recycling. "
                        + toString());
            }

            getBitmap().recycle();
        }
        //END_INCLUDE(check_state)
    }

    private synchronized boolean hasValidBitmap() {
        Bitmap bitmap = getBitmap();
        return bitmap != null && !bitmap.isRecycled();
    }

}

主要是对图片进行了及时的释放处理,希望对遇到此问题的人有帮助。额。 忘记说了,用的话,自己的头像处理View,继承它就行了, 只需要做处理下就行了。


0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

5.0及以上系统上使用CircleImageView圆形头像出现方块背景问题(上一个Activity中的页面)

问题:5.0及以上系统上使用CircleImageView圆形头像出现背景(上一个Activity中的页面) 解决办法:在全局配置文件中开启硬件加速
  • Pillar1066527881
  • Pillar1066527881
  • 2015-12-24 18:09
  • 1931

WAPG4 解决透明导航栏返回黑块

不做gif了,虽然我会做^ ^,具体情况你遇到了就知道我说的是什么,没遇到这篇文章对你也没有价值。 具体来说就是,我APP中根视图导航栏是透明的,二级页面导航栏是不透明的,在页面切换的时候会看到黑块,...
  • MIRAGE086
  • MIRAGE086
  • 2016-02-02 17:34
  • 1351

Word里面设置标题编号后显示为黑块?

在word中新建了几个样式,设置了几个标题的编号形式,比如(1)等,保存文档时一切正常。同时提示是否保存Normal.dotm,我点击了“是”。 再次打开这个文档后,发现之前设置的编号形式全部显...
  • Kinger0
  • Kinger0
  • 2015-11-23 21:31
  • 1771

【android】把view保存为图片的方法以及解决保存后图片背景变黑色的问题

上代码: public class MainActivity extends Activity { ImageView imgView; @Override protected void on...
  • u011494050
  • u011494050
  • 2014-08-23 11:14
  • 6340

5.0及以上系统上使用CircleImageView圆形头像出现方块背景问题(上一个Activity中的页面)

问题:5.0及以上系统上使用CircleImageView圆形头像出现背景(上一个Activity中的页面) 解决办法:在全局配置文件中开启硬件加速
  • Pillar1066527881
  • Pillar1066527881
  • 2015-12-24 18:09
  • 1931

解决Android程序启动出现黑色闪现的问题。

问题:Activity启动中onCreate耗时过多引起黑屏闪现一下(1-3s),用户体验非常不好! 我们都知道android程序启动的过程为Application→MainActivity→界面完...
  • goodxianping
  • goodxianping
  • 2015-03-08 16:13
  • 1385

解决软键盘隐藏时,短暂出现黑块的情况

解决软键盘隐藏时,短暂出现黑块的情况在做项目的时候,一个界面的Edittext比较多,出现了在隐藏输入法软键盘的时候短暂的黑色区块,由于这个界面布局比较复杂,刚开始以为是因为界面复杂的原因造成卡顿现象...
  • a987687115
  • a987687115
  • 2016-11-08 11:25
  • 1087

1602显示一排黑

今天在做频率计时候出现的问题。由于之前已经做出一块可以实现正常功能的板子,再做一块就没怎么注意细节。毕竟原理很简单,而且电路模块也不多。而出现的问题就是1602显示上面一排黑。这样的情况之前也有出现过...
  • u011303443
  • u011303443
  • 2016-06-08 00:13
  • 776

快速解决光标由竖线变黑块

快速解决光标由竖线变黑块   编程时偶尔会突然出现光标突然间由“小竖线”变成“黑块矩形”,网上有说在控制面板中进行设置。由于光标是在使用中突然发生变化,推测是碰到了快捷键,因此断定有快...
  • haiross
  • haiross
  • 2016-04-18 13:23
  • 2302

android自定义控件画布canvas背景色失效变黑色

错误示范: *********************************************************************************************...
  • seashine_yan
  • seashine_yan
  • 2017-04-13 10:10
  • 2504
    个人资料
    • 访问:201399次
    • 积分:2274
    • 等级:
    • 排名:第19082名
    • 原创:39篇
    • 转载:0篇
    • 译文:0篇
    • 评论:122条
    Android开发交流群
    323876830
    博客专栏