編輯:關於Android編程
android大家都有很多需要用戶上傳頭像的需求,有的是選方形,有的是圓角矩形,有的是圓形。
首先我們要做一個處理圖片的自定義控件,把傳入的圖片,經過用戶選擇區域,處理成一定的形狀。
有的app是通過在圖片上畫一個矩形區域表示選中的內容,有的則是通過雙指放大縮小,拖動圖片來選取圖片。圓形頭像,還是改變圖片比較好
圓形區域可調節大小。
這個自定義View的圖像部分分為三個,背景圖片,半透明蒙層,和亮色區域……還是直接貼代碼得了
package com.example.jjj.widget; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; public class RoundEditImageView extends View { private Bitmap bitmap; RectF clipBounds, dst, src; Paint clearPaint; // 控件寬高 private int w, h; // 選區半徑 private float radius = 150f; // 圓形選區的邊界 private RectF circleBounds; // 最大放大倍數 private float max_scale = 2.0f; // 雙指的距離 private float distance; private float x0, y0; private boolean doublePoint; public RoundEditImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } public RoundEditImageView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public RoundEditImageView(Context context) { super(context); init(); } private void init() { clearPaint = new Paint(Paint.ANTI_ALIAS_FLAG); clearPaint.setColor(Color.GRAY); clearPaint.setXfermode(new PorterDuffXfermode(Mode.CLEAR)); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (bitmap != null) { canvas.drawBitmap(bitmap, null, dst, null);//每次invalidate通過改變dst達到縮放平移的目的 } // 保存圖層,以免清除時清除了bitmap int count = canvas.saveLayer(clipBounds, null, Canvas.ALL_SAVE_FLAG); canvas.drawColor(0x80000000); canvas.drawCircle(w / 2, h / 2, radius, clearPaint);// 清除半透明黑色,留下一個透明圓 canvas.restoreToCount(count); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); this.w = w; this.h = h; // 記錄view所占的矩形 clipBounds = new RectF(0, 0, w, h); float l, r, t, b; if (bitmap != null) { // 判斷長寬比,當長寬比太長會太寬是,以fitCenter的方式初始化圖片 if (w / (float) h > bitmap.getWidth() / (float) bitmap.getHeight()) { // 圖片太高 float w_ = h * bitmap.getWidth() / (float) bitmap.getHeight(); l = w / 2f - w_ / 2f; r = w / 2f + w_ / 2f; t = 0; b = h; } else { // 圖片太長,或跟view一樣長 float h_ = w * bitmap.getHeight() / (float) bitmap.getWidth(); l = 0; r = w; t = h / 2f - h_ / 2f; b = h / 2f + h_ / 2f; } dst = new RectF(l, t, r, b);// 這個矩形用來變換 src = new RectF(l, t, r, b);// 這個矩形僅為保存第一次的狀態 max_scale = Math.max(max_scale, bitmap.getWidth() / src.width()); } circleBounds = new RectF(w / 2 - radius, h / 2 - radius, w / 2 + radius, h / 2 + radius); } public void setImageBitmap(Bitmap bitmap) { this.bitmap = bitmap; invalidate(); } @Override public boolean dispatchTouchEvent(MotionEvent e) { if (e.getPointerCount() > 2) {// 不接受多於兩指的事件 return false; } else if (e.getPointerCount() == 2) { doublePoint = true;// 標志位,記錄兩指事件處理後,抬起一只手也不處理拖動 handleDoubleMove(e); } else { // 處理單指的拖動 switch (e.getAction()) { case MotionEvent.ACTION_DOWN: x0 = e.getX(); y0 = e.getY(); break; case MotionEvent.ACTION_MOVE: if (doublePoint) { break; } float x = e.getX(); float y = e.getY(); float w = dst.width(); float h = dst.height(); // 不允許拖過圓形區域,不能使圓形區域內空白 dst.left += x - x0; if (dst.left > circleBounds.left) { dst.left = circleBounds.left; } else if (dst.left < circleBounds.right - w) { dst.left = circleBounds.right - w; } dst.right = dst.left + w; // 不允許拖過圓形區域,不能使圓形區域內空白 dst.top += y - y0; if (dst.top > circleBounds.top) { dst.top = circleBounds.top; } else if (dst.top < circleBounds.bottom - h) { dst.top = circleBounds.bottom - h; } dst.bottom = dst.top + h; x0 = x; y0 = y; invalidate(); break; case MotionEvent.ACTION_UP: doublePoint = false;// 恢復標志位 break; } } return true; } // 處理雙指事件 private void handleDoubleMove(MotionEvent e) { switch (e.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_POINTER_DOWN: distance = sqrt(e); Log.d("px", "down:distance=" + distance); break; case MotionEvent.ACTION_MOVE: scale(e); break; case MotionEvent.ACTION_UP: break; default: break; } } private void scale(MotionEvent e) { float dis = sqrt(e); // 以雙指中心作為圖片縮放的支點 float pX = e.getX(0) / 2f + e.getX(1) / 2f; float pY = e.getY(0) / 2f + e.getY(1) / 2f; float scale = dis / distance; Log.d("px", "move:distance=" + dis + ",scale to" + scale); float w = dst.width(); float h = dst.height(); if (w * scale < radius * 2 || h * scale < radius * 2 || w * scale > src.width() * max_scale) { // 無法縮小到比選區還小,或到達最大倍數 return; } // 把dst區域放大scale倍 dst.left = (dst.left - pX) * scale + pX; dst.right = (dst.right - pX) * scale + pX; dst.top = (dst.top - pY) * scale + pY; dst.bottom = (dst.bottom - pY) * scale + pY; // 縮放同樣不允許使圓形區域空白 if (dst.left > circleBounds.left) { dst.left = circleBounds.left; dst.right = dst.left + w * scale; } else if (dst.right < circleBounds.right) { dst.right = circleBounds.right; dst.left = dst.right - w * scale; } if (dst.top > circleBounds.top) { dst.top = circleBounds.top; dst.bottom = dst.top + h * scale; } else if (dst.bottom < circleBounds.bottom) { dst.bottom = circleBounds.bottom; dst.top = dst.bottom - h * scale; } invalidate(); distance = dis; } private float sqrt(MotionEvent e) { return (float) Math.sqrt((e.getX(0) - e.getX(1)) * (e.getX(0) - e.getX(1)) + (e.getY(0) - e.getY(1)) * (e.getY(0) - e.getY(1))); } // 生成目前選區指定大小的圓形bitmap public Bitmap extractBitmap(int width) { Bitmap outBitmap = Bitmap.createBitmap(width, width, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(outBitmap); Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); p.setColor(Color.GRAY); canvas.drawCircle(width / 2, width / 2, width / 2, p); float scale = dst.width() / bitmap.getWidth(); int w = (int) (circleBounds.width() / scale); int l = (int) ((circleBounds.left - dst.left) / scale); int r = l + w; int t = (int) ((circleBounds.top - dst.top) / scale); int b = t + w; Rect resRect = new Rect(l, t, r, b); Paint paint = new Paint(); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(bitmap, resRect, canvas.getClipBounds(), paint); return outBitmap; } }
Activity中用法
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_select_header); RoundEditImageView imageView = (RoundEditImageView) findViewById(R.id.roundEditImageView1); bitmap = BitmapFactory.decodeFile(imagePath); imageView.setImageBitmap(bitmap); } @Override public void onClick(View v) { //生成一個300*300的當前亮圓形中的圖片 Bitmap result = imageView.extractBitmap(300); //壓縮成png FileOutputStream out = new FileOutputStream(new File(filePath)); result.compress(Bitmap.CompressFormat.PNG, 100, out); //上傳與顯示 ... }
需求是模仿QQ的,本人不太會講解,做著玩玩。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。
從意圖返回結果 startActivity()方法調用另一個活動,但並沒有返回結果給當前活動。此時如想從一個活動中回傳數據,就要使用startActivityFo
我們在開發android的過程中,合理使用動畫能夠提高用戶體驗,帶給用戶耳目一新的感覺。因此我們應該掌握android的動畫使用。我在開發的過程中,很少自己寫動畫,在gi
一.Activity的四種啟動模式:當應用運行起來後就會開啟一條線程,線程中會運行一個任務棧,當Activity實例創建後就會放入任務棧中。可以根據實際的需求為Activ
NDK是什麼?Android平台是基於java實現,運行於虛擬機Dalvik;故而使用Android SDK創建應用程序需要使用java語言來編寫實現。不過並不僅限於使用