[Android] 通过Menu实现图片怀旧、浮雕、模糊、光照和素描效果
生活随笔
收集整理的這篇文章主要介紹了
[Android] 通过Menu实现图片怀旧、浮雕、模糊、光照和素描效果
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
? ? 由于隨手拍項目想做成類似于美圖秀秀那種底部有一排Menu實現不同效果的功能,這里先簡單介紹如何通過Menu實現打開相冊中的圖片、懷舊效果、浮雕效果、光照效果和素描效果.后面可能會講述如何通過PopupWindow實現自定義的Menu效果.
? ? 希望文章對大家有所幫助,如果有錯誤或不足之處請海涵~
一. Menu效果展示
? ?Android手機上有個Menu按鍵,點擊他會彈出一個菜單,通常在屏幕底部或右上角,在選項菜單OptionsMenu中最多顯示2排每排3個菜單項,可以包含自定義的圖片和文字.如果Menu菜單項多于6項時,第6項(Expanded Menus,擴展菜單)會變成More,點擊它會顯示后面所隱藏的所有選項.? ? 下面講述如何在Android 4.0項目中實現簡單的Menu功能.添加如下代碼: @Override public boolean onCreateOptionsMenu(Menu menu) { //創建Menu//自定義menu 添加圖標(使用自帶圖標)menu.add(Menu.NONE, Menu.FIRST + 1 , 1, "打開").setIcon(android.R.drawable.ic_menu_slideshow);menu.add(Menu.NONE, Menu.FIRST + 2 , 2, "懷舊").setIcon(android.R.drawable.ic_menu_edit);menu.add(Menu.NONE, Menu.FIRST + 3 , 3, "浮雕").setIcon(android.R.drawable.ic_menu_gallery);menu.add(Menu.NONE, Menu.FIRST + 4 , 4, "模糊").setIcon(android.R.drawable.ic_menu_crop);menu.add(Menu.NONE, Menu.FIRST + 5 , 5, "光照").setIcon(android.R.drawable.ic_menu_camera);menu.add(Menu.NONE, Menu.FIRST + 6 , 6, "銳化").setIcon(android.R.drawable.ic_menu_view);return true; } ? ?由于Android 4.0系統缺省UI風格有所變化,所以需要設置Activity的theme為Theme.Light.同時也可以在res/menu/main.xml設置菜單項.參考"愷風"博主關于Menu的介紹,非常不錯.http://blog.csdn.net/flowingflying/article/details/11967301 <activityandroid:name="com.example.menushowimage.MainActivity"android:label="@string/app_name" android:theme="@android:style/Theme.Light" > ? ?下圖是設置前面的顯示Menu不同效果,同時我調用的圖標都是Android自帶的圖片,用戶也可以自定義.(android默認圖標列表)
? ? ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ??
? ? 同時設置XML格式顯示圖片: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/container"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.example.touchimagetest.MainActivity"tools:ignore="MergeRootFrame" ><!-- 頂部添加文字 --><RelativeLayoutandroid:id="@+id/Layout_top"android:orientation="horizontal" android:layout_width="fill_parent"android:layout_height="25dp"android:layout_alignParentTop="true"android:gravity="center"><TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20sp" android:text="請點擊menu處理圖片" /> </RelativeLayout><!-- 底部顯示圖片 --><RelativeLayoutandroid:id="@+id/Layout_bottom" android:orientation="horizontal"android:layout_below="@id/Layout_top" android:layout_width="fill_parent" android:layout_height="wrap_content"android:background="#EFDFDF"android:gravity="center"><ImageViewandroid:id="@+id/imageView1"android:layout_width="fill_parent"android:layout_height="fill_parent"android:layout_gravity="center_horizontal" /></RelativeLayout> </RelativeLayout>
二. Menu實現打開圖片
? ?然后通過onOptionsItemSelected(MenuItem item)實現選擇圖片,通過調用自定義函數實現各種功能. @Override public boolean onOptionsItemSelected(MenuItem item) { //選擇Menu//選擇id 對應Menu.add的參數Menu.FIRST+iint id = item.getItemId();switch(id) {case Menu.FIRST+1: Toast.makeText(this, "打開圖片", Toast.LENGTH_SHORT).show();OpenImage();break;case Menu.FIRST+2: Toast.makeText(this, "圖片懷舊效果", Toast.LENGTH_SHORT).show();OldRemeberImage();break;case Menu.FIRST+3: Toast.makeText(this, "圖片浮雕效果", Toast.LENGTH_SHORT).show();ReliefImage();break;case Menu.FIRST+4: Toast.makeText(this, "圖片模糊效果", Toast.LENGTH_SHORT).show();FuzzyImage();break;case Menu.FIRST+5: Toast.makeText(this, "圖片光照效果", Toast.LENGTH_SHORT).show();SunshineImage();break;case Menu.FIRST+6: Toast.makeText(this, "圖片銳化效果", Toast.LENGTH_SHORT).show();SharpenImage();break;}return super.onOptionsItemSelected(item); } ? ?其中打開圖片函數實現方法如下,而上面的很多自定義函數都將在第三部分介紹,你此處可以注釋掉只驗證"打開圖片".首先添加自定義變量和獲取ImageView布局. //自定義變量 private ImageView imageShow; //顯示圖片 private Bitmap bmp; //原始圖片 private final int IMAGE_OPEN = 0; //打開圖片 @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);imageShow = (ImageView) findViewById(R.id.imageView1); if (savedInstanceState == null) {getFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();} } ? ? 然后通過自定義函數OpenImage打開函數,與前面文章介紹的方法一樣. //自定義函數 打開圖片 public void OpenImage() {Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(intent, IMAGE_OPEN); } //顯示打開圖片 protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(resultCode==RESULT_OK && requestCode==IMAGE_OPEN) { Uri imageFileUri = data.getData(); DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); int width = dm.widthPixels; //手機屏幕水平分辨率 int height = dm.heightPixels; //手機屏幕垂直分辨率 try { //載入圖片尺寸大小沒載入圖片本身 true BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options(); bmpFactoryOptions.inJustDecodeBounds = true; bmp = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageFileUri), null, bmpFactoryOptions); int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)height); int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)width); //inSampleSize表示圖片占原圖比例 1表示原圖 if(heightRatio>1&&widthRatio>1) { if(heightRatio>widthRatio) { bmpFactoryOptions.inSampleSize = heightRatio; } else { bmpFactoryOptions.inSampleSize = widthRatio; } } //圖像真正解碼 false bmpFactoryOptions.inJustDecodeBounds = false; bmp = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageFileUri), null, bmpFactoryOptions); imageShow.setImageBitmap(bmp); } catch(FileNotFoundException e) { e.printStackTrace(); } } //end if } ? ? 下面講講使用Options Menu的函數:? ?onCreateOptionsMenu(Menu menu)創建options menu,這個函數只會在menu第一次顯示時調用.
? ? onOptionsItemSelected(MenuItem item)處理選中的菜單項.
? ? 在通過menu.add函數實現添加菜單項,如menu.add(Menu.NONE,Menu.FIRST+1,1,"打開"),第一個參數表示組別;第二個參數menu標志編號與onOptionsItemSelected函數中值對應;第三個參數是在菜單中出現的順序,順序由小到大,由左至右;第四個參數是顯示的文字,同時setIcon可以設置圖標.
三. 圖像各種效果實現
? ? 最后講講各個效果實現過程,通過不同自定義函數實現.其中各個效果主要參照《Android圖像處理總結》那篇文章和eoeAndroid社區亞瑟的文章.??? 書籍下載地址:
1.圖片懷舊效果 //圖片懷舊處理 private void OldRemeberImage() {/** 懷舊處理算法即設置新的RGB* R=0.393r+0.769g+0.189b* G=0.349r+0.686g+0.168b* B=0.272r+0.534g+0.131b*/int width = bmp.getWidth();int height = bmp.getHeight();Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);int pixColor = 0;int pixR = 0;int pixG = 0;int pixB = 0;int newR = 0;int newG = 0;int newB = 0;int[] pixels = new int[width * height];bmp.getPixels(pixels, 0, width, 0, 0, width, height);for (int i = 0; i < height; i++){for (int k = 0; k < width; k++){pixColor = pixels[width * i + k];pixR = Color.red(pixColor);pixG = Color.green(pixColor);pixB = Color.blue(pixColor);newR = (int) (0.393 * pixR + 0.769 * pixG + 0.189 * pixB);newG = (int) (0.349 * pixR + 0.686 * pixG + 0.168 * pixB);newB = (int) (0.272 * pixR + 0.534 * pixG + 0.131 * pixB);int newColor = Color.argb(255, newR > 255 ? 255 : newR, newG > 255 ? 255 : newG, newB > 255 ? 255 : newB);pixels[width * i + k] = newColor;}}bitmap.setPixels(pixels, 0, width, 0, 0, width, height);imageShow.setImageBitmap(bitmap); } ??? 顯示效果如下圖所示:
? ? ? ? ? ? ?? ? ? ?? 2.圖片浮雕效果 //圖片浮雕處理 //底片效果也非常簡單:將當前像素點的RGB值分別與255之差后的值作為當前點的RGB //灰度圖像:通常使用的方法是gray=0.3*pixR+0.59*pixG+0.11*pixB private void ReliefImage() {/** 算法原理:(前一個像素點RGB-當前像素點RGB+127)作為當前像素點RGB值* 在ABC中計算B點浮雕效果(RGB值在0~255)* B.r = C.r - B.r + 127* B.g = C.g - B.g + 127* B.b = C.b - B.b + 127*/int width = bmp.getWidth();int height = bmp.getHeight();Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);int pixColor = 0;int pixR = 0;int pixG = 0;int pixB = 0;int newR = 0;int newG = 0;int newB = 0;int[] pixels = new int[width * height];bmp.getPixels(pixels, 0, width, 0, 0, width, height);for (int i = 1; i < height-1; i++){for (int k = 1; k < width-1; k++){//獲取前一個像素顏色pixColor = pixels[width * i + k]; pixR = Color.red(pixColor);pixG = Color.green(pixColor);pixB = Color.blue(pixColor);//獲取當前像素pixColor = pixels[(width * i + k) + 1];newR = Color.red(pixColor) - pixR +127;newG = Color.green(pixColor) - pixG +127;newB = Color.blue(pixColor) - pixB +127;newR = Math.min(255, Math.max(0, newR));newG = Math.min(255, Math.max(0, newG));newB = Math.min(255, Math.max(0, newB));pixels[width * i + k] = Color.argb(255, newR, newG, newB);}}bitmap.setPixels(pixels, 0, width, 0, 0, width, height);imageShow.setImageBitmap(bitmap); } ???顯示效果如下圖所示:
?? 3.圖像模糊效果 //圖像模糊處理 private void FuzzyImage() {/** 算法原理:* 簡單算法將像素周圍八個點包括自身共九個點RGB值分別相加后平均,當前像素點的RGB值* 復雜算法采用高斯模糊* 高斯矩陣 int[] gauss = new int[] { 1, 2, 1, 2, 4, 2, 1, 2, 1 };* 將九個點的RGB值分別與高斯矩陣中的對應項相乘的和,再除以一個相應的值作為當前像素點的RGB*/int[] gauss = new int[] { 1, 2, 1, 2, 4, 2, 1, 2, 1 }; // 高斯矩陣int delta = 16; // 除以值 值越小圖片會越亮,越大則越暗int width = bmp.getWidth();int height = bmp.getHeight();Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);int pixColor = 0;int pixR = 0; int pixG = 0; int pixB = 0; int newR, newG, newB;int pos = 0; //位置int[] pixels = new int[width * height]; bmp.getPixels(pixels, 0, width, 0, 0, width, height); //循環賦值for (int i = 1; i < height-1; i++){for (int k = 1; k < width-1; k++){pos = 0;newR = 0; newG = 0; newB = 0; for (int m = -1; m <= 1; m++) //寬不變{ for (int n = -1; n <= 1; n++) //高先變{ pixColor = pixels[(i + m) * width + k + n]; pixR = Color.red(pixColor); pixG = Color.green(pixColor); pixB = Color.blue(pixColor); //3*3像素相加newR = newR + (int) (pixR * gauss[pos]); newG = newG + (int) (pixG * gauss[pos]); newB = newB + (int) (pixB * gauss[pos]); pos++; } } newR /= delta; newG /= delta; newB /= delta; newR = Math.min(255, Math.max(0, newR)); newG = Math.min(255, Math.max(0, newG)); newB = Math.min(255, Math.max(0, newB)); pixels[i * width + k] = Color.argb(255, newR, newG, newB); }}bitmap.setPixels(pixels, 0, width, 0, 0, width, height);imageShow.setImageBitmap(bitmap); } ??? 該圖顯示效果不是很理想,對高斯模糊理解還不夠,建議大家看我收藏合集里面講述模糊的超鏈接.
4.圖像光照效果 //圖片光照效果 private void SunshineImage() {/** 算法原理:(前一個像素點RGB-當前像素點RGB+127)作為當前像素點RGB值* 在ABC中計算B點浮雕效果(RGB值在0~255)* B.r = C.r - B.r + 127* B.g = C.g - B.g + 127* B.b = C.b - B.b + 127* 光照中心取長寬較小值為半徑,也可以自定義從左上角射過來*/ int width = bmp.getWidth();int height = bmp.getHeight();Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);int pixColor = 0;int pixR = 0;int pixG = 0;int pixB = 0;int newR = 0;int newG = 0;int newB = 0;//圍繞圓形光照int centerX = width / 2;int centerY = height / 2;int radius = Math.min(centerX, centerY);float strength = 150F; //光照強度100-150int[] pixels = new int[width * height];bmp.getPixels(pixels, 0, width, 0, 0, width, height);for (int i = 1; i < height-1; i++){for (int k = 1; k < width-1; k++){//獲取前一個像素顏色pixColor = pixels[width * i + k]; pixR = Color.red(pixColor);pixG = Color.green(pixColor);pixB = Color.blue(pixColor);newR = pixR;newG = pixG;newB = pixB;//計算當前點到光照中心的距離,平面坐標系中兩點之間的距離int distance = (int) (Math.pow((centerY-i), 2) + Math.pow((centerX-k), 2));if(distance < radius*radius){//按照距離大小計算增強的光照值int result = (int)(strength*( 1.0-Math.sqrt(distance) / radius ));newR = pixR + result;newG = newG + result;newB = pixB + result;}newR = Math.min(255, Math.max(0, newR));newG = Math.min(255, Math.max(0, newG));newB = Math.min(255, Math.max(0, newB));pixels[width * i + k] = Color.argb(255, newR, newG, newB);}}bitmap.setPixels(pixels, 0, width, 0, 0, width, height);imageShow.setImageBitmap(bitmap); } ? ? 顯示效果如下圖所示?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ? ?
5.圖片銳化效果
? ? 本打算采用拉普拉斯算子或Sobel算子對圖像進行銳化,在使用C++對24位bmp圖像處理時能非常好的顯示圖像的輪廓,但是Android總是效果不是很好啊,而且有虛線!網上一些銳化效果完全沒有實現顯示圖像輪廓,與原圖區別不大,感覺是錯誤的方法.研究ing //圖像銳化處理 拉普拉斯算子處理 private void SharpenImage() {/** 銳化基本思想是加強圖像中景物的邊緣和輪廓,使圖像變得清晰* 而圖像平滑是使圖像中邊界和輪廓變得模糊* * 拉普拉斯算子圖像銳化* 獲取周圍9個點的矩陣乘以模板9個的矩陣 卷積*///拉普拉斯算子模板 { 0, -1, 0, -1, -5, -1, 0, -1, 0 } { -1, -1, -1, -1, 9, -1, -1, -1, -1 }int[] laplacian = new int[] { -1, -1, -1, -1, 9, -1, -1, -1, -1 }; int width = bmp.getWidth(); int height = bmp.getHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); int pixR = 0; int pixG = 0; int pixB = 0; int pixColor = 0; int newR = 0; int newG = 0; int newB = 0; int idx = 0; float alpha = 0.3F; //圖片透明度int[] pixels = new int[width * height]; bmp.getPixels(pixels, 0, width, 0, 0, width, height); //圖像處理for (int i = 1; i < height - 1; i++) { for (int k = 1; k < width - 1; k++) { idx = 0;newR = 0; newG = 0; newB = 0; for (int n = -1; n <= 1; n++) //取出圖像3*3領域像素 { for (int m = -1; m <= 1; m++) //n行數不變 m列變換{ pixColor = pixels[(i + n) * width + k + m]; //當前點(i,k)pixR = Color.red(pixColor); pixG = Color.green(pixColor); pixB = Color.blue(pixColor); //圖像像素與對應摸板相乘 newR = newR + (int) (pixR * laplacian[idx] * alpha); newG = newG + (int) (pixG * laplacian[idx] * alpha); newB = newB + (int) (pixB * laplacian[idx] * alpha); idx++; } }newR = Math.min(255, Math.max(0, newR)); newG = Math.min(255, Math.max(0, newG)); newB = Math.min(255, Math.max(0, newB)); //賦值 pixels[i * width + k] = Color.argb(255, newR, newG, newB); }}bitmap.setPixels(pixels, 0, width, 0, 0, width, height); imageShow.setImageBitmap(bitmap); }
? ?作圖是其顯示效果,而右圖是我以前《數字圖像處理》課用C++寫的不同模版的銳化效果.
?
?
??? 下面再介紹些效果,下面這個效果是參考亞瑟BOY的冰凍效果.
? ? 源代碼地址:http://www.eoeandroid.com/thread-176490-1-1.html
? ? 源代碼地址:http://blog.csdn.net/xu_fu/article/details/21485461
? ? ??效果顯示如下圖所示,在Menu選擇中調用函數IceImage或SuMiaoImage即可實現.
? ? ? ? ? ? ?? ? ? ? ?? //素描效果 private void SuMiaoImage() {//創建新Bitmapint width = bmp.getWidth(); int height = bmp.getHeight(); int[] pixels = new int[width * height]; //存儲變換圖像int[] linpix = new int[width * height]; //存儲灰度圖像Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); bmp.getPixels(pixels, 0, width, 0, 0, width, height);int pixColor = 0;int pixR = 0;int pixG = 0;int pixB = 0;int newR = 0; int newG = 0; int newB = 0;//灰度圖像for (int i = 1; i < width - 1; i++) { for (int j = 1; j < height - 1; j++) //拉普拉斯算子模板 { 0, -1, 0, -1, -5, -1, 0, -1, 0 { //獲取前一個像素顏色pixColor = pixels[width * i + j]; pixR = Color.red(pixColor);pixG = Color.green(pixColor);pixB = Color.blue(pixColor);//灰度圖像int gray=(int)(0.3*pixR+0.59*pixG+0.11*pixB);linpix[width * i + j] = Color.argb(255, gray, gray, gray);//圖像反向gray=255-gray;pixels[width * i + j] = Color.argb(255, gray, gray, gray);}}int radius = Math.min(width/2, height/2);int[] copixels = gaussBlur(pixels, width, height, 10, 10/3); //高斯模糊 采用半徑10int[] result = colorDodge(linpix, copixels); //素描圖像 顏色減淡bitmap.setPixels(result, 0, width, 0, 0, width, height);imageShow.setImageBitmap(bitmap); }//高斯模糊 public static int[] gaussBlur(int[] data, int width, int height, int radius, float sigma) { float pa = (float) (1 / (Math.sqrt(2 * Math.PI) * sigma)); float pb = -1.0f / (2 * sigma * sigma); // generate the Gauss Matrix float[] gaussMatrix = new float[radius * 2 + 1]; float gaussSum = 0f; for (int i = 0, x = -radius; x <= radius; ++x, ++i) { float g = (float) (pa * Math.exp(pb * x * x)); gaussMatrix[i] = g; gaussSum += g; } for (int i = 0, length = gaussMatrix.length; i < length; ++i) { gaussMatrix[i] /= gaussSum; } // x direction for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { float r = 0, g = 0, b = 0; gaussSum = 0; for (int j = -radius; j <= radius; ++j) { int k = x + j; if (k >= 0 && k < width) { int index = y * width + k; int color = data[index]; int cr = (color & 0x00ff0000) >> 16; int cg = (color & 0x0000ff00) >> 8; int cb = (color & 0x000000ff); r += cr * gaussMatrix[j + radius]; g += cg * gaussMatrix[j + radius]; b += cb * gaussMatrix[j + radius]; gaussSum += gaussMatrix[j + radius]; } } int index = y * width + x; int cr = (int) (r / gaussSum); int cg = (int) (g / gaussSum); int cb = (int) (b / gaussSum); data[index] = cr << 16 | cg << 8 | cb | 0xff000000; } } // y direction for (int x = 0; x < width; ++x) { for (int y = 0; y < height; ++y) { float r = 0, g = 0, b = 0; gaussSum = 0; for (int j = -radius; j <= radius; ++j) { int k = y + j; if (k >= 0 && k < height) { int index = k * width + x; int color = data[index]; int cr = (color & 0x00ff0000) >> 16; int cg = (color & 0x0000ff00) >> 8; int cb = (color & 0x000000ff); r += cr * gaussMatrix[j + radius]; g += cg * gaussMatrix[j + radius]; b += cb * gaussMatrix[j + radius]; gaussSum += gaussMatrix[j + radius]; } } int index = y * width + x; int cr = (int) (r / gaussSum); int cg = (int) (g / gaussSum); int cb = (int) (b / gaussSum); data[index] = cr << 16 | cg << 8 | cb | 0xff000000; } } return data; } //顏色減淡 public static int[] colorDodge(int[] baseColor, int[] mixColor) { for (int i = 0, length = baseColor.length; i < length; ++i) { int bColor = baseColor[i]; int br = (bColor & 0x00ff0000) >> 16; int bg = (bColor & 0x0000ff00) >> 8; int bb = (bColor & 0x000000ff); int mColor = mixColor[i]; int mr = (mColor & 0x00ff0000) >> 16; int mg = (mColor & 0x0000ff00) >> 8; int mb = (mColor & 0x000000ff); int nr = colorDodgeFormular(br, mr); int ng = colorDodgeFormular(bg, mg); int nb = colorDodgeFormular(bb, mb); baseColor[i] = nr << 16 | ng << 8 | nb | 0xff000000; } return baseColor; } private static int colorDodgeFormular(int base, int mix) { int result = base + (base * mix) / (255 - mix); result = result > 255 ? 255 : result; return result; } ? ? 最后希望文章對大家有所幫助,感謝上面提到的作者,同時可能還有些如LOMO等效果可參考下面的文章,它是圖像處理的一個集合超鏈接.后面會寫PopupWindows實現美圖秀秀的效果和對人臉進行處理.
??? 源代碼下載:
? ? (By:Eastmount 2014-11-2 晚8點 http://blog.csdn.net/eastmount/)
總結
以上是生活随笔為你收集整理的[Android] 通过Menu实现图片怀旧、浮雕、模糊、光照和素描效果的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Android] 给图像添加相框、圆形
- 下一篇: [Android] 底部菜单布局+Pop