顯示具有 Image 標籤的文章。 顯示所有文章
顯示具有 Image 標籤的文章。 顯示所有文章

2017年8月10日 星期四

iOS Swift Cache Image 簡易的Image Cache

簡單的Cache Image, 讓圖片不用一直下載,造成卡卡的問題

1.建立一個Project, 先在Info.plist ->右鍵 Open AS -> 選Source Code
在dict內加入,
NSAppTransportSecurity
NSAllowsArbitraryLoads 

2.接著建立MyTableViewCell.swift, 後面在Cell建立Image View後拉過來對應
class MyTableViewCell: UITableViewCell {

    @IBOutlet weak var iv: UIImageView!
    
    var ivUrl: NSURL! //圖片來源url
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}

3.然後在Main.storyboard拉一個Table View

在cell裡面加個Image View, 對應Class: MyTableViewCell
Table View拉一下dataSource與delegate到ViewController
記得給Cell的Identifier,這裡寫ImageCell

4.建立一個CustomImageCache.swift檔案
import UIKit

class CustomImageCache {
    
    static let sharedCache: NSCache = { () -> NSCache<AnyObject, AnyObject> in
        let cache = NSCache<AnyObject, AnyObject>()
        cache.name = "MyImageCache"
        cache.countLimit = 20 // Max 20 images in memory.
        cache.totalCostLimit = 10*1024*1024 // Max 10MB used.
        return cache
    }()
    
}

extension NSURL {
    
    typealias ImageCacheCompletion = (UIImage) -> Void
    
    
    var cachedImage: UIImage? {
        return CustomImageCache.sharedCache.object(
            forKey: absoluteString as AnyObject) as? UIImage
    }
    
    func fetchImage(completion: @escaping ImageCacheCompletion) {
        // 如果需要客製化取得資料在此做
        let task = URLSession.shared.dataTask(with: self as URL) {
            data, response, error in
            if error == nil {
                if let data = data, let image = UIImage(data: data) {
                    CustomImageCache.sharedCache.setObject(
                        image,
                        forKey: self.absoluteString as AnyObject,
                        cost: data.count)
                    DispatchQueue.main.async() {
                        completion(image)
                    }
                }
            }
        }
        task.resume()
    }
    
}

5.最後在ViewController.swift
import UIKit

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    var url = [String]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 重複50張圖片
        url = Array(repeating: "http://g03.a.alicdn.com/kf/HTB1hvNUIFXXXXbBXFXXq6xXFXXX2/3D-Diamond-Embroidery-Paintings-Rhinestone-Pasted-diy-Diamond-painting-cross-Stitch-font-b-coffe-b-font.jpg", count: 50)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return url.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell: MyTableViewCell = tableView.dequeueReusableCell(withIdentifier: "ImageCell") as! MyTableViewCell
        let ivUrl = NSURL(string: url[indexPath.row])
    
        cell.ivUrl = ivUrl // For recycled cells' late image loads.
        if let image = ivUrl?.cachedImage { //抓過了 -> 直接顯示
            cell.iv.image = image
            cell.iv.alpha = 1
        } else { //沒抓過 ->下載圖片
            cell.iv.alpha = 0
            // 下載圖片
            ivUrl?.fetchImage { image in
                // Check the cell hasn't recycled while loading.
                if cell.ivUrl == ivUrl {
                    cell.iv.image = image
                    UIView.animate(withDuration: 0.3) {
                        cell.iv.alpha = 1
                    }
                }
            }
        }
        
        return cell
    }
}



檔案下載:
https://github.com/terryyamg/CacheImag
參考來源:
http://www.splinter.com.au/2015/09/24/swift-image-cache/

2015年4月28日 星期二

Android Load Image From Camera Or Gallery 讀取照片從相機或圖片庫

利用相機拍照或從已經存在的圖片庫,讀取照片並紀錄,將其顯示在app上。
1.AndroidManifest.xml加入讀取與寫入權限
 
 
2./res/layout/activity_main.xml


    

        
    

    

        
        
    


3.MainActivity.java
package tw.android;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.provider.MediaStore.MediaColumns;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends Activity {

 private Button btnSelect;
 private ImageView ivImage;

 private int REQUEST_CAMERA = 0, SELECT_FILE = 1;
 private String selectedImagePath; // 圖片檔案位置

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  btnSelect = (Button) findViewById(R.id.btnSelectPhoto);
  ivImage = (ImageView) findViewById(R.id.ivImage);

  // 取出最後圖片檔案位置
  try {
   SharedPreferences preferencesGet = getApplicationContext()
     .getSharedPreferences("image",
       android.content.Context.MODE_PRIVATE);
   selectedImagePath = preferencesGet.getString("selectedImagePath",
     ""); // 圖片檔案位置,預設為空

   Log.i("selectedImagePath", selectedImagePath + "");

  } catch (Exception e) {
  }

  /* 選擇照片 */
  btnSelect.setOnClickListener(new OnClickListener() {

   public void onClick(View v) {
    selectImage();
   }
  });

  setImage();
 }

 /* 設定圖片 */
 private void setImage() {
  BitmapFactory.Options options = new BitmapFactory.Options();
  options.inJustDecodeBounds = false; // 不顯示照片
  BitmapFactory.decodeFile(selectedImagePath, options);
  final int REQUIRED_SIZE = 200;
  int scale = 1;
  /* 圖片縮小2倍 */
  while (options.outWidth / scale / 2 >= REQUIRED_SIZE
    && options.outHeight / scale / 2 >= REQUIRED_SIZE) {
   scale *= 2;
  }
  options.inSampleSize = scale;
  options.inJustDecodeBounds = false; // 顯示照片
  Bitmap bm = BitmapFactory.decodeFile(selectedImagePath, options);
  Log.i("selectedImagePath", selectedImagePath + "");
  ivImage.setImageBitmap(bm);// 將圖片顯示
 }

 private void selectImage() {
  final String item1, item2, item3;
  item1 = "拍一張照";
  item2 = "從圖庫選取";
  item3 = "取消";

  final CharSequence[] items = { item1, item2, item3 };

  AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
  builder.setTitle("新增照片視窗");
  builder.setItems(items, new DialogInterface.OnClickListener() {
   public void onClick(DialogInterface dialog, int item) {
    switch (item) {
    case 0: // 拍一張照
     Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
     startActivityForResult(intent, REQUEST_CAMERA);
     break;
    case 1: // 從圖庫選取
     Intent intent1 = new Intent(
       Intent.ACTION_PICK,
       android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
     intent1.setType("image/*");
     startActivityForResult(
       Intent.createChooser(intent1, "選擇開啟圖庫"),
       SELECT_FILE);
     break;
    default: // 取消
     dialog.dismiss(); // 關閉對畫框
     break;
    }

   }
  });
  builder.show();
 }

 /* 啟動選擇方式 */
 @Override
 public void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);

  if (resultCode == Activity.RESULT_OK) {
   if (requestCode == SELECT_FILE) // 從圖庫開啟
    onSelectFromGalleryResult(data);
   else if (requestCode == REQUEST_CAMERA) // 拍照
    onCaptureImageResult(data);
  }
 }

 /* 拍照 */
 private void onCaptureImageResult(Intent data) {
  Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
  ByteArrayOutputStream bytes = new ByteArrayOutputStream();
  thumbnail.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
  File destination = new File(Environment.getExternalStorageDirectory(),
    System.currentTimeMillis() + ".jpg"); // 輸出檔案名稱
  selectedImagePath = destination + ""; // 輸出檔案位置
  FileOutputStream fo;
  try {
   destination.createNewFile(); // 建立檔案
   fo = new FileOutputStream(destination); // 輸出
   fo.write(bytes.toByteArray());
   fo.close();
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }

  ivImage.setImageBitmap(thumbnail); // 將圖片顯示
 }

 @SuppressWarnings("deprecation")
 private void onSelectFromGalleryResult(Intent data) {
  Uri selectedImageUri = data.getData();
  String[] projection = { MediaColumns.DATA };
  Cursor cursor = managedQuery(selectedImageUri, projection, null, null,
    null);
  int column_index = cursor.getColumnIndexOrThrow(MediaColumns.DATA);
  cursor.moveToFirst();

  selectedImagePath = cursor.getString(column_index); // 選擇的照片位置

  setImage(); // 設定圖片
 }

 /* 結束時 */
 @Override
 protected void onDestroy() {
  super.onDestroy();
  /* 紀錄圖片檔案位置 */
  SharedPreferences preferencesSave = getApplicationContext()
    .getSharedPreferences("image",
      android.content.Context.MODE_PRIVATE);
  SharedPreferences.Editor editor = preferencesSave.edit();
  editor.putString("selectedImagePath", selectedImagePath); // 紀錄最後圖片位置
  editor.commit();

  Log.i("onDestroy", "onDestroy");
 }

}



檔案下載:
https://github.com/terryyamg/loadImageFromGalleryTest
參考來源:
http://www.theappguruz.com/blog/android-take-photo-camera-gallery-code-sample/

2015年4月21日 星期二

Android Load Image From Url 讀取網址照片

從網址上讀取圖片,仿ptt app讀圖片功能
1.AndroidManifest.xml加入網路權限
    
    

2./res/layout/activity_main.xml


    

    

    
    


3.MainActivity.java
package tw.android;

import java.io.InputStream;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends Activity {

 private Button btUrl, btLoad;
 private String url;

 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  btUrl = (Button) findViewById(R.id.btUrl);
  btLoad = (Button) findViewById(R.id.btLoad);

  /* 顯示url */

  url = "http://i.imgur.com/WPydEEx.jpg"; // 圖片網址
  btUrl.setText(url); // 顯示網址
  btUrl.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View v) {
    Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri
      .parse(url));
    startActivity(browserIntent); // 使用網頁開啟
   }
  });

  /* 下載圖片 */
  btLoad.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View v) {
    btLoad.setVisibility(View.GONE); // 隱藏按鈕
    new DownloadImageTask((ImageView) findViewById(R.id.ivLoad))
      .execute(url); // 載入圖片

   }
  });

 }

 /* AsyncTask執行下載任務 */
 @SuppressLint("NewApi")
 private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
  ImageView bmImage;

  public DownloadImageTask(ImageView bmImage) {
   this.bmImage = bmImage;
  }

  protected Bitmap doInBackground(String... urls) {
   String urldisplay = urls[0];
   Bitmap mIcon11 = null;
   try {
    InputStream in = new java.net.URL(urldisplay).openStream(); // 從網址上下載
    mIcon11 = BitmapFactory.decodeStream(in);
   } catch (Exception e) {
    Log.e("Error", e.getMessage());
    e.printStackTrace();
   }
   return mIcon11;
  }

  protected void onPostExecute(Bitmap result) {
   bmImage.setImageBitmap(result); // 下載完成後載入結果
  }
 }
}


參考網址:
http://stackoverflow.com/questions/5776851/load-image-from-url