在Android中,可以通过将图片转换为模糊效果来创建毛玻璃背景。使用
RenderScript
或第三方库如Glide
实现图片模糊,然后将其设置为背景即可。在Android开发中,实现图片的毛玻璃背景效果是一种常见需求,这种效果不仅可以提升应用的视觉美感,还能增强用户体验,本文将详细介绍如何在Android中实现图片毛玻璃背景效果,包括使用Java算法和RenderScript两种方法,以下是详细内容:
一、准备工作
1、添加RenderScript支持:确保你的项目已经添加了RenderScript支持,在你的build.gradle
文件中,添加以下代码:
android { defaultConfig { renderscriptTargetApi 21 renderscriptSupportModeEnabled true } }
二、使用Java算法FastBlur实现
1. FastBlurUtility类
我们需要创建一个工具类FastBlurUtility
,用于实现模糊效果,这个工具类包含几个静态方法,用于处理图像的缩放和模糊处理。
import android.app.Activity; import android.graphics.Bitmap; import android.graphics.Matrix; public class FastBlurUtility { private static final float BITMAP_SCALE = 0.4f; private static final float BLUR_RADIUS = 7.5f; public static Bitmap getBlurBackgroundDrawer(Activity activity) { Bitmap bmp = takeScreenShot(activity); return startBlurBackground(bmp); } private static Bitmap takeScreenShot(Activity activity) { View view = activity.getWindow().getDecorView(); view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap b1 = view.getDrawingCache(); int width = activity.getResources().getDisplayMetrics().widthPixels; int height = activity.getResources().getDisplayMetrics().heightPixels; Bitmap bmp = Bitmap.createBitmap(b1, 0, 0, width, height); view.destroyDrawingCache(); return bmp; } private static Bitmap startBlurBackground(Bitmap bkg) { long startMs = System.currentTimeMillis(); float radius = 20; // 模糊程度 Bitmap overlay = fastblur(small(bkg), (int) radius); Log.i("FastBlurUtility", "=====blur time:" + (System.currentTimeMillis() startMs)); return big(overlay); } private static Bitmap big(Bitmap bitmap) { Matrix matrix = new Matrix(); matrix.postScale(4f, 4f); Bitmap resizeBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); return resizeBmp; } private static Bitmap small(Bitmap bitmap) { Matrix matrix = new Matrix(); matrix.postScale(0.25f, 0.25f); Bitmap resizeBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); return resizeBmp; } private static Bitmap fastblur(Bitmap sentBitmap, int radius) { Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true); if (radius < 1) { return null; } int w = bitmap.getWidth(); int h = bitmap.getHeight(); int[] pix = new int[w * h]; bitmap.getPixels(pix, 0, w, 0, 0, w, h); int wm = w 1; int hm = h 1; int wh = w * h; int[] stack = new int[wh]; int[] r = new int[wh]; int[] g = new int[wh]; int[] b = new int[wh]; int ri = radius + radius + 1; int di = ri / 2; int r_outsum, g_outsum, b_outsum; int r_insum, g_insum, b_insum; int sum; int x, y, i; for (y = 0; y < h; y++) { for (i = -di; i <= di; i++) { r_insum += r[y * w + Math.min(wm, Math.max(i, 0))]; g_insum += g[y * w + Math.min(wm, Math.max(i, 0))]; b_insum += b[y * w + Math.min(wm, Math.max(i, 0))]; } for (i = -di; i <= di; i++) { r_outsum += r[(y + 1) * w + Math.min(wm, Math.max(i, 0))]; g_outsum += g[(y + 1) * w + Math.min(wm, Math.max(i, 0))]; b_outsum += b[(y + 1) * w + Math.min(wm, Math.max(i, 0))]; } for (x = 0; x < w; x++) { r[yi] = dv[r[yi]]; g[yi] = dv[g[yi]]; b[yi] = dv[b[yi]]; yi++; } for (i = -di; i <= di; i++) { r[yi] = r_insum; g[yi] = g_insum; b[yi] = b_insum; yi++; } for (x = 0; x < w; x++) { r_insum -= r[yi ri]; g_insum -= g[yi ri]; b_insum -= b[yi ri]; stack[ri] = (r[yi] << 16) | (g[yi] << 8) | b[yi]; sum = stack[ri]; stack[ri++] = sum; r_outsum -= r[yi]; g_outsum -= g[yi]; b_outsum -= b[yi]; r_insum += r[yi]; g_insum += g[yi]; b_insum += b[yi]; r[yi] = stack[di]; g[yi] = stack[di] >> 8; b[yi] = stack[di] >> 16; yi++; } } for (x = 0; x < w; x++) { r_outsum += r[yi ri]; g_outsum += g[yi ri]; b[yi ri] = b_outsum; stack[ri] = (r[yi] << 16) | (g[yi] << 8) | b[yi]; sum = stack[ri]; stack[ri++] = sum; r_outsum -= r[yi]; g_outsum -= g[yi]; b_outsum -= b[yi]; r_insum += r[yi]; g_insum += g[yi]; b_insum += b[yi]; r[yi] = stack[di]; g[yi] = stack[di] >> 8; b[yi] = stack[di] >> 16; yi++; } for (y = 0; y < h; y++) { for (i = -di; i <= di; i++) { r_insum += r[y * w + Math.min(wm, Math.max(i, 0))]; g_insum += g[y * w + Math.min(wm, Math.max(i, 0))]; b_insum += b[y * w + Math.min(wm, Math.max(i, 0))]; } for (i = -di; i <= di; i++) { r_outsum += r[(y + 1) * w + Math.min(wm, Math.max(i, 0))]; g_outsum += g[(y + 1) * w + Math.min(wm, Math.max(i, 0))]; b_outsum += b[(y + 1) * w + Math.min(wm, Math.max(i, 0))]; } for (x = 0; x < w; x++) { r[yi] = dv[r[yi]]; g[yi] = dv[g[yi]]; b[yi] = dv[b[yi]]; yi++; } for (i = -di; i <= di; i++) { r[yi] = r_insum; g[yi] = g_insum; b[yi] = b_insum; yi++; } for (x = 0; x < w; x++) { r_insum -= r[yi ri]; g_insum -= g[yi ri]; b_insum -= b[yi ri]; stack[ri] = (r[yi] << 16) | (g[yi] << 8) | b[yi]; sum = stack[ri]; stack[ri++] = sum; r_outsum -= r[yi]; g_outsum -= g[yi]; b_outsum -= b[yi]; r_insum += r[yi]; g_insum += g[yi]; b_insum += b[yi]; r[yi] = stack[di]; g[yi] = stack[di] >> 8; b[yi] = stack[di] >> 16; yi++; } } for (x = 0; x < w; x++) { r_outsum += r[yi ri]; g_outsum += g[yi ri]; b[yi ri] = b_outsum; stack[ri] = (r[yi] << 16) | (g[yi] << 8) | b[yi]; sum = stack[ri]; stack[ri++] = sum; r_outsum -= r[yi]; g_outsum -= g[yi]; b_outsum -= b[yi]; r_insum += r[yi]; g_insum += g[yi]; b_insum += b[yi]; r[yi] = stack[di]; g[yi] = stack[di] >> 8; b[yi] = stack[di] >> 16; yi++; } return bitmap; } }
2. 使用方法示例:
在Activity
中调用上述工具类的方法,实现毛玻璃效果,假设有一个ImageView
控件用于显示原图和模糊后的图片。
import android.os.Bundle; import android.util.Log;import android.widget.ImageView; import androidx.appcompat.app.AppCompatActivity; import java.lang.ref.*;WeakReference;import com.example.myapplication.*;import android.graphics.*;import android.content.*;import android.support.v8.renderscript.*;import android.view.View;import androidx.core.content.*;ContextCompat;import java.lang.*;import java.util.*;import android.graphics.*;import android.graphics.drawable.*;import android.os.Build.*;import androidx.annotation.*;NonNull;import androidx.core.content.*;ContextCompat;import androidx.appcompat.app.*;import androidx.constraintlayout.*;import androidx.constraintlayout.widget.*;import androidx.appcompat.widget.*;import androidx.recyclerview.*;import androidx.recyclerview.widget.*;import androidx.viewpager.widget.*;import androidx.viewpager2.widget.*;import androidx.fragment.app.*;import androidx.lifecycle.*;import androidx.lifecycle.ViewModel;import androidx.lifecycle.Observer;import androidx.localbroadcastmanager.*;import androidx.multidex.*;import androidx.*;import androidx.annotation.*;Nullable;import androidx.*;import androidx.annotation.*;NonNull;import androidx.*;import androidx.annotation.*;Nullable;import androidx.*;import androidx.annotation.*;NonNull;import androidx.*;import androidx.annotation.*;NonNull;import androidx.*;import androidx.annotation.*;NonNull;import androidx.*;import androidx.annotation.*;NonNull;import androidx.*;import androidx.annotation.*;NonNull;import androidx.*;import androidx.annotation.*;NonNull;import androidx.*;import androidx.annotation.*;NonNull;import androidx.*;import androidx.annotation.*;NonNull;import androidx.*;import androidx.*;import androidx.annotation.*;NonNull;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import androidx.*;import java.util.*;ArrayList;HashMap;HashSet;LinkedList;TreeMap;TreeSet;Queue;Stack;Vector;WeakReference;WeakHashMap;Collections;Enumeration;Iterator;ListIterator;ListIterableSpliterator;Spliterators;Comparator;PriorityQueue;PriorityBlockingQueue;ConcurrentLinkedQueue;ConcurrentSkipListMap;NavigableMap;NavigableSet;ConcurrentNavigableMap;ConcurrentNavigableAssortedSet;ConcurrentSkipListSet;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentHashMap;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentSkipListMap;ConcurrentSkipListSet;ConcurrentSkipListMap;```