【问题标题】:CircularImageView and API 16: NullPointerException errorCircularImageView 和 API 16:NullPointerException 错误
【发布时间】:2016-04-14 04:57:11
【问题描述】:

我在不同的 API 上测试我的应用程序,它似乎在 API 17 到 23 上工作,但我发现在 API 16 中,我无法加载我的自定义视图。我只想在一个圆圈中显示一张照片,我已经从这个线程中获得了 customview 的代码:How to create a circular ImageView in Android?

我的代码贴在这里:

public class CircularImageView extends ImageView {

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

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

    public CircularImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onDraw(Canvas canvas) {

        Drawable drawable = getDrawable();

        int w = getWidth();

        if (drawable == null) {
            return;
        }

        if (getWidth() == 0 || getHeight() == 0) {
            return;
        }
        Bitmap b = ((BitmapDrawable) drawable).getBitmap();

        Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);

        Bitmap roundBitmap = getCroppedBitmap(bitmap, w);
        canvas.drawBitmap(roundBitmap, 0, 0, null);

    }

    public static Bitmap getCroppedBitmap(Bitmap bmp, int radius) {
        Bitmap sbmp;

        if (bmp.getWidth() != radius || bmp.getHeight() != radius) {
            float smallest = Math.min(bmp.getWidth(), bmp.getHeight());
            float factor = smallest / radius;
            sbmp = Bitmap.createScaledBitmap(bmp, (int) (bmp.getWidth() / factor), (int) (bmp.getHeight() / factor), false);
        } else {
            sbmp = bmp;
        }

        Bitmap output = Bitmap.createBitmap(radius, radius,
                Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, radius, radius);

        paint.setAntiAlias(true);
        paint.setFilterBitmap(true);
        paint.setDither(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(Color.parseColor("#BAB399"));
        canvas.drawCircle(radius / 2 + 0.7f,
                radius / 2 + 0.7f, radius / 2 + 0.1f, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(sbmp, rect, rect, paint);

        return output;
    }
}

错误出现在这一行:

    if (bmp.getWidth() != radius || bmp.getHeight() != radius) 

这是日志猫:

01-09 15:09:51.185 2119-2119/? E/AndroidRuntime: 致命异常: main java.lang.NullPointerException 在 com.example.simon.customshapes.CircularImageView.getCroppedBitmap(CircularImageView.java:59) 在 com.example.simon.customshapes.CircularImageView.onDraw(CircularImageView.java:51) 在 android.view.View.draw(View.java:13458) 在 android.view.View.getDisplayList(View.java:12409) 在 android.view.View.getDisplayList(View.java:12453) 在 android.view.View.draw(View.java:13182) 在 android.view.ViewGroup.drawChild(ViewGroup.java:2929) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:2799) 在 android.view.View.draw(View.java:13461) 在 android.view.View.getDisplayList(View.java:12409) 在 android.view.View.getDisplayList(View.java:12453) 在 android.view.View.draw(View.java:13182) 在 android.view.ViewGroup.drawChild(ViewGroup.java:2929) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:2799) 在 android.view.View.getDisplayList(View.java:12407) 在 android.view.View.getDisplayList(View.java:12453) 在 android.view.View.draw(View.java:13182) 在 android.view.ViewGroup.drawChild(ViewGroup.java:2929) 在 android.support.v7.widget.RecyclerView.drawChild(RecyclerView.java:3588) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:2799) 在 android.view.View.draw(View.java:13461) 在 android.support.v7.widget.RecyclerView.draw(RecyclerView.java:3097) 在 android.view.View.getDisplayList(View.java:12409) 在 android.view.View.getDisplayList(View.java:12453) 在 android.view.View.draw(View.java:13182) 在 android.view.ViewGroup.drawChild(ViewGroup.java:2929) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:2806) 在 android.view.View.draw(View.java:13461) 在 android.view.View.getDisplayList(View.java:12409) 在 android.view.View.getDisplayList(View.java:12453) 在 android.view.View.draw(View.java:13182) 在 android.view.ViewGroup.drawChild(ViewGroup.java:2929) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:2799) 在 android.view.View.getDisplayList(View.java:12407) 在 android.view.View.getDisplayList(View.java:12453) 在 android.view.View.draw(View.java:13182) 在 android.view.ViewGroup.drawChild(ViewGroup.java:2929) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:2799) 在 android.view.View.draw(View.java:13461) 在 android.support.v4.view.ViewPager.draw(ViewPager.java:2262) 在 android.view.View.getDisplayList(View.java:12409) 在 android.view.View.getDisplayList(View.java:12453) 在 android.view.View.draw(View.java:13182) 在 android.view.ViewGroup.drawChild(ViewGroup.java:2929) 在 android.support.design.widget.CoordinatorLayout.drawChild(CoordinatorLayout.java:1077) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:2799) 在 android.view.View.getDisplayList(View.java:12407) 在 android.view.View.getDisplayList(View.java:12453) 在 android.view.View.draw(View.java:13182) 在 android.view.ViewGroup.drawChild(ViewGroup.java:2929) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:2799) 在 android.view.View.getDisplayList(View.java:12407) 在 android.view.View.getDisplayList(View.java:12453) 在 android.view.View.draw(View.java:13182) 在 android.view.ViewGroup.drawChild(ViewGroup.java:2929) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:2799) 在 android.view.View.getDisplayList(View.java:12407) 在 android.view.View.getDisplayList(View.java:12453) 在 android.view.View.draw(View.java:13182) 在 android.view.ViewGroup.drawChild(ViewGroup.java:2929) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:2799) 在 android.view.View.draw(View.java:13461) 在 android.widget.FrameLayout.draw(FrameLayout.java:467) 在 android.view.View.getDisplayList(View.java:12409) 在 android.view.View.getDisplayList(View.java:12453) 在 android.view.View.draw(View.java:13182) 在 android.view.ViewGroup.drawChild(ViewGroup.java:2929) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:2799) 在 android.view.View.getDisplayList(View.java:12407) 在 android.view.View.getDisplayList(View.java:12453) 在 android.view.View.draw(View.java:13182) 在 android.view.ViewGroup.drawChild(ViewGroup.java:2929) 在一个

我无法在 Android API 16 中绘制圆形图像视图有什么原因吗?

【问题讨论】:

标签: android nullpointerexception imageview


【解决方案1】:

好吧,因为您的位图为空,并且可绘制对象不是错误可能出现的唯一位置,而是在 copy(Bitmap, boolean) 内。

如果您查看文档

如果不支持转换,或者分配器失败,则返回 NULL。

尝试使用较小的图像,因为这可能表示内存不足。您还应该添加一些防范可能返回的空值,例如在这种情况下只绘制普通位图。

【讨论】:

  • 我正在加载的位图非常小。没有什么大于 100kb,大多数都小于 50kb。
  • 从我看到的错误来自该行。它仍然可能是位图转换失败,但我不知道为什么:/
【解决方案2】:

您可以将 MLRoundedImageView 用于圆形图像视图。 MLRoundedImageView.java

public class MLRoundedImageView extends ImageView {

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

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

public MLRoundedImageView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

@Override
protected void onDraw(Canvas canvas) {

    Drawable drawable = getDrawable();

    if (drawable == null) {
        return;
    }

    if (getWidth() == 0 || getHeight() == 0) {
        return;
    }
    Bitmap b = ((BitmapDrawable) drawable).getBitmap();
    Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);

    int w = getWidth(), h = getHeight();

    Bitmap roundBitmap = getCroppedBitmap(bitmap, w);
    canvas.drawBitmap(roundBitmap, 0, 0, null);

}

public static Bitmap getCroppedBitmap(Bitmap bmp, int radius) {
    Bitmap sbmp;

    if (bmp.getWidth() != radius || bmp.getHeight() != radius) {
        float smallest = Math.min(bmp.getWidth(), bmp.getHeight());
        float factor = smallest / radius;
        sbmp = Bitmap.createScaledBitmap(bmp, (int)(bmp.getWidth() / factor), (int)(bmp.getHeight() / factor), false);
    } else {
        sbmp = bmp;
    }

    Bitmap output = Bitmap.createBitmap(radius, radius,
            Config.ARGB_8888);
    Canvas canvas = new Canvas(output);

    final int color = 0xffa19774;
    final Paint paint = new Paint();
    final Rect rect = new Rect(0, 0, radius, radius);

    paint.setAntiAlias(true);
    paint.setFilterBitmap(true);
    paint.setDither(true);
    canvas.drawARGB(0, 0, 0, 0);
    paint.setColor(Color.parseColor("#BAB399"));
    canvas.drawCircle(radius / 2 + 0.7f,
            radius / 2 + 0.7f, radius / 2 + 0.1f, paint);
    paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
    canvas.drawBitmap(sbmp, rect, rect, paint);

    return output;
}
}

然后在布局中这样使用

   <com.yourproject.MLRoundedImagView
  Layout properties here />

然后在你的活动中

MLRoundedImagView imageview = (MLRoundedImagView) findViewbyId(R.id.imageview);

【讨论】:

  • 抱歉 - 不知道这如何回答我的问题,因为您班级中的代码与我班级中的代码相同。我可以创建圆圈 - 我只是无法在 API 16 中创建圆圈。
【解决方案3】:

使用此方法将您的可绘制对象转换为位图:

public static Bitmap drawableToBitmap (Drawable drawable) {
    Bitmap bitmap = null;

    if (drawable instanceof BitmapDrawable) {
        BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
        if(bitmapDrawable.getBitmap() != null) {
            return bitmapDrawable.getBitmap();
        }
    }

    if(drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
        bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
    } else {
        bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
    }

    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);
    return bitmap;
}

然后在原始代码中使用以下行:

Bitmap b = ((BitmapDrawable) drawable).getBitmap();

改用这个:

Bitmap b = drawableToBitmap(drawable);

然后就可以正常运行了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-23
    • 2017-03-30
    • 1970-01-01
    • 2018-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多