2015年7月15日 星期三

Android Volley Cache 緩衝 讀取 圖片

先下載資訊,在下滑ListView時,才進行網路讀取圖片。

1.先下載android-support-v4.jarvolley.jar,並在專案下建立libs資料夾,放入libs此資料夾

2.先建立一個list.json檔案,要存成UTF-8格式,並放入圖片url
[{
        "title": "鐵刀",
        "image": "http://terryyamg.3eeweb.com/test/pic/b01.JPG",
        "attack": 480,
        "attributes": "無",
        "material": ["燕雀石x3", "鐵礦石x8","大地的結晶x7", "砥石x12"]
    },
    {
        "title": "鐵刀【禊】",
        "image": "http://terryyamg.3eeweb.com/test/pic/b02.JPG",
        "attack": 528,
        "attributes": "無",
        "material": ["鐵礦石x10", "燕雀石x6", "大地的結晶x10"]
    },
    {
        "title": "鐵刀【神樂】",
        "image": "http://terryyamg.3eeweb.com/test/pic/b03.JPG",
        "attack": 576,
        "attributes": "無",
        "material": ["鐵礦石x15", "燕雀石x12", "大地的結晶x15"]
    },
    {
        "title": "斬破刀",
        "image": "http://terryyamg.3eeweb.com/test/pic/b04.JPG",
        "attack": 624,
        "attributes": "雷:250",
        "material": ["燕雀石x18", "大地的結晶x30", "電氣袋x3"]
    },
    {
        "title": "鬼斬破",
        "image": "http://terryyamg.3eeweb.com/test/pic/b05.JPG",
        "attack": 672,
        "attributes": "雷:380",
        "material": ["輝龍石x5", "燕雀石x20", "電氣袋x5"]
    },
    {
        "title": "鬼神斬破刀",
        "image": "http://terryyamg.3eeweb.com/test/pic/b06.JPG",
        "attack": 768,
        "attributes": "雷:490",
        "material": ["輝龍石x8", "靈鶴石x24", "電龍帶肉肋骨x2"]
    },
    {
        "title": "鬼神斬破刀【極】",
        "image": "http://terryyamg.3eeweb.com/test/pic/b07.JPG",
        "attack": 912,
        "attributes": "雷:620",
        "material": ["白鳩石x14", "電龍霜降肉x4", "祖龍角x1"]
    },
    {
        "title": "鐵刀【冰刃】",
        "image": "http://terryyamg.3eeweb.com/test/pic/b08.JPG",
        "attack": 528,
        "attributes": "冰:100",
        "material": ["鐵礦石x20", "冰結晶x12", "燕雀石x2"]
    },
    {
        "title": "白猿薙",
        "image": "http://terryyamg.3eeweb.com/test/pic/b09.JPG",
        "attack": 576,
        "attributes": "冰:150",
        "material": ["雪獅子的毛x6","鐵礦石x5","冰結晶x8"]
    },
    {
        "title": "白猿薙【中級】",
        "image": "http://terryyamg.3eeweb.com/test/pic/b10.JPG",
        "attack": 672,
        "attributes": "冰:250",
        "material": ["雪獅子王牙x3","雪獅子王的鬍鬚x5","冰結晶x20"]
    },
    {
        "title": "白猿薙【高級】",
        "image": "http://terryyamg.3eeweb.com/test/pic/b11.JPG",
        "attack": 864,
        "attributes": "冰:350",
        "material": ["雪獅子王的利牙x5","雪獅子的剛毛x8","雪獅子王尾x6"]
    },
    {
       "title": "白猿薙【驚嘆】",
        "image": "http://terryyamg.3eeweb.com/test/pic/b12.JPG",
        "attack": 1008,
        "attributes": "冰:560",
        "material": ["牙獸種的重牙x5","草食種的上皮x18","冰冷袋x3"]
    }]


3.AndroidManifest.xml先加入
uses-permission android:name="android.permission.INTERNET"

android:name=".AppController"


    
    

    
    

    
        
            
                
                

                
                
            
        
    


4./res/layout/activity_main.xml 主頁面放入ListView


    
    


5./res/layout/list.xml 建立客製化ListView項目


    
    

    

        
        

        

            
            

            
            
        

        
        
    




先建立AppControllerJsonArrayPostRequestLruBitmapCache三個檔案,此三個檔案不需要進行修改

6.AppController.java
package tw.android;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;

import android.app.Application;
import android.text.TextUtils;
import android.util.Log;


public class AppController extends Application {

 public static final String TAG = AppController.class.getSimpleName();

 private RequestQueue mRequestQueue;
 private ImageLoader mImageLoader;

 private static AppController mInstance;

 @Override
 public void onCreate() {
  super.onCreate();
  mInstance = this;
  Log.i("mInstance.this", mInstance+"");
 }

 public static synchronized AppController getInstance() {
  return mInstance;
 }

 public RequestQueue getRequestQueue() {
  if (mRequestQueue == null) {
   mRequestQueue = Volley.newRequestQueue(getApplicationContext());
  }
  return mRequestQueue;
 }

 public ImageLoader getImageLoader() {
  getRequestQueue();
  if (mImageLoader == null) {
   mImageLoader = new ImageLoader(this.mRequestQueue,
     new LruBitmapCache());
  }
  return this.mImageLoader;
 }

 public <T> void addToRequestQueue(Request<T> req, String tag) {
  // set the default tag if tag is empty
  req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
  getRequestQueue().add(req);
 }

 public <T> void addToRequestQueue(Request<T> req) {
  req.setTag(TAG);
  getRequestQueue().add(req);
 }

 public void cancelPendingRequests(Object tag) {
  if (mRequestQueue != null) {
   mRequestQueue.cancelAll(tag);
  }
 }
}
7.JsonArrayPostRequest.java 編碼
package tw.android;

import java.io.UnsupportedEncodingException;

import org.json.JSONArray;
import org.json.JSONException;

import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.toolbox.HttpHeaderParser;

public class JsonArrayPostRequest extends Request<JSONArray> {

    private Response.Listener<JSONArray> mListener;
    public JsonArrayPostRequest(String url, Response.Listener<JSONArray> listener,
                                Response.ErrorListener errorListener){
        super(Method.GET, url, errorListener);
        mListener = listener;
    }

    @Override
    protected Response<JSONArray> parseNetworkResponse(NetworkResponse response) {
        try {

         /*utf-8 編碼 否則中文會出現亂碼*/
            String jsonString = new String(response.data, "UTF-8");
            return Response.success(new JSONArray(jsonString),
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e){
            return Response.error(new ParseError(e));
        } catch (JSONException je){
            return Response.error(new ParseError(je));
        }
    }
    @Override
    protected void deliverResponse(JSONArray response) {
        mListener.onResponse(response);
    }
}
8.LruBitmapCache.java 緩衝
package tw.android;

import android.graphics.Bitmap;
import android.support.v4.util.LruCache;

import com.android.volley.toolbox.ImageLoader.ImageCache;

/*緩衝*/
public class LruBitmapCache extends LruCache<String, Bitmap> implements
  ImageCache {
 public static int getDefaultLruCacheSize() {
  final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
  final int cacheSize = maxMemory / 8;

  return cacheSize;
 }

 public LruBitmapCache() {
  this(getDefaultLruCacheSize());
 }

 public LruBitmapCache(int sizeInKiloBytes) {
  super(sizeInKiloBytes);
 }

 @Override
 protected int sizeOf(String key, Bitmap value) {
  return value.getRowBytes() * value.getHeight() / 1024;
 }

 public Bitmap getBitmap(String url) {
  return get(url);
 }

 public void putBitmap(String url, Bitmap bitmap) {
  put(url, bitmap);
 }
}



再建立符合自己需要的清單
9.ListItem.java 清單資訊
package tw.android;

import java.util.ArrayList;

public class ListItem {

 private String title, thumbnailUrl,attributes;
 private int attack;
 private ArrayList material;

 public ListItem() {
 }

 public ListItem(String name, String thumbnailUrl, int attack, String attributes,
   ArrayList material) {
  this.title = name;
  this.thumbnailUrl = thumbnailUrl;
  this.attack = attack;
  this.attributes = attributes;
  this.material = material;
 }

 /* 名稱 */
 public String getTitle() {
  return title;
 }

 public void setTitle(String name) {
  this.title = name;
 }

 /* 縮圖 */
 public String getThumbnailUrl() {
  return thumbnailUrl;
 }

 public void setThumbnailUrl(String thumbnailUrl) {
  this.thumbnailUrl = thumbnailUrl;
 }

 /* 攻擊力 */
 public int getAttack() {
  return attack;
 }

 public void setAttack(int attack) {
  this.attack = attack;
 }

 /* 屬性 */
 public String getAttributes() {
  return attributes;
 }

 public void setAttributes(String attributes) {
  this.attributes = attributes;
 }

 /* 材料 */
 public ArrayList getMaterial() {
  return material;
 }

 public void setMaterial(ArrayList material) {
  this.material = material;
 }

}

10.CustomListAdapter.java 建立listview項目清單
package tw.android;

import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.NetworkImageView;

public class CustomListAdapter extends BaseAdapter {
 private Activity activity;
 private LayoutInflater inflater;
 private List items;
 ImageLoader imageLoader = AppController.getInstance().getImageLoader();

 public CustomListAdapter(Activity activity, List items) {
  this.activity = activity;
  this.items = items;
 }

 public int getCount() {
  return items.size();
 }

 public Object getItem(int location) {
  return items.get(location);
 }

 public long getItemId(int position) {
  return position;
 }

 public View getView(int position, View convertView, ViewGroup parent) {

  if (inflater == null)
   inflater = (LayoutInflater) activity
     .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  if (convertView == null)
   convertView = inflater.inflate(R.layout.list, null);

  if (imageLoader == null)
   imageLoader = AppController.getInstance().getImageLoader();
  NetworkImageView thumbNail = (NetworkImageView) convertView
    .findViewById(R.id.thumbnail);
  TextView title = (TextView) convertView.findViewById(R.id.title);
  TextView attack = (TextView) convertView.findViewById(R.id.attack);
  TextView attributes = (TextView) convertView
    .findViewById(R.id.attributes);
  TextView material = (TextView) convertView.findViewById(R.id.material);

  // getting movie data for the row
  ListItem m = items.get(position);

  // 縮圖
  thumbNail.setImageUrl(m.getThumbnailUrl(), imageLoader);

  // 名稱
  title.setText(m.getTitle());

  // 攻擊力
  attack.setText("攻擊力: " + String.valueOf(m.getAttack()));

  // 屬性
  attributes.setText("屬性: " + m.getAttributes());

  // 材料
  String materialStr = "";
  for (String str : m.getMaterial()) {
   materialStr += str + ", ";
  }
  materialStr = materialStr.length() > 0 ? materialStr.substring(0,
    materialStr.length() - 2) : materialStr;
  material.setText(materialStr);

  return convertView;
 }

}

11.MainActivity.java 主頁面
package tw.android;

import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;

import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.VolleyLog;

public class MainActivity extends Activity {// Log tag
 private static final String TAG = MainActivity.class.getSimpleName();

 // json檔案位置
 private static final String url = "http://terryyamg.3eeweb.com/test/list.json";

 private List listItem = new ArrayList();
 private ListView listView;
 private CustomListAdapter adapter;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  listView = (ListView) findViewById(R.id.list);
  adapter = new CustomListAdapter(this, listItem);
  listView.setAdapter(adapter); 
  
  // 取得資料並編碼
  JsonArrayPostRequest itemReq = new JsonArrayPostRequest(url,
    new Response.Listener() {

     public void onResponse(JSONArray response) {

      // 解析json
      for (int i = 0; i < response.length(); i++) {
       try {
        
        //取得回應物件
        JSONObject obj = response.getJSONObject(i);
        //取得對定標題並放入item內
        ListItem item = new ListItem();
        item.setTitle(obj.getString("title"));
        item.setThumbnailUrl(obj.getString("image"));
        item.setAttack(obj.getInt("attack"));
        item.setAttributes(obj.getString("attributes"));
        //多項目處理
        JSONArray materialArry = obj
          .getJSONArray("material");
        ArrayList material = new ArrayList();
        for (int j = 0; j < materialArry.length(); j++) {
         material.add((String) materialArry.get(j));
        }
        item.setMaterial(material);

        // 將所有項目item放入listItem陣列
        listItem.add(item);

       } catch (JSONException e) {
        e.printStackTrace();
       }

      }

      // 更新adapter數據
      adapter.notifyDataSetChanged();
     }
     
     
    }, new Response.ErrorListener() {

     public void onErrorResponse(VolleyError error) {
      VolleyLog.d(TAG, "Error: " + error.getMessage());

     }
    });

  // 使用AppController內的排序
  AppController.getInstance().addToRequestQueue(itemReq);
 }

 @Override
 public void onDestroy() {
  super.onDestroy();
 }



}

1.檔案下載:
https://github.com/terryyamg/CacheImageTest
 2.參考連結:
http://www.androidhive.info/2014/07/android-custom-listview-with-image-and-text-using-volley/
http://dnakreatif.com/programming/android-volley-jsonarray-post-with-params/
http://stackoverflow.com/questions/19267616/why-does-volleys-response-string-use-an-encoding-different-from-that-in-the-res

2015年7月5日 星期日

iOS Swift Time Format Compare 時間 格式 比較

Swift的時間格式化

1.ViewController.swift
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        //取得日期
        let date = NSDate()
        println(date) //原始
        var formatter = NSDateFormatter();
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss";
        let date2 = formatter.stringFromDate(date);
        
        println(date2) //格式為yyyy-MM-dd HH:mm:ss
        formatter.dateFormat = "yyyy/MM/dd";
        let date3 = formatter.stringFromDate(date);
        println(date3)//格式為yyyy/MM/dd

        //比較時間
        //現在時間
        let date = NSDate()
        let calendar = NSCalendar.currentCalendar()
        let components = calendar.components([.Month, .Day], fromDate: date) //只取月,日
        let dateNow = String(format: "%02d-%02d", components.month, components.day) //NSDate 轉 字串(格式 日-月)
        //自設時間
        let formatter = NSDateFormatter()
        formatter.dateFormat = "MM-dd" //日期格式
        formatter.timeZone = NSTimeZone(name: "UTC")
        let dateSet = "03-29" //自設時間
        
        let dateA = formatter.dateFromString(dateNow)! //字串 轉 NSDate
        let dateB = formatter.dateFromString(dateSet)! //字串 轉 NSDate
        print("DateA:\(dateA)")
        print("DateB:\(dateB)")
        // 比較
        switch dateA.compare(dateB) {
            case .OrderedAscending     :   print("Date A 比 date B 早")
            case .OrderedDescending    :   print("Date A 比 date B 晚")
            case .OrderedSame          :   print("同日")
        }

    }
}
參考來源:
http://www.brianjcoleman.com/tutorial-nsdate-in-swift/
http://iswift.org/cookbook/compare-2-dates

iOS Swift String Random 字串 亂數 亂碼

swift的隨機亂碼

1.FunctionHelper.swift
class FunctionHelper {

    // 產生亂碼 len-需要亂碼長度
    func randomString(len:Int) -> String {
        let charSet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
        var c = Array(charSet)
        var s:String = ""
        for n in (1...len) {
            s.append(c[Int(arc4random()) % c.count])
        }
        return s
    }
    
}

2.ViewController.swift
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        let funHelper = FunctionHelper()
        var number = funHelper.randomString(8) //取8位
        println("產生得亂碼:\(number)")
    }
}
參考來源:
https://gist.github.com/szhernovoy/276e69eb90a0de84dd90

2015年7月2日 星期四

iOS CocoaPods libs 安裝套件

1.iOS安裝套件的方法,簡單說就是要用終端機下指令裝一個叫做CocoaPods的軟體,然後用這個軟體在專案下建立一個Podfile檔案,在這個檔案裡面寫入要取得的套件名稱,再進行安裝指令就會自動下載,跟Android Studio的方式比較像,詳細步驟在http://code4app.com/article/cocoapods-install-usage有介紹。

ps:在安裝CocoaPods時要有root權限,開啟設定root請參閱https://support.apple.com/zh-tw/HT204012 "如何啟用 root 使用者" 詳細步驟

2.沒提到的問題,下載套件時可能會出現錯誤
 
[!] Pods written in Swift can only be integrated as frameworks; this feature is still in beta. Add `use_frameworks!` to your Podfile or target to opt into using it.

此時安裝不完全會造成.xcworkspace檔案與Podfile.lock檔案產生不出來

因此要在Podfile加入"use_frameworks!"就可以順利安裝

參考 
http://stackoverflow.com/questions/29091522/error-running-pod-install-with-swift

安裝完成點選出現的.xcworkspace檔案開啟就可以使用了!!讚!!!