亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android自定義控件仿QQ編輯和選取圓形頭像

 更新時間:2016年09月30日 09:07:13   作者:u013147734  
這篇文章主要為大家詳細介紹了Android自定義控件編輯和選取圓形頭像,具有一定的參考價值,感興趣的小伙伴們可以參考一下

android大家都有很多需要用戶上傳頭像的需求,有的是選方形,有的是圓角矩形,有的是圓形。
首先我們要做一個處理圖片的自定義控件,把傳入的圖片,經(jīng)過用戶選擇區(qū)域,處理成一定的形狀。

有的app是通過在圖片上畫一個矩形區(qū)域表示選中的內(nèi)容,有的則是通過雙指放大縮小,拖動圖片來選取圖片。圓形頭像,還是改變圖片比較好

圓形區(qū)域可調(diào)節(jié)大小。

這個自定義View的圖像部分分為三個,背景圖片,半透明蒙層,和亮色區(qū)域……還是直接貼代碼得了

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;
 // 選區(qū)半徑
 private float radius = 150f;

 // 圓形選區(qū)的邊界
 private RectF circleBounds;

 // 最大放大倍數(shù)
 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) {
   // 判斷長寬比,當(dāng)長寬比太長會太寬是,以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);// 這個矩形僅為保存第一次的狀態(tài)

   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();

    // 不允許拖過圓形區(qū)域,不能使圓形區(qū)域內(nèi)空白
    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;

    // 不允許拖過圓形區(qū)域,不能使圓形區(qū)域內(nèi)空白
    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;// 恢復(fù)標志位
    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) {
   // 無法縮小到比選區(qū)還小,或到達最大倍數(shù)
   return;
  }
  // 把dst區(qū)域放大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;

  // 縮放同樣不允許使圓形區(qū)域空白
  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)));
 }

 // 生成目前選區(qū)指定大小的圓形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的當(dāng)前亮圓形中的圖片
   Bitmap result = imageView.extractBitmap(300);
   //壓縮成png
   FileOutputStream out = new FileOutputStream(new File(filePath));
   result.compress(Bitmap.CompressFormat.PNG, 100, out);
   //上傳與顯示
   ...
 }

需求是模仿QQ的,本人不太會講解,做著玩玩。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android新浪微博下拉刷新(最新消息顯示在最上面)

    Android新浪微博下拉刷新(最新消息顯示在最上面)

    查看最新消息要用到類似新浪微博下拉刷新,想必這個功能很多的朋友都會使用吧,下面與大家分享下具體的實現(xiàn)方法,感興趣的朋友可以參考下哈
    2013-05-05
  • Android實現(xiàn)簡單的自定義ViewGroup流式布局

    Android實現(xiàn)簡單的自定義ViewGroup流式布局

    本文我們將一起復(fù)習(xí)一下ViewGroup的測量布局方式。然后會以入門級的 FlowLayout 為例,來看看流式布局是如何測量與布局的,感興趣的可以了解一下
    2022-12-12
  • Android仿新浪微博/QQ空間滑動自動播放視頻功能

    Android仿新浪微博/QQ空間滑動自動播放視頻功能

    相信用過新浪微博或者QQ空間的朋友都看到過滑動自動播放視頻的效果,那么這篇文章跟大家分享下如何利用Android實現(xiàn)這一個功能,有需要的朋友們可以參考借鑒。
    2016-09-09
  • Android模仿微信收藏文件的標簽處理功能

    Android模仿微信收藏文件的標簽處理功能

    這篇文章主要介紹了android模仿微信收藏文件的標簽處理功能的相關(guān)資料,也可以刪除已編輯菜單,需要的朋友可以參考下
    2016-11-11
  • ScrollView與ListView合用(正確計算Listview的高度)的問題解決

    ScrollView與ListView合用(正確計算Listview的高度)的問題解決

    最近做項目中用到ScrollView和ListView一起使用的問題,顯示的時候ListView不能完全正確的顯示,查了好多資料終于成功解決:
    2013-05-05
  • Android框架組件Lifecycle的使用詳解

    Android框架組件Lifecycle的使用詳解

    這篇文章主要介紹了Android框架組件Lifecycle的使用詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • Android協(xié)程代替Handler使用示例詳解

    Android協(xié)程代替Handler使用示例詳解

    這篇文章主要為大家介紹了Android?協(xié)程代替Handler使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2024-01-01
  • Android基于Flutter編寫文件下載管理器

    Android基于Flutter編寫文件下載管理器

    文件下載在很多類型的應(yīng)用中會涉及,例如音樂、文檔、包括圖片(只是圖片可以使用一些組件完成無感知的下載)。本篇介紹使用Flutter中的Dio下載方法完成文件的下載,需要的可以參考一下
    2022-03-03
  • Android繪制雙折線圖的方法

    Android繪制雙折線圖的方法

    這篇文章主要為大家詳細介紹了Android繪制雙折線圖的方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Android文件下載功能實現(xiàn)代碼

    Android文件下載功能實現(xiàn)代碼

    這篇文章主要為大家詳細介紹了Android文件下載功能實現(xiàn)代碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07

最新評論