国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android實現長按圖片保存至相冊功能

2019-12-12 03:32:47
字體:
來源:轉載
供稿:網友

前言:前面寫了一篇reactnative的學習筆記,說reactnative的Android框架中有很多福利,確實是的,也說到了我們app中的一個把圖片保存到相冊的功能,好吧,還是準備寫一篇博客,就當筆記了~

先上幾張app的圖片:

一進app就是一個進度條加載圖片(我待會也會說一下進度條view跟怎么監聽圖片加載過程):

圖片加載完畢后:

長按圖片進入相冊可以看到我們保存的圖片:

監聽圖片加載的loaddingview源碼(不是很難,我就直接貼代碼了):

package com.leo.camerroll;import android.animation.ValueAnimator;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.RectF;import android.util.AttributeSet;import android.util.TypedValue;import android.view.View;import android.view.animation.Animation;import android.view.animation.LinearInterpolator;import android.widget.ProgressBar;/** * Created by leo on 17/1/22. */public class LoadingView extends ProgressBar {  private final int DEFAULT_RADIUS = dp2px(15);  private final int DEFAULT_REACH_COLOR = 0XFFFFFFFF;  private final int DEFAULT_UNREACH_COLOR = 0X88000000;  private final long ANIM_DURATION = 1000;  private final String BASE_TEXT = "00%";  private boolean isStop;  private int mRadius = DEFAULT_RADIUS;  private int mStrokeWidth;  private Paint reachPaint;  private Paint unreachPaint;  private Paint textPaint;  private Paint bgPaint;  private int mStartAngle=0;  private float mSweepAngle=360*0.382f;  private ValueAnimator anim;  public LoadingView(Context context) {    this(context, null);  }  public LoadingView(Context context, AttributeSet attrs) {    this(context, attrs, 0);  }  public LoadingView(Context context, AttributeSet attrs, int defStyleAttr) {    super(context, attrs, defStyleAttr);    initView();  }  private void initView() {    reachPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);    reachPaint.setStrokeCap(Paint.Cap.ROUND);    reachPaint.setStyle(Paint.Style.STROKE);    unreachPaint = new Paint(reachPaint);    reachPaint.setColor(DEFAULT_REACH_COLOR);    unreachPaint.setColor(DEFAULT_UNREACH_COLOR);    textPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);    textPaint.setStyle(Paint.Style.STROKE);    textPaint.setColor(Color.WHITE);    textPaint.setFakeBoldText(true);    bgPaint=new Paint(Paint.ANTI_ALIAS_FLAG|Paint.DITHER_FLAG);    bgPaint.setStrokeCap(Paint.Cap.ROUND);    bgPaint.setColor(Color.argb(44,0,0,0));    setMax(100);  }  @Override  protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    int defWidth = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);    int defHeight = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);    int expectSize = Math.min(defHeight, defWidth);    if (expectSize <= 0) {      expectSize = mRadius * 2;    } else {      mRadius = expectSize / 2;    }    mStrokeWidth = mRadius / 5;    reachPaint.setStrokeWidth(mStrokeWidth);    unreachPaint.setStrokeWidth(mStrokeWidth);    setMeasuredDimension(expectSize, expectSize);    float textSize=0;    while(true){      textSize+=0.1;      textPaint.setTextSize(textSize);      if(textPaint.measureText(BASE_TEXT,0,BASE_TEXT.length())>=mRadius){        break;      }    }  }  @Override  protected synchronized void onDraw(Canvas canvas) {    if(isStop){      setVisibility(View.GONE);      return;    }    //drawbackground transparent    canvas.drawCircle(getWidth()/2,getWidth()/2,mRadius-mStrokeWidth,bgPaint);    //draw reach    drawProgressReach(canvas);    //draw progress text    drawProgressText(canvas);  }  private void drawProgressText(Canvas canvas) {    String text=String.valueOf((int)(getProgress()*1.0f/getMax()*100))+"%";    int centerX=getWidth()/2;    int centerY=getWidth()/2;    int baseX= (int) (centerX-textPaint.measureText(text,0,text.length())/2);    int baseY= (int) (centerY-(textPaint.getFontMetrics().ascent+textPaint.getFontMetrics().descent)/2);    canvas.drawText(text,baseX,baseY,textPaint);  }  private void drawProgressReach(Canvas canvas) {    canvas.drawArc(new RectF(0 + mStrokeWidth / 2, 0 + mStrokeWidth / 2, mRadius * 2 - mStrokeWidth / 2, mRadius * 2 - mStrokeWidth / 2), mStartAngle, mSweepAngle, false, reachPaint);    //drawonreach    canvas.drawArc(new RectF(0 + mStrokeWidth / 2, 0 + mStrokeWidth / 2, mRadius * 2 - mStrokeWidth / 2, mRadius * 2 - mStrokeWidth / 2), mStartAngle+mSweepAngle, 360-mSweepAngle,false, unreachPaint);  }  @Override  protected void onAttachedToWindow() {    super.onAttachedToWindow();    if(anim==null){      anim=ValueAnimator.ofInt(0,360);      anim.setInterpolator(new LinearInterpolator());      anim.setDuration(ANIM_DURATION);      anim.setRepeatCount(Animation.INFINITE);      anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {        @Override        public void onAnimationUpdate(ValueAnimator animation) {          if(animation!=null&&animation.getAnimatedValue()!=null){            int startAngle= (int) animation.getAnimatedValue();            mStartAngle=startAngle;            postInvalidate();          }        }      });    }else{      anim.cancel();      anim.removeAllUpdateListeners();    }    anim.start();  }  public void loadCompleted() {    isStop=true;    if(anim!=null){      anim.cancel();      anim.removeAllUpdateListeners();      this.setVisibility(View.GONE);    }  }  /**   * @param size   * @return px   */  private int dp2px(int size) {    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size, getContext().getResources().getDisplayMetrics());  }}

實現起來還是很簡單的,就是動態改變兩端弧的起點和終點,通過屬性動畫不斷的在(0-360)循環,代碼應該還算比較清晰哈!~~~~

圖片加載用了一個AsyncTask:

private class DownImageTask extends AsyncTask<String, Long, Bitmap> {    private ImageView imageView;    private long contentLength;    public DownImageTask(ImageView imageView) {      this.imageView = imageView;    }    @Override    protected Bitmap doInBackground(String... params) {      Bitmap bitmap = null;      BufferedInputStream bis = null;      ByteArrayOutputStream bos = null;      try {        File fileDir=new File(getApplication().getExternalCacheDir(),"images");        if(fileDir==null||!fileDir.isDirectory()){          fileDir.mkdir();        }        File file=new File(fileDir.getAbsolutePath()+"/"+params[0].hashCode()+".png");        if(file!=null&&file.length()>0){          return bitmap=BitmapFactory.decodeFile(file.getAbsolutePath());        }        bos=new ByteArrayOutputStream();        byte[] buffer = new byte[512];        long total=0;        int len ;        URL url = new URL(params[0]);        HttpURLConnection conn = (HttpURLConnection) url.openConnection();        this.contentLength = conn.getContentLength();        bis = new BufferedInputStream(conn.getInputStream());        while ((len = bis.read(buffer)) != -1) {          total+=len;          publishProgress(total);          Thread.sleep(100);          bos.write(buffer, 0, len);          bos.flush();        }        bitmap= BitmapFactory.decodeByteArray(bos.toByteArray(),0,bos.toByteArray().length);        saveBitmapToDisk(bos,params[0]);      } catch (Exception e) {        e.printStackTrace();      } finally {        try {          if (bis != null) {            bis.close();          }          if (bos != null) {            bos.close();          }        } catch (IOException e) {          e.printStackTrace();        }      }      return bitmap;    }    private void saveBitmapToDisk(final ByteArrayOutputStream baos, final String url) {      new Thread(){        @Override        public void run() {BufferedOutputStream bos=null;          try{            if(!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())){              Log.e("TAG","內存卡不存在");              return;            }            Log.e("TAG","開始保存圖片至內存卡~~");            byte[] bytes = baos.toByteArray();            File fileDir=new File(getApplication().getExternalCacheDir(),"images");            if(fileDir==null||!fileDir.isDirectory()){              fileDir.mkdir();            }            File file=new File(fileDir.getAbsolutePath()+"/"+url.hashCode()+".png");            file.createNewFile();            bos=new BufferedOutputStream(new FileOutputStream(file));            bos.write(bytes);            bos.flush();            Log.e("TAG","圖片已經保存至內存卡~~");          }catch (Exception e){            e.printStackTrace();          }finally {            if(bos!=null){              try {                bos.close();              } catch (IOException e) {                e.printStackTrace();              }            }          }        }      }.start();    }    @Override    protected void onProgressUpdate(Long... values) {      mLoadingView.setProgress((int) ((values[0].longValue() * 1.0f / contentLength) * 100));    }    @Override    protected void onPostExecute(Bitmap bitmap) {      if (imageView != null && bitmap != null) {        imageView.setImageBitmap(bitmap);        mLoadingView.loadCompleted();      }    }  }

加載完畢后把圖片存放在了內存卡中(當然,這是我隨便寫的一個圖片加載,大家換成自己的加載框架哈,):

private void saveBitmapToDisk(final ByteArrayOutputStream baos, final String url) {      new Thread(){        @Override        public void run() {BufferedOutputStream bos=null;          try{            if(!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())){              Log.e("TAG","內存卡不存在");              return;            }            Log.e("TAG","開始保存圖片至內存卡~~");            byte[] bytes = baos.toByteArray();            File fileDir=new File(getApplication().getExternalCacheDir(),"images");            if(fileDir==null||!fileDir.isDirectory()){              fileDir.mkdir();            }            File file=new File(fileDir.getAbsolutePath()+"/"+url.hashCode()+".png");            file.createNewFile();            bos=new BufferedOutputStream(new FileOutputStream(file));            bos.write(bytes);            bos.flush();            Log.e("TAG","圖片已經保存至內存卡~~");          }catch (Exception e){            e.printStackTrace();          }finally {            if(bos!=null){              try {                bos.close();              } catch (IOException e) {                e.printStackTrace();              }            }          }        }      }.start();    }

這里我們是需要把圖片保存到內存卡中,所以考慮到了android 6.0的運行時權限,所以小伙伴們也一定要判斷哦,我在oncreate的時候就判斷了:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {      if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)          != PackageManager.PERMISSION_GRANTED) {        requestAlertWindowPermission();      }    }
private static final int REQUEST_CODE = 1;  private void requestAlertWindowPermission() {    ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},REQUEST_CODE);  }

下面就是講長按圖片保存至相冊了:

 mImageView.setOnLongClickListener(new View.OnLongClickListener(){      @Override      public boolean onLongClick(View v) {        if(mImageView.getDrawable() instanceof BitmapDrawable){          Toast.makeText(getApplicationContext(),"長按保存圖片至相冊",Toast.LENGTH_SHORT).show();          File fileDir=new File(getApplication().getExternalCacheDir(),"images");          File file=new File(fileDir.getAbsolutePath()+"/"+IMAGE_URL.hashCode()+".png");          if(file!=null&&file.length()>0){            CameraRollManager rollManager=new CameraRollManager(MainActivity.this, Uri.parse(file.getAbsolutePath()));            rollManager.execute();          }        }        return false;      }    });

CameraRollManager是我直接copy的reactnatvie中的android模塊的代碼:

CameraRollManager.java

package com.leo.camerroll.camera;import android.content.Context;import android.content.Intent;import android.media.MediaScannerConnection;import android.net.Uri;import android.os.Environment;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.widget.Toast;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.nio.channels.FileChannel;/** * Created by leo on 17/1/22. */public class CameraRollManager extends GuardedAsyncTask{  private static Context mContext;  private final Uri mUri;  private static Handler handler=new Handler(Looper.getMainLooper()){    @Override    public void handleMessage(Message msg) {      Toast.makeText(mContext,"保存成功!",Toast.LENGTH_SHORT).show();      Intent intent = new Intent();      intent.setType("image/*");      intent.setAction(Intent.ACTION_GET_CONTENT);      mContext.startActivity(intent);    }  };  public CameraRollManager(Context context, Uri uri) {    super(context);    mContext = context;    mUri = uri;  }  @Override  protected void doInBackgroundGuarded(Object[] params) {    File source = new File(mUri.getPath());    FileChannel input = null, output = null;    try {      File exportDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);      exportDir.mkdirs();      if (!exportDir.isDirectory()) {        return;      }      File dest = new File(exportDir, source.getName());      int n = 0;      String fullSourceName = source.getName();      String sourceName, sourceExt;      if (fullSourceName.indexOf('.') >= 0) {        sourceName = fullSourceName.substring(0, fullSourceName.lastIndexOf('.'));        sourceExt = fullSourceName.substring(fullSourceName.lastIndexOf('.'));      } else {        sourceName = fullSourceName;        sourceExt = "";      }      while (!dest.createNewFile()) {        dest = new File(exportDir, sourceName + "_" + (n++) + sourceExt);      }      input = new FileInputStream(source).getChannel();      output = new FileOutputStream(dest).getChannel();      output.transferFrom(input, 0, input.size());      input.close();      output.close();      MediaScannerConnection.scanFile(          mContext,          new String[]{dest.getAbsolutePath()},          null,          new MediaScannerConnection.OnScanCompletedListener() {            @Override            public void onScanCompleted(String path, Uri uri) {              handler.sendEmptyMessage(0);            }          });    } catch (IOException e) {    } finally {      if (input != null && input.isOpen()) {        try {          input.close();        } catch (IOException e) {        }      }      if (output != null && output.isOpen()) {        try {          output.close();        } catch (IOException e) {        }      }    }  }}

GuardedAsyncTask.java:

package com.leo.camerroll.camera;import android.content.Context;import android.os.AsyncTask;/** * Created by leo on 17/1/22. */public abstract class GuardedAsyncTask <Params, Progress>    extends AsyncTask<Params, Progress, Void> {  private final Context mReactContext;  protected GuardedAsyncTask(Context reactContext) {    mReactContext = reactContext;  }  @Override  protected final Void doInBackground(Params... params) {    try {      doInBackgroundGuarded(params);    } catch (RuntimeException e) {    }    return null;  }  protected abstract void doInBackgroundGuarded(Params... params);}

好啦?。?! 看著簡單哈,花了我一個上午的時間,還是自己不熟練的原因額,感覺高了一段時間rn,結果android原生又生疏了,小伙伴們如果也像我一樣的話,一定要常練習哦,兩個東西都是需要常敲的那種,不然又忘記了?。?!

最后附上demo的git鏈接:
https://github.com/913453448/CamerRoll

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 通渭县| 泗洪县| 平武县| 绥江县| 建水县| 兴安盟| 株洲市| 阜康市| 苗栗县| 平谷区| 昭苏县| 会同县| 叙永县| 奉新县| 吉首市| 宝应县| SHOW| 和平县| 长春市| 吴旗县| 焦作市| 江油市| 拉萨市| 怀来县| 商城县| 兴义市| 安达市| 东台市| 金乡县| 镇远县| 高台县| 农安县| 探索| 宣武区| 高陵县| 泸西县| 西城区| 绥滨县| 增城市| 拉萨市| 年辖:市辖区|