欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android實(shí)現(xiàn)長(zhǎng)按圖片保存至相冊(cè)功能

 更新時(shí)間:2017年03月01日 10:04:54   作者:vv_小蟲(chóng)  
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)長(zhǎng)按圖片保存至相冊(cè)功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

前言:前面寫了一篇reactnative的學(xué)習(xí)筆記,說(shuō)reactnative的Android框架中有很多福利,確實(shí)是的,也說(shuō)到了我們app中的一個(gè)把圖片保存到相冊(cè)的功能,好吧,還是準(zhǔn)備寫一篇博客,就當(dāng)筆記了~

先上幾張app的圖片:

一進(jìn)app就是一個(gè)進(jìn)度條加載圖片(我待會(huì)也會(huì)說(shuō)一下進(jìn)度條view跟怎么監(jiān)聽(tīng)圖片加載過(guò)程):

圖片加載完畢后:

長(zhǎng)按圖片進(jìn)入相冊(cè)可以看到我們保存的圖片:

監(jiān)聽(tīng)圖片加載的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());
  }
}

實(shí)現(xiàn)起來(lái)還是很簡(jiǎn)單的,就是動(dòng)態(tài)改變兩端弧的起點(diǎn)和終點(diǎn),通過(guò)屬性動(dòng)畫不斷的在(0-360)循環(huán),代碼應(yīng)該還算比較清晰哈!~~~~

圖片加載用了一個(gè)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","內(nèi)存卡不存在");
              return;
            }
            Log.e("TAG","開(kāi)始保存圖片至內(nèi)存卡~~");
            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","圖片已經(jīng)保存至內(nèi)存卡~~");
          }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();
      }
    }
  }

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

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","內(nèi)存卡不存在");
              return;
            }
            Log.e("TAG","開(kāi)始保存圖片至內(nèi)存卡~~");
            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","圖片已經(jīng)保存至內(nèi)存卡~~");
          }catch (Exception e){
            e.printStackTrace();
          }finally {
            if(bos!=null){
              try {
                bos.close();
              } catch (IOException e) {
                e.printStackTrace();
              }
            }
          }
        }
      }.start();
    }

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

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

下面就是講長(zhǎng)按圖片保存至相冊(cè)了:

 mImageView.setOnLongClickListener(new View.OnLongClickListener(){
      @Override
      public boolean onLongClick(View v) {
        if(mImageView.getDrawable() instanceof BitmapDrawable){
          Toast.makeText(getApplicationContext(),"長(zhǎng)按保存圖片至相冊(cè)",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);
}

好啦?。。?看著簡(jiǎn)單哈,花了我一個(gè)上午的時(shí)間,還是自己不熟練的原因額,感覺(jué)高了一段時(shí)間rn,結(jié)果android原生又生疏了,小伙伴們?nèi)绻蚕裎乙粯拥脑挘欢ㄒ>毩?xí)哦,兩個(gè)東西都是需要常敲的那種,不然又忘記了?。?!

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

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

相關(guān)文章

  • Android Studio下添加assets目錄的實(shí)現(xiàn)方法

    Android Studio下添加assets目錄的實(shí)現(xiàn)方法

    下面小編就為大家?guī)?lái)一篇Android Studio下添加assets目錄的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-03-03
  • Android實(shí)現(xiàn)精確到天時(shí)分秒的搶購(gòu)倒計(jì)時(shí)

    Android實(shí)現(xiàn)精確到天時(shí)分秒的搶購(gòu)倒計(jì)時(shí)

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)精確到天時(shí)分秒的搶購(gòu)倒計(jì)時(shí),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • Android中Bitmap用法實(shí)例分析

    Android中Bitmap用法實(shí)例分析

    這篇文章主要介紹了Android中Bitmap用法,結(jié)合實(shí)例形式分析了Android操作圖片的載入、屬性設(shè)置、旋轉(zhuǎn)等相關(guān)技巧,需要的朋友可以參考下
    2016-02-02
  • Android PopWindow 設(shè)置背景亮度的實(shí)例

    Android PopWindow 設(shè)置背景亮度的實(shí)例

    這篇文章主要介紹了Android PopWindow 設(shè)置背景亮度的實(shí)例的相關(guān)資料,這里提供實(shí)現(xiàn)方法,希望能幫助有所需要的朋友,需要的朋友可以參考下
    2017-08-08
  • Android 四種獲取屏幕寬度的方法總結(jié)

    Android 四種獲取屏幕寬度的方法總結(jié)

    這篇文章主要介紹了Android 四種獲取屏幕寬度的方法總結(jié)的相關(guān)資料,這里對(duì)四種方法進(jìn)行了一一介紹,需要的朋友可以參考下
    2017-01-01
  • Kotlin 協(xié)程 supervisorScope {} 運(yùn)行崩潰解決方法

    Kotlin 協(xié)程 supervisorScope {} 運(yùn)行崩潰解決方法

    看過(guò)很多?supervisorScope {}?文檔的使用,我照抄一摸一樣的代碼,運(yùn)行就崩潰,最后找到了解決方法,應(yīng)該是kotlin版本更新做過(guò)改動(dòng),當(dāng)前我使用的是?androidx.core:core-ktx:1.9.0,本文給大家介紹Kotlin 協(xié)程 supervisorScope {} 運(yùn)行崩潰解決方法,感興趣的朋友一起看看吧
    2024-01-01
  • Kotlin語(yǔ)言中CompileSdkVersion與targetSdkVersion的區(qū)別淺析

    Kotlin語(yǔ)言中CompileSdkVersion與targetSdkVersion的區(qū)別淺析

    這篇文章主要介紹了Kotlin語(yǔ)言中CompileSdkVersion和targetSdkVersion有什么區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2023-02-02
  • Android?通用視頻組件開(kāi)發(fā)過(guò)程詳解

    Android?通用視頻組件開(kāi)發(fā)過(guò)程詳解

    這篇文章主要介紹了Android?通用視頻組件開(kāi)發(fā)的詳細(xì)過(guò)程,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2024-07-07
  • Android仿IOS底部彈出對(duì)話框

    Android仿IOS底部彈出對(duì)話框

    這篇文章主要為大家詳細(xì)介紹了Android仿IOS底部彈出對(duì)話框的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Android開(kāi)發(fā)-之環(huán)境的搭建(圖文詳解)

    Android開(kāi)發(fā)-之環(huán)境的搭建(圖文詳解)

    這篇文章主要介紹了Android開(kāi)發(fā)-之環(huán)境的搭建(圖文詳解),具有一定的參考價(jià)值,有興趣的可以了解一下。
    2016-11-11

最新評(píng)論