2012-12-16

利用檢視原始碼了解在臉書上誰最關注你(妳)

網路上流傳一種用『檢視原始碼』就能知道誰最關注你(妳)的方法

我來給它實作看看:


步驟一:登入你()Facebook到個人首頁


步驟二:在空白處按右鍵,選取『檢視原始碼』




步驟三:搜尋『InitialChatFriendsList


步驟四:List後面一串一串的數字第一個就是最關注你()的人


步驟五:把此串數字加到後面”www.facebook.com/”放到網址上去就知道是誰了



實作的結果真的是我朋友沒錯,不過是不是最關注我的我就不知道了

反正好玩就好了,您說對不對!





2012-12-10

Android下拉選單(spinner)應用(五) - 更換字體大小、顏色

一般網路上都會教一些基本下拉選單(spinner),套用simple_spinner_dropdown_item或

simple_spinner_item這些基本模板,但有時想改變Spinner內的文字大小及顏色又不知從哪下手

今天就來教大家怎麼改變Spinner內的文字大小及顏色,當然也包含對齊方式

我用比較簡單的方法直接由Layout下手去修改Spinner內文字的字體大小及顏色

步驟一:

在res-->layout內新增一個myspinner.xml的android xml檔,貼上下列程式碼

myspinner.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ellipsize="marquee"
    android:gravity="center"
    android:paddingLeft="8dip"
    android:singleLine="true"
    android:textColor="#8B008B"
    android:textSize="32sp"
    android:textStyle="bold" >
</TextView>


步驟二:

回到java程式碼,假設我們已經在main.xml中加入一個下拉選單spinner1了

基本的下拉選單都是這樣寫的:
//將可選内容與ArrayAdapter連接起來 
adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item,Blood_group);
//對應控件
spinner = (Spinner) findViewById(R.id.spinner1);
//設置下拉列表的風格
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
//將adapter 添加到spinner中  
spinner.setAdapter(adapter); 

換成下面這個樣子:
//將可選内容與ArrayAdapter連接起來 
adapter = new ArrayAdapter<String>(this,R.layout.myspinner,Blood_group);
//對應控件
spinner = (Spinner) findViewById(R.id.spinner1);
//設置下拉列表的風格
adapter.setDropDownViewResource(R.layout.myspinner);
//將adapter 添加到spinner中  
spinner.setAdapter(adapter);


為什麼有兩個地方是要換成myspinner的呢?

因為adapter是代表內容(也就是下拉時)

setDropDownViewResource是代表靜止未點選下拉時的樣式(感謝網友指教)

setDropDownViewResource是代表點選下拉時彈出的樣式

執行後畫面



文字被我改為紫色、字體大小變32、置中對齊

這樣簡簡單單兩個步驟就能改變下拉選單的三種樣式設定了

以上介紹,謝謝各位!!

ps:貼上一些參數(spinner、adapter、Blood_group)的宣告,不然新手會對應不起來
private Spinner spinner;  
 private ArrayAdapter<String> adapter;  
 private static final String[] Blood_group={"A型","B型","O型","AB型","其他"};

2012-12-01

Android TextView應用(一) - 跑馬燈

一般的HTML有跑馬燈功能,那Android應用程式能否用跑馬燈功能呢?可以的!

只要用TextView文字列就可以做出跑馬燈功能了,今天來做的比較特別一點

就是我改用EditText輸入文字後,傳給TextView後做自輸入型的跑馬燈功能

先說一下我的開發環境吧,雖然沒什麼太大影響

我用的Android版本是4.0.3,作業系統是Window 7 64位元,eclipse當然也是for 64位元的

接下來就來看看程式碼吧!


main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/tv_ouput"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="15dp"
        android:textSize="30sp"
        android:singleLine="true"
        android:ellipsize="marquee"
        android:marqueeRepeatLimit="marquee_forever"
        android:focusableInTouchMode="true"
        android:focusable="true"
        android:text="@string/hello_world" />

    <EditText
        android:id="@+id/et_input"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tv_ouput"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="17dp"
        android:ems="10"
        android:hint="請輸入跑馬燈訊息..." >
    </EditText>

    <Button
        android:id="@+id/btn_submit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/et_input"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="28dp"
        android:text="@string/submit" />

</RelativeLayout>






TripleSpinnerActivity
package jim.demo.rundemo;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  final TextView tv=(TextView)findViewById(R.id.tv_ouput);
  
  
  final EditText et = (EditText)findViewById(R.id.et_input);
  
  Button btn = (Button)findViewById(R.id.btn_submit);
  btn.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    tv.setText(et.getText().toString());
    tv.setSelected(true);
   }
   
  });
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.activity_main, menu);
  return true;
 }

}


執行後畫面









說明:

1‧TextView在xml上說明如下:
//單行文本顯示,
android:singleLine="true"
//跑馬燈效果
android:ellipsize="marquee"
//重複次數的設定,默認是無窮次
android:marqueeRepeatLimit="marquee_forever"
//取得焦點,這是讓跑馬燈一開始就可以跑
android:focusableInTouchMode="true"
android:focusable="true"

2.Activity中只差在onClick中設定完文字後
需要用.setSelected(true);讓焦點回到TextView上

3.注意:輸入的文字必須大於TextView的寬度,跑馬燈才會動作
所以如果發現跑馬燈不動作,可以試著在XML中把android:layout_width改小

以上是為你做的說明,有問題歡迎提問,謝謝。

2012-11-06

Android下拉選單(spinner)應用(四) - 三層連動式下拉選單

因為很多人看完了上篇連動式下拉選單後開始問我怎麼再加一層做三層連動下拉選單

而三層下拉在很多地方都會用到,如:最常用到的縣市鄉鎮選取,所以就抽空寫這篇好了

本人用的是最白痴的寫法(因為我懶),其實還有其他寫法,不過這個寫法最快(最懶)

而且最直覺,就直接把二層連動下拉選單中的二維陣列再加一個三維陣列的而已

夠簡單也夠直覺吧(夠懶),下面就直接po程式碼,看完您就會覺得就這樣而已喔

其實也就是這麼簡單而已,我直接從連動式下拉選單改來的,看程式碼吧。

main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#FFFFFF"
    >
    <Spinner android:id="@+id/type" 
        android:layout_width="fill_parent" 
          android:layout_height="45dp"
          android:layout_marginLeft="75dp"
          android:layout_marginRight="20dp"
        android:layout_marginTop="7dp" 
         android:drawSelectorOnTop="true"
         android:layout_alignParentRight="true" 
    />
       <Spinner android:id="@+id/type2" 
        android:layout_width="fill_parent" 
          android:layout_height="45dp"
          android:layout_marginLeft="75dp"
          android:layout_marginRight="20dp"
          android:layout_marginTop="3dp" 
         android:drawSelectorOnTop="true"
         android:layout_alignParentRight="true" 
         android:layout_below="@id/type" 
         />


       <Spinner
           android:id="@+id/type3"
           android:layout_width="fill_parent"
           android:layout_height="45dp"
           android:layout_marginLeft="75dp"
           android:layout_marginRight="20dp"
           android:layout_marginTop="3dp"
           android:drawSelectorOnTop="true"
           android:layout_alignParentRight="true"
           android:layout_below="@+id/type2" />
      
</RelativeLayout>



TripleSpinnerActivity
package jim.demo.TripleSpinner;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.AdapterView.OnItemSelectedListener;

public class TripleSpinnerActivity extends Activity {
 private String[] type = new String[] {"茶類", "果汁類"};//載入第一下拉選單
    private String[] tea = new String[]{"紅茶","綠茶","烏龍綠","青茶"};//起始畫面時預先載入第二下拉選單
    private String[] tea2 = new String[]{"紅茶超好喝","紅茶喝完臉會紅"};//起始畫面時預先載入第三下拉選單
    //第一下拉選取後載入第二下拉選單
    private String[][] type2 = new String[][]{{"紅茶","綠茶","烏龍綠","青茶"},{"柳丁汁","西瓜汁","烏梅汁"}};
    //第二下拉選取後載入第三下拉選單
    private String[][][] type3 = new String[][][]{{{"紅茶超好喝","紅茶喝完臉會紅"},{"綠茶超好喝","綠茶喝完臉會綠"},{"烏龍茶超好喝","烏龍茶超烏龍"},{"青茶超好喝","青茶很尚青"}},{{"柳丁汁超好喝","柳丁汁好棒"},{"西瓜汁超好喝","西瓜汁還可以"},{"烏梅汁超好喝","烏梅汁還可以"}}};
    private Spinner sp;//第一個下拉選單
    private Spinner sp2;//第二個下拉選單
    private Spinner sp3;//第三個下拉選單
    private Context context;

    ArrayAdapter<String> adapter ;

    ArrayAdapter<String> adapter2; 
    
    ArrayAdapter<String> adapter3; 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
         context = this;
        
        //程式剛啟始時載入第一個下拉選單
        adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, type); 
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
        sp = (Spinner) findViewById(R.id.type); 
        sp.setAdapter(adapter);
        sp.setOnItemSelectedListener(selectListener);
        
        //因為下拉選單第一個為茶類,所以先載入茶類群組進第二個下拉選單
        adapter2 = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, tea); 
        adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
        sp2 = (Spinner) findViewById(R.id.type2);
        sp2.setAdapter(adapter2);
        sp2.setOnItemSelectedListener(selectListener2);
        
      //因為下拉選單第二個為紅茶,所以先載入紅茶群組進第三個下拉選單
        adapter3 = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, tea2); 
        adapter3.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
        sp3 = (Spinner) findViewById(R.id.type3);
        sp3.setAdapter(adapter3);
        
    }
    
    //第一個下拉類別的監看式
    private OnItemSelectedListener selectListener = new OnItemSelectedListener(){
        public void onItemSelected(AdapterView<?> parent, View v, int position,long id){
         //讀取第一個下拉選單是選擇第幾個
            int pos = sp.getSelectedItemPosition();
            //重新產生新的Adapter,用的是二維陣列type2[pos]
            adapter2 = new ArrayAdapter<String>(context,android.R.layout.simple_spinner_item, type2[pos]);
            //載入第二個下拉選單Spinner
            sp2.setAdapter(adapter2);
        }
      
        public void onNothingSelected(AdapterView<?> arg0){

        }

    };
    
  //第二個下拉類別的監看式
    private OnItemSelectedListener selectListener2 = new OnItemSelectedListener(){
        public void onItemSelected(AdapterView<?> parent, View v, int position,long id){
         //讀取第一個下拉選單是選擇第幾個
            int pos = sp.getSelectedItemPosition();
         //讀取第二個下拉選單是選擇第幾個
            int pos2 = sp2.getSelectedItemPosition();
            //重新產生新的Adapter,用的是三維陣列type3[pos][pos2]
            adapter3 = new ArrayAdapter<String>(context,android.R.layout.simple_spinner_item, type3[pos][pos2]);
            //載入第三個下拉選單Spinner
            sp3.setAdapter(adapter3);
        }
      
        public void onNothingSelected(AdapterView<?> arg0){

        }

    };
}



執行後畫面


選取第二個下拉選單

點選後第二個下拉和第三個下拉選單改變

第三個下拉選單內容也改變了

第一個下拉選單改變會連動其他二個下拉選單改變

說明:
          1.和連動式下拉選單其實改變的沒有很多,只是加入一個Spineer和一個三維陣列

          2.主要的內容要照著三維陣列內的設定,第一個下拉是類別、第二個下拉是品項

             、第三個下拉是評價,所以一開始下拉選單內的預設值因為第一個下拉的類別

             會預設為茶類,而第二下拉會是紅茶,所以第三個下拉就給它一維陣列紅茶的評價

          3.新增的第二個下拉選單選取監看式,new ArrayAdapter<String>產出的是一維陣列

             括號逗點前第一區只是下拉的樣式,所以不用管它,第二區帶入三維陣列

             給三維陣列type3第一和第二下拉的選取項就會產出一維陣列選項讓ArrayAdapter載入

             Spineer3中。

後記:

           以上說明應該清楚了,如有問題歡迎來信指教,謝謝。

2012-10-10

PhoneGap到底是什麼?

最近在忙著幫公司做表單電子化,一個月(11月前)要把兩個表單(外出申請單、忘刷卡單)電子化

忙到我都忘了我有blog這件事了<---有點虎爛!!

今天完成一個表單後為了有在focus我的blog的朋友們

所以今天特別上來寫了這一篇文章<---因為也有人在問!

讓不是很了解PhoneGap的人能再更了解PhoneGap到底是什麼玩意兒?

PhoneGap到底是什麼?是Mobile App?IPhone?App?HTML5?

還有人說是手機應用程式,PhoneGap到底是什麼?

用最簡單再簡單,簡單到一句話就說完的說法就是:

PhoneGap是網頁(HTML5、CSS3)和手機底層功能的中介溝通層套件

請把這句話表框起來,然後放到你的腦海深處不要忘記了

為什麼說它是中介層套件,下面開始為你說明你就會了解:

我們都知道手機應用程式開發分為兩種:Native App和Mobile App

Native App是用原生程式碼,如Android用Java、iPhone用ObjectC...等

Mobile App是用HTML5+手機瀏覽器

Native App我就不廢話直接跳過了

我們針對Mobile App來說明為什麼PhoneGap是Mobile App開發的一個中介溝通層套件

所有的手機應用程式都是APP(廢話),APP 就會需要封裝,這樣才好各別下載(好免費分享...誤)

而PhoneGap也不是開發APP的工具,因為以開發Android是用Eclipse

Eclipse才是開發工具,PhoneGap只能算是開發中的一個套件

而Mobile App有一個大缺點,就是雖然網頁有共通性,不過只要用到手機瀏覽器

手機上的功能你就完全不能用,就算手機能發出七彩霓虹燈、一秒內打電話給林志玲或如花

你也不能用,這是Mobile App最大的缺點,那你會問這跟PhoneGap有什麼關係

怎麼會沒關係,PhoneGap就是在改善這一點的中介溝通層套件(終於說到了!)

在HTML5中用寫JavaScrip的型式就能去呼叫手機內建的功能

這樣你說有沒有很帥,雖然它也不是萬能的,不過最少能加減用點功能也好

以上說明應該夠清楚了,希望不會再有人看完這篇還不知道PhoneGap是什麼?能吃嗎?才好!

最後還是不了解的歡迎寫信問題,我再幫您加強說明,謝謝。

PS:如果以上有錯誤的地方,小弟我也歡迎指教,教學相長,我會很感謝您的。

2012-09-04

PhoneGap API應用:Camera相機(二) - 選取手機內照片用img顯示出來

上篇-用相機拍照後,這篇就不得不說說怎麼從手機內取出照片了

鬼月廢話還是不要太多,不然別人會覺得我是在"鬼話連篇",直接PO上程式碼


JavaScript程式碼
<script type="text/javascript" charset="utf-8" src="phonegap-1.0.0.js"></script>
<script type="text/javascript" charset="utf-8">
       
      var pictureSource;   //圖片的來源
    var destinationType;  //返回值的格式設置

    // Wait for PhoneGap to connect with the device
    document.addEventListener("deviceready",onDeviceReady,false);

    // PhoneGap 剛onload時
    function onDeviceReady() {
        pictureSource=navigator.camera.PictureSourceType;
        destinationType=navigator.camera.DestinationType;
    }
//一個按鈕將調用這個函數
//Android的怪癖:pictureSource.PHOTOLIBRARY和pictureSource.SAVEDPHOTOALBUM是相同的
//所以點選getPhoto(pictureSource.PHOTOLIBRARY)
//或是getPhoto(pictureSource.SAVEDPHOTOALBUM)功能是相同的
    function getPhoto(source) {
      // 取得圖像(成功事件 ,失敗事件,{圖片設定});
      // getpicture(cameraSuccess,cameraError,{cameraOptions});
      navigator.camera.getPicture(onPhotoURISuccess, onFail, { quality: 50, 
        destinationType: destinationType.FILE_URI,
        sourceType: source });
    }
//照片是成功檢索時調用
    function onPhotoURISuccess(imageURI) {
      //取消註釋,以查看base64編碼的圖像數據
      // console.log(imageURI);

      //獲取的圖像處理
      var largeImage = document.getElementById('largeImage');

      //取消隱藏的圖像元素
      largeImage.style.display = 'block';

      //顯示取得的照片
      // The inline CSS rules are used to resize the image
      largeImage.src = imageURI;
    }

    //錯誤發生時 
    function onFail(message) {
      alert('Failed because: ' + message);
    }

      </script>



html元件
<button onclick="getPhoto(pictureSource.PHOTOLIBRARY);">從相片的檔案庫</button><br>
<button onclick="getPhoto(pictureSource.SAVEDPHOTOALBUM);">從相片簿</button><br>
<img style="display:none;width:60px;height:60px;" id="largeImage" src="" />


實作出來的畫面:






說明:

雖然有兩個功能按鈕可以作出這個功能,而且帶入的參數不同

但其實做出來的功能是一樣的,原因是Android的怪癖

Camera.PictureSourceType.PHOTOLIBRARY和PictureSourceType.SAVEDPHOTOALBUM

會被視為相同,都會都出現相同的相冊,官網說明文件中有提到

以上是為您做的簡單介紹,謝謝。

2012-08-29

PhoneGap API應用:Camera相機(一) - 用相機拍照後用img顯示出來

最近因為比較忙一些專案,所以比較沒空寫blog文章

因為之前寫Native App(原生應用程式)比較多,Mobile App的部份相對的就比較少

所以今後會先寫一幾篇Mobile App,Android的開發是很廣泛的,不限定一定要用

怎樣的方式開發,像電子報來說,你可以用Native的方式開發,也能用PhoneGap

的Mobile app方式開發,這都是可行的,所以開發是沒有一定的形式,在於使用

者和設計者的喜好和習慣,這兩種開發方式都有其優缺點,優缺點我在這裡有介紹

過了,各位可以參考,好!以上是我的完全和本文無關的碎碎唸,系列文章第一篇的

廢話都是比較多的請見諒,接下來進入主題。

我會針對PhoneGap API的各大項API做各別應用上的大略介紹,實際在開發上各位還

是要針對需求做自我轉變,我不可能都猜到各位實際開發上會怎麼使用它,如果都猜

得到,我就改行當算命的了XD(誤)。

如果建立、安裝及設定Phonegap因為之前我就有介紹過了PhoneGap安裝,所以之後系列

應用上就都直接貼上程式碼,不再重覆介紹了,請見諒!,直接PO上JavaScript程式碼再來說明。


JavaScript程式碼
<script type="text/javascript" charset="utf-8">
       
       //功用和onload相同
       document.addEventListener("deviceready", onDeviceReady, false);
    
    function onDeviceReady() {
        // Empty
    }
 //一個按鈕將調用這個函數
    function capturePhoto() {
       // 取得圖像(成功事件 ,失敗事件,{圖片設定});
      // getpicture(cameraSuccess,cameraError,{cameraOptions});
      navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 50 });
    }
    //照片是成功檢索時調用
    function onPhotoDataSuccess(imageData) {
      //取消註釋,以查看base64編碼的圖像數據
      // console.log(imageData);

      //獲取的圖像處理
      var smallImage = document.getElementById('smallImage');

      //取消隱藏的圖像元素
      smallImage.style.display = 'block';

      //顯示拍攝的照片
      //內聯 CSS規則是用來調整圖像的大小
      smallImage.src = "data:image/jpeg;base64," + imageData;
    }

    //錯誤發生時 
    function onFail(message) {
      alert('Failed because: ' + message);
    }
      </script>


html元件
<button onclick="capturePhoto();">Capture Photo</button>
<img style="display:none;width:60px;height:60px;" id="smallImage" src="" />


實作出來的畫面:

跳出來的選取相機和Native中的使用其他服務幫忙拍照類似


拍照後,圖片就直接出現在img內



說明:

看得懂JavaScript的應該自己看程式碼就知道了,全部的重點就是
navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 50 });

再來就是顯示圖片 smallImage.src = "data:image/jpeg;base64," + imageData;

以上是為您做的簡單介紹,謝謝。


2012-08-20

Android Adapter家族系列(三) - BaseAdapter

今天介紹Adapter家族內一個本人還蠻常用到的子類別BaseAdapter

幾乎元件在使用自定義的方式呈現時最常出現的一個子類別

因為自定義的view是自由設定的,所以不能像ArrayAdapter只是單純

只帶入資料而已,必須對view內的元件也做設定及加入事件等

也就是說主要的Activity只是建構此子類別,帶入相關需要的參數

其他的自定義view元件想要怎麼加、想要怎麼設定、做什麼事

都是在BaseAdapter內做設定就可以了,這樣說應該聽了還是霧煞煞

我們用實際的程式碼來邊做邊說明好了。

這裡我們用自定義的ListView來做說明:

ListView listView01 = (ListView)findViewById(R.id.listView1); 
     CharSequence[] list = MemorandumDate;
     CharSequence[] list2 = MemorandumNote;
     CharSequence[] list3 = MemorandumPW;
     BaseAdapter adapter = new MyAdapter(this, list, mID, list2, list3, mreminder);  
     listView01.setAdapter(adapter);

說明:
在主要的Activity中,找到ListView元件,然後我們建構一個適配器adapter

CharSequence[]是字元陣列,用來儲存文字用的,我同時在其他地方有宣告三個字元陣列

(list、list2、list3),也分別給於其值(此部份請自己依所需撰寫)及兩個整數陣列(mID、mreminder)

帶入建構子中建構該元件後帶入ListView,要帶入什麼參數和參數的順序是依照規劃MyAdapter這個

BaseAdapter子類別時怎麼開的,這裡就會是需要什麼樣的參數和順序,下面貼出MyAdapter的程式碼。


package jim.memorandum;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class MyAdapter extends BaseAdapter{  
 public LayoutInflater myInflater;
 public Context context;
    CharSequence[] mDate = null;
    CharSequence[] mData = null;
    CharSequence[] mPw = null;
    int[] MID = null;
    int[] mreminder = null;
    
    public MyAdapter(Context ctxt, CharSequence[] mdate,int[] mID,CharSequence[] mdata,CharSequence[] mpw,int[] mreminder){
        myInflater = LayoutInflater.from(ctxt);
        this.mDate = mdate;
        this.MID = mID;
        this.mData = mdata;
        this.context = ctxt;
        this.mPw = mpw;
        this.mreminder = mreminder;
    }

 public int getCount() {
  // TODO Auto-generated method stub
  return MID.length;
 }

 public Object getItem(int position) {
  // TODO Auto-generated method stub
  return MID[position];
 }

 public long getItemId(int position) {
  // TODO Auto-generated method stub
  return position;
 }

 public View getView(int position, View convertView, ViewGroup parent) {
  final int index = position;
         
  ViewTag viewTag;
        
        if(convertView == null){
            
            convertView = myInflater.inflate(R.layout.list_data, null);
            
           
            viewTag = new ViewTag(
                    (TextView)convertView.findViewById(R.id.tv_Date),
                    (TextView)convertView.findViewById(R.id.tv_Data),
                    (ImageButton)convertView.findViewById(R.id.ibtn_edit),
                    (ImageButton)convertView.findViewById(R.id.ibtn_del),
                    (ImageView)convertView.findViewById(R.id.img_remind),
                    (ImageView)convertView.findViewById(R.id.img_lock)
                    );
            
            convertView.setTag(viewTag);
        }
        else{
            viewTag = (ViewTag) convertView.getTag();
        }
        
        //如果有設定密碼就只顯示前五個字
        String stitle =""; 
        if(!mPw[position].toString().equalsIgnoreCase("")){
         stitle = mData[position].toString();
         if(stitle.length() &gt; 3){
         stitle = stitle.subSequence(0, 3) + "...";
         }
         else
         {
          stitle = mData[position].toString();
         }
        }
        else
        {
         stitle = mData[position].toString();
        }
        
        viewTag.tvdata.setText(stitle);
        viewTag.tvdate.setText(mDate[position].toString());    
        
        //提醒
        if(mreminder[index] == 1)
        {
           viewTag.img_reminder.setImageResource(R.drawable.checkbox_on);
        }
        else
        {
          viewTag.img_reminder.setImageResource(R.drawable.checkbox_off);
        }
           
       
        //是否有密碼
        if(!mPw[index].toString().equalsIgnoreCase(""))
        {
           viewTag.img_lock.setImageResource(R.drawable.lock_on);
        }
        else
        {
          viewTag.img_lock.setImageResource(R.drawable.lock_off);
        }
        
        
        //修改按鈕
        final ImageButton btn_edit = (ImageButton) convertView.findViewById(R.id.ibtn_edit);
        btn_edit.setOnClickListener(new View.OnClickListener()  {
          public void onClick(View v)  {
         
         //有密碼時必須輸入密碼
         if(!mPw[index].toString().equalsIgnoreCase(""))
         {
          LayoutInflater factory=LayoutInflater.from(context);
           //得到自定義對話框
                final View DialogView=factory.inflate(R.layout.dialog, null);
                
                AlertDialog.Builder builder = new AlertDialog.Builder(context);
                builder.setTitle("請輸入密碼");
                builder.setCancelable(false);
                builder.setView(DialogView); //設置自定義對話框樣式
             builder.setPositiveButton("送出", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                       try
                         {
                            EditText pw = (EditText)DialogView.findViewById(R.id.pw_dialog);//輸入之密碼
                            //驗證密碼是否相同
                            String sPW1 = mPw[index].toString();//原密碼
                            String sPW2 = pw.getText().toString();//驗證密碼
                            if(sPW1.equals(sPW2))
                            {
                             //相同就進入 
                                Intent intent_request = new Intent(context, Edit.class);
                                String val=String.valueOf(MID[index]);
                                intent_request.putExtra("val", val); 
                                context.startActivity(intent_request);    
                              
                            }else
                            {
                             //不相同時顯示密碼錯誤
                                Toast.makeText(context,"密碼錯誤!", Toast.LENGTH_SHORT).show(); 
                            }                   
                          }catch(Exception e)
                          {
                             e.printStackTrace();
                          }
                  }
             });
             
             builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
              public void onClick(DialogInterface dialog, int id) {
              }
             });  
                
             AlertDialog alert = builder.create();
             alert.show();
             
         }else
         {
          Intent intent_request = new Intent(context, Edit.class);
             String val=String.valueOf(MID[index]);
             intent_request.putExtra("val", val); 
                context.startActivity(intent_request);
         }
          }
        });
        
        //刪除按鈕
        final ImageButton btn_del = (ImageButton) convertView.findViewById(R.id.ibtn_del);
        btn_del.setTag(position);
        btn_del.setOnClickListener(new View.OnClickListener()  {
         
          public void onClick(View v)  {
           AlertDialog.Builder builder = new AlertDialog.Builder(context);
           
           builder.setMessage("確定要刪除?");
           builder.setCancelable(false);
           
           builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int dialog_id) {
           SQLiteDatabase db;
           NewListDataSQL helper = new NewListDataSQL(context, "MemorandumSQL");
           db = helper.getReadableDatabase();
           long long1 = db.delete("newMemorandum", "_ID=" + MID[index], null);               
        //添加成功後返回行號,失敗後返回-1
      if (long1 == -1) {
       Toast.makeText(context,
         "刪除失敗!", Toast.LENGTH_SHORT)
         .show();
      } else {
       Intent intent = new Intent(context, MemorandumActivity.class);
                context.startActivity(intent);
                quit();//關閉,讓back鍵不會出現上一頁
      }
    
                }
            });
           builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
          public void onClick(DialogInterface dialog, int id) {
          }
         });   
         
         AlertDialog alert = builder.create();
         alert.show();
          }
        });
        
        return convertView;
 }
   
    public class ViewTag{
     TextView tvdate;
        TextView tvdata;
        ImageButton ibtnEdit;
        ImageButton ibtnDel;
        ImageView img_reminder;
        ImageView img_lock;
        
        public ViewTag(TextView date, TextView data, ImageButton edit, ImageButton del, ImageView img1, ImageView img2){
            this.tvdate = date;
            this.tvdata = data;
            this.ibtnEdit = edit;
            this.ibtnDel = del;
            this.img_reminder = img1;
            this.img_lock = img2;
            
        }
    }
    
    public void quit() {
        int pid = android.os.Process.myPid();
        android.os.Process.killProcess(pid);
        System.exit(0);
    }
    
}


說明:
1.MyAdapter是繼承自BaseAdapter這個子類別

2.LayoutInflater myInflater 指的是一種擴充,就是說如果你想用自定的XML配置檔

可以用此擴充把自定的XML置檔加入到現有元件中

3.Activity在建構此類別時,需要帶入什麼參數是在MyAdapter 內設定的
如果這個也不了解請麻煩去翻一下物件導向書籍

4.重點在getView內,所有的自定介面設定、處理都在getView內產生及設定、處理

5.有使用一個viewTag的元件設定類別,要告訴介面自定義的XML內有哪些元件配置


貼出自定義的XML配置檔,讓各位更了解崁在ListView內的是怎麼配置的

list_data.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:descendantFocusability="blocksDescendants"
    android:background="@drawable/button_style" >

    <RelativeLayout
        android:id="@+id/relativeLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >


        <TextView
            android:id="@+id/tv_Date"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textSize="20dp" />
        
        
        <ImageView
        android:id="@+id/img_lock"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@+id/img_remind"
        android:layout_alignParentTop="true"
        android:contentDescription="@string/password"
        />
        
        
        <ImageView
        android:id="@+id/img_remind"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@+id/ibtn_edit"
        android:layout_alignParentTop="true"
        android:contentDescription="@string/remind"
        />
        

        <ImageButton
            android:id="@+id/ibtn_del"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:src="@android:drawable/ic_menu_delete"
            android:contentDescription="@string/del" />


        <ImageButton
            android:id="@+id/ibtn_edit"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_alignParentTop="true"
            android:layout_toLeftOf="@+id/ibtn_del"
            android:src="@android:drawable/ic_menu_edit"
            android:contentDescription="@string/edit" />

    </RelativeLayout>

    <TextView
        android:id="@+id/tv_Data"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:singleLine="true"
        android:textAppearance="?android:attr/textAppearanceLarge" />

</LinearLayout>


實際圖型:



後記:
這個是ListView中的自定義圖型,當然這是有美化過的,所以看起來才會有點不一樣

不過如果你想要做到像這個樣子,就一定要用BaseAdapter,然後套用自定義XML配置檔list_data.xml

不然是做不出這樣很自由的變化配置的,以上介紹,謝謝。

2012-08-12

Android Adapter家族系列(二) - ArrayAdapter

這次開始介紹Adapter的各子類別,因為怕太過深入會不容易了解,所以介紹各子類時

都只介紹一些比較基本的應用,如果有想更深入了解的人可以參考官網上面的介紹

ArrayAdapter上面有很完整的說明,謝謝。


我拿ArrayAdapter來橋接Spinner(下拉選單)做為介紹

直接帶入陣列當資料

//定義adapter為ArrayAdapter
ArrayAdapter<String> adapter ;

//建立陣列
private String[] type = new String[] {"茶類", "果汁類"};

//物件化
android.widget.ArrayAdapter.ArrayAdapter<string>(Context context, int textViewResourceId, String[] objects)
//上面是原式,textViewResourceId是下拉選單的樣式

adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, type); 

//設定下拉選單點選後出現選單的樣式,使用的是內建預設樣式
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 

//下拉選單
private Spinner sp;

sp = (Spinner) findViewById(R.id.type); 

sp.setAdapter(adapter);


重點:
可能你會發現ArrayAdapter在物件化時,有一個樣式textViewResourceId,
然後setDropDownViewResource又再設定一個樣式,為什麼呢?
因為textViewResourceId指的是下拉選單還未點選時的下拉選單樣式
而setDropDownViewResource設定的是點選下拉選單後跳出選單的樣式
這兩者是不一樣的,這樣說各位應該還是一頭霧水,我用圖片說明好了

new物件時樣式用simple_spinner_item

new物件時樣式用simple_spinner_dropdown_item


setDropDownViewResource物件時樣式用simple_spinner_item

setDropDownViewResource物件時樣式用simple_spinner_dropdown_item

有看清楚了嗎?new物件時textViewResourceId的樣式設定指的是下拉選單出現時的樣式
setDropDownViewResource指的是彈出下拉選單時,出現列表的樣式,此兩者是不同的
當然這兩者也都能使用自定義的佈局XML,只要自己新增一個XML,然後就能在textViewResourceId或setDropDownViewResource裡面選取,選單內的樣式也會跟著改變
以上是為你做ArrayAdapter的簡單介紹,謝謝。

2012-08-10

Android Adapter家族系列(一) - Adapter(適配器)

Adapter(適配器)  官方網站上有對它的一些類別概述:
適配器對象作為AdapterView之間的一個橋樑,並為這一觀點的基礎數據。適配器提供的數據項的訪問。適配器也作出負責的數據集給每個項目。

簡單的來說就是資料和元件間溝通的橋樑,Adapter有以下幾種間接子類別:
ArrayAdapterBaseAdapterCursorAdapterHeaderViewListAdapterListAdapterResourceCursorAdapterSimpleAdapter,SimpleCursorAdapterSpinnerAdapterWrapperListAdapter
這些子類別我們在後續章節再做各別的介紹。

我們常會在ListView、Spinner...等看到這一類別,而且也必須使用到它
我們就來看它常用的公用方法:


getCount ()

How many items are in the data set represented by this Adapter.
適配器內的資料個數

程式碼
public  int getCount() {
   return title.length;
}


GetItem (位置)


Get the data item associated with the specified position in the data set.
獲取的數據在指定位置的數據集相關的項目。


程式碼
public Object getItem(int position) {
  return title[position];
}


getItemId (int position)



Get the row id associated with the specified position in the list.

獲取的行ID列表中的指定位置。

Parameters
position  The position of the item within the adapter's data set whose row id we want.
放置在適配器的數據集的行ID,我們希望該項目的位置。

Returns
The id of the item at the specified position.

返回指定位置編號的項目。

程式碼
public long getItemId(int position) {
   return position;
}


getItemViewType (int position)


Get the type of View that will be created by getView(int, View, ViewGroup) for the specified item.
獲取由getView(INT,查看,ViewGroup的)創建的視圖類型的指定項目


參數
position  該項目內適配器的數據集,我們想要的視圖類型的位置


程式碼
public int getItemViewType(int position) {
  return position ;
}


getView int position, View convertView, ViewGroup parent



Get a View that displays the data at the specified position in the data set. You can either create a View manually or inflate it from an XML layout file. When the View is inflated, the parent View (GridView, ListView...) will apply default layout parameters unless you use inflate(int, android.view.ViewGroup, boolean) to specify a root view and to prevent attachment to the root.
得到一個視圖顯示在指定位置的數據集的數據。你可以手動創建一個視圖從一個XML佈局文件
Parameters (參數)
position(位置)The position of the item within the adapter's data set of the item whose view we want.
進入此方法時是數據集的第幾個了,可做為需要不同項目產生不同資料時判別之用

convertView The old view to reuse, if possible. Note: You should check that this view is non-null and of an appropriate type before using. If it is not possible to convert this view to display the correct data, this method can create a new view. Heterogeneous lists can specify their number of view types, so that this View is always of the right type (see getViewTypeCount() and getItemViewType(int)).
簡單來說就是一個view的容器,可以引用新的XML佈局資料達到自定義佈局,再載入資料,最後回傳給需要的元件使用。

parent The parent that this view will eventually be attached to
Returns(返回)
  • A View corresponding to the data at the specified position.  
  • 查看相應的數據在指定的位置
程式碼
public View getView(int position, View convertView, ViewGroup parent) {

  //自訂類別,表達個別listItem中的view物件集合。
        ViewTag viewTag;

        if(convertView == null){
            //取得listItem容器 view
            convertView = myInflater.inflate(R.layout.adapter, null);
            
            //建構listItem內容view
            viewTag = new ViewTag(
            (ImageView)convertView.findViewById(R.id.MyAdapter_ImageView_icon),
            (TextView) convertView.findViewById(R.id.MyAdapter_TextView_title),
            (TextView) convertView.findViewById(R.id.MyAdapter_TextView_info)
             );
            
            //設置容器內容
            convertView.setTag(viewTag);
        }
        else{
            viewTag = (ViewTag) convertView.getTag();
        }
        
        //設定內容圖案
        switch(position){
            case 0:
                viewTag.icon.setBackgroundResource(R.drawable.taipei);
                break;
            case 1:
                viewTag.icon.setBackgroundResource(R.drawable.taichung);
                break;
            case 2:
                viewTag.icon.setBackgroundResource(R.drawable.kaohsiung);
                break;
        }
        
        //設定標題文字
        viewTag.title.setText(title[position]);
        //設定內容文字
        viewTag.info.setText(info[position]);
        
        return convertView;
 }

後記:

Adapter(適配器)還蠻常會看到的,因為如果想客製化介面元件的話,一般都需要用到Adapter(適配器)改變元件為自定義形式,最常用的就是BaseAdapter這個子類,一般形態ArrayAdapter也蠻常用的,不過ArrayAdapter都是用在沒什麼改變時調用,如果想自定義一般都會做用到BaseAdapter這個子類,後續我們再逐步介紹這兩個子類別,謝謝。



2012-08-09

Android 工具 - 幫Eclipse 換程式碼顏色

開發Android一般都是Eclipse做為開發工具,但每次都看到相同的程式碼顏色還蠻無聊的

某天我就上網找了一下看能不能改變一下程式碼的顏色換換心情也好,很幸運的也讓我

找到了相關網站有在做這種事情,就讓我們來看看怎麼改變Eclipse的程式碼顏色吧!


進入Eclipse Color Themes選擇你想改變的程式碼顏色 - 小弟我用的是"Sunburst"


選取可以直接安裝的EPF檔下載它


下載後會是一個epf檔


進入Eclipse中匯入該檔,[File] →[Import] →[Gerneral] →[Preferences] →[瀏覽剛才下載的檔案] 


選取剛剛的epf檔按下完成(Finish)


回來看看程式碼全變了

後記:

改變後順眼多了,整個心情也跟著變好(有點誇張!),最少覺得不會那麼刺眼,不過要習慣新的

程式碼配色,像註解就變白了,一開始看會有點不習慣,不過久了就覺得還好了,而且每次看

到的程式碼顏色都一樣很無聊,所以有空可以改一下程式碼顏色也是蠻好玩的,分享給大家

謝謝。

2012-08-07

Android Activity、Intent系列(一) - 萬用的Intent(意圖)

一般人都知道Intent(意圖)是用來幫Activity傳遞參數用的,但如果你的觀念只停留在

Intent只能用來傳遞參數用那就大錯特錯了,下面介紹怎麼使用萬能的Intent幫我們

簡單的就能做很多的事情了。


Activity跳轉-無參數時
Intent it = new Intent(Activity1.this, Activity2.class);
startActivity(it); 



Activity跳轉-有參數時
Intent it = new Intent(Activity1.this, Activity2.class);
Bundle bundle=new Bundle();
bundle.putString("ID", "This is Activity1 message!");
it.putExtras(bundle);
startActivity(it);  



參數接取方的資料處理程式碼
Bundle bundle=getIntent().getExtras();
String name=bundle.getString("ID");



向上一個Activity返回結果
Intent intent=getIntent();
Bundle bundle=new Bundle();
bundle.putString("ID", "This is from Activity2!");
intent.putExtras(bundle);
setResult(RESULT_OK, intent);



返回結果的處理函數
@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode==REQUEST_CODE){
            if(resultCode==RESULT_CANCELED)
                  setTitle("cancle");
            else if (resultCode==RESULT_OK) {
                 String temp=null;
                 Bundle bundle=data.getExtras();
                 if(bundle!=null)   temp=bundle.getString("ID");
                 setTitle(temp);
            }
        }
    }



瀏覽網頁
Uri uri = Uri.parse("http://jim690701.blogspot.tw/");  
Intent it = new Intent(Intent.ACTION_VIEW, uri);  
startActivity(it);



顯示地圖
//輸入經緯度座標呼叫地圖
Uri uri = Uri.parse("geo:38.899533,-77.036476");  
 Intent it = new Intent(Intent.ACTION_VIEW, uri);   
 startActivity(it); 



路徑規劃
Uri uri = Uri.parse("http://maps.google.com/maps?f=d&saddr=startLat%20startLng&daddr=endLat%20endLng&hl=en");  
Intent it = new Intent(Intent.ACTION_VIEW, uri);  
startActivity(it); 



撥打電話
//注意:使用撥號必須在AndroidManifest.xml 中,加上
//<uses-permission id="android.permission.CALL_PHONE" /> 

//呼叫撥號程序
Uri uri = Uri.parse("tel:0800000123");  
Intent it = new Intent(Intent.ACTION_DIAL, uri);  
startActivity(it); 

//直接撥號
Uri uri = Uri.parse("tel:0800000123");  
Intent it = new Intent(Intent.ACTION_CALL, uri);  
startActivity(it);  



寄送SMS/MMS簡訊
//呼叫簡訊程序 
   Intent it = new Intent(Intent.ACTION_VIEW, uri);  
   it.putExtra("sms_body", "The SMS text");   
   it.setType("vnd.android-dir/mms-sms");  
   startActivity(it); 

   //傳送簡訊 
   Uri uri = Uri.parse("smsto://0800000123");  
   Intent it = new Intent(Intent.ACTION_SENDTO, uri);  
   it.putExtra("sms_body", "The SMS text");  
   startActivity(it); 

  //傳送MMS彩訊  
   //取得手機內圖片連結
   Uri uri = Uri.parse("content://media/external/images/media/23");  
   Intent it = new Intent(Intent.ACTION_SEND); 
   //簡訊主題  
   it.putExtra("sms_body", "some text");   
   it.putExtra(Intent.EXTRA_STREAM, uri);  
   it.setType("image/png");   
   startActivity(it); 



傳送E-mail
//呼叫mail程序
Uri uri = Uri.parse("mailto:xxx@abc.com");  
Intent it = new Intent(Intent.ACTION_SENDTO, uri);  
startActivity(it); 


//簡易寄送E-mail
Intent it = new Intent(Intent.ACTION_SEND);  
it.putExtra(Intent.EXTRA_EMAIL, "me@abc.com");  
it.putExtra(Intent.EXTRA_TEXT, "The email body text");  
it.setType("text/plain");  
startActivity(Intent.createChooser(it, "Choose Email Client")); 


//一般寄送E-mail
Intent it=new Intent(Intent.ACTION_SEND);    
String[] tos={"me@abc.com"};    
String[] ccs={"you@abc.com"};
//主要寄送對象    
it.putExtra(Intent.EXTRA_EMAIL, tos);    
//cc對象
it.putExtra(Intent.EXTRA_CC, ccs);    
//Email內容
it.putExtra(Intent.EXTRA_TEXT, "The email body text");  
//Email主題  
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");    
it.setType("message/rfc822");    
startActivity(Intent.createChooser(it, "選擇電子郵件客戶端"));


//寄送附件
Intent it = new Intent(Intent.ACTION_SEND);  
//Email主題  
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text"); 
//附件 
it.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/mysong.mp3");
//檔案格式  
sendIntent.setType("audio/mp3");  
startActivity(Intent.createChooser(it, "選擇電子郵件客戶端"));





播放多媒體
//播放手機內的MP3
Uri uri = Uri.parse("file:///sdcard/song.mp3");  
Intent it = new Intent(Intent.ACTION_VIEW, uri);  
it.setType("audio/mp3");  
startActivity(it); 

//播放內存的第一個鈴聲
Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1");  
Intent it = new Intent(Intent.ACTION_VIEW, uri);  
startActivity(it);




google play應用
//尋找某個應用
Uri uri = Uri.parse("https://play.google.com/store/search?q=jim.memorandum"); 
Intent it = new Intent(Intent.ACTION_VIEW, uri);  
startActivity(it);  
//https://play.google.com/store/search?q=這段都一樣
//主要是q後面的搜尋條件,可以是package也可以是名稱


//顯示某個應用的相關信息 
Uri uri = Uri.parse("https://play.google.com/store/apps/details?id=jim.memorandum");  
Intent it = new Intent(Intent.ACTION_VIEW, uri); 
startActivity(it);  
//https://play.google.com/store/apps/details?id=這段都一樣
//主要是id後面的package




Uninstall應用程式
//反安裝必須知道package name
Uri uri = Uri.fromParts("package", strPackageName, null); 
Intent it = new Intent(Intent.ACTION_DELETE, uri);   
startActivity(it); 



讀取QR Code
叫用條碼掃描器
Intent intent = new Intent("com.google.zxing.client.android.SCAN");//開啟條碼掃描器
intent.putExtra("SCAN_MODE", "QR_CODE_MODE");//設定QR Code參數
startActivityForResult(intent, 1);//要求回傳1,回傳值可以自由設定


接收掃描後的回傳值
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 // TODO Auto-generated method stub
 super.onActivityResult(requestCode, resultCode, data);
 
     if (requestCode == 1) { //startActivityForResult回傳值,回傳值是由叫用時帶入的設定
         if (resultCode == RESULT_OK) {
             String contents = data.getStringExtra("SCAN_RESULT");//取得QR Code內容
          txt_hello.setText(contents);//顯示儲存值
  }
            }
 }



後記:

看完以上的Intent應用是不是覺得Intent可以用到的地方還真不少吧

我個人是覺得Intent超好用的需要什麼都可以用Intent去呼叫就好,

簡單又能節省程式碼,以上是對萬用Intent的介紹,謝謝。

2012-08-06

Android Image應用(五) - 縮放、指定圖片大小

此篇要介紹的是如何縮放圖片,我們都知道圖片大小有時在呈現上讓我們不是那麼的滿意

或是讀取進來的圖片尺寸可能都有各式各樣的,這樣很容易破壞我們原來的版型,怎麼辦呢?

今天就介紹怎麼縮放圖片,讓圖片變大、變小、變成我們想要的。

  為了讓讀者比較容易了解及讀取方便,所以我會故意把三個按鈕的處理程序都拆開來寫

,而不是寫在一起,目的是為了易於讀取,不然用程序 + switch case寫在一起就好了


main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <ImageView
            android:id="@+id/imageView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:src="@drawable/ic_launcher" />
    </RelativeLayout>


    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >




        <Button
            android:id="@+id/btn_Center"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:text="@string/button_center" />



        <Button
            android:id="@+id/btn_Right"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_marginLeft="30dp"
            android:layout_toRightOf="@+id/btn_Center"
            android:text="@string/button_right" />


        <Button
            android:id="@+id/btn_Left"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_marginRight="30dp"
            android:layout_toLeftOf="@+id/btn_Center"
            android:text="@string/button_left" />

    </RelativeLayout>

</LinearLayout>



strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">圖片縮放</string>
    <string name="button_left">放大</string>
    <string name="button_right">縮小</string>
    <string name="button_center">變為480*480</string>

</resources>


DemoZoomActivity.java
package jim.demo.zoom;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class DemoZoomActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
         //圖片
        final ImageView imageView = (ImageView) findViewById(R.id.imageView1);
        
        //放大
        Button btnLeft = (Button)findViewById(R.id.btn_Left);
        //指定大小
        Button btnCenter = (Button)findViewById(R.id.btn_Center);
        //縮小
        Button btnRight = (Button)findViewById(R.id.btn_Right);
        
        
        //放大按鈕事件
        View.OnClickListener listener_left = new View.OnClickListener() {

			@Override
			public void onClick(View arg0) {
				
				//imageView轉Bitmap
				  imageView.buildDrawingCache();
		          Bitmap bmp=imageView.getDrawingCache();
		        		
		        //轉換為圖片指定大小
	      	    //獲得圖片的寬高
	      	    int width = bmp.getWidth();
	      	    int height = bmp.getHeight();
	      	   
	      	    //放大為1.2倍
	      	    float scaleWidth = (float) 1.2;
	      	    float scaleHeight = (float) 1.2;
	      	    
	      	    // 取得想要缩放的matrix參數
	      	    Matrix matrix = new Matrix();
	      	    matrix.postScale(scaleWidth, scaleHeight);
	      	    // 得到新的圖片
	      	    Bitmap newbm = Bitmap.createBitmap(bmp, 0, 0, width, height, matrix,true);
	      	    
	      	  //重新載入 imageView
	      	  imageView.setImageBitmap(newbm);
	          
			} 
        	
        };
        btnLeft.setOnClickListener(listener_left); 
        
        //指定大小按鈕事件
        View.OnClickListener listener_center = new View.OnClickListener() {

			@Override
			public void onClick(View arg0) {
				
				//imageView轉Bitmap
				  imageView.buildDrawingCache();
		          Bitmap bmp=imageView.getDrawingCache();
		        		
		        //轉換為圖片指定大小
	      	    //獲得圖片的寬高
	      	    int width = bmp.getWidth();
	      	    int height = bmp.getHeight();
	      	    // 設置想要的大小
	      	    int newWidth = 480;
	      	    int newHeight = 480;
	      	    // 計算缩放比例
	      	    float scaleWidth = ((float) newWidth) / width;
	      	    float scaleHeight = ((float) newHeight) / height;
	      	    // 取得想要缩放的matrix參數
	      	    Matrix matrix = new Matrix();
	      	    matrix.postScale(scaleWidth, scaleHeight);
	      	    // 得到新的圖片
	      	    Bitmap newbm = Bitmap.createBitmap(bmp, 0, 0, width, height, matrix,true);
	      	    
	      	  //重新載入 imageView
	      	  imageView.setImageBitmap(newbm);
	      	  
			} 
        	
        };
        btnCenter.setOnClickListener(listener_center); 
        
        //縮小按鈕事件
        View.OnClickListener listener_right = new View.OnClickListener() {

			@Override
			public void onClick(View arg0) {
				
				//imageView轉Bitmap
				  imageView.buildDrawingCache();
		          Bitmap bmp=imageView.getDrawingCache();
		        		
		        //轉換為圖片指定大小
	      	    //獲得圖片的寬高
	      	    int width = bmp.getWidth();
	      	    int height = bmp.getHeight();
	      	   
	      	    //縮小為0.8倍
	      	    float scaleWidth = (float) 0.8;
	      	    float scaleHeight = (float) 0.8;
	      	    
	      	    // 取得想要缩放的matrix參數
	      	    Matrix matrix = new Matrix();
	      	    matrix.postScale(scaleWidth, scaleHeight);
	      	    // 得到新的圖片
	      	    Bitmap newbm = Bitmap.createBitmap(bmp, 0, 0, width, height, matrix,true);
	      	    
	      	  //重新載入 imageView
	      	  imageView.setImageBitmap(newbm);
			} 
        	
        };
        btnRight.setOnClickListener(listener_right); 
    }
}


執行畫面





後記:

            如果試著一直放大縮小你會發現一種現象:"失真了",因為把小圖放的太大本來

就會失真,所以最常用的是在讀取圖片後改變圖片比例到我們指定的大小,要不失真也

行,請準備一張大圖,這樣就比較不會失真了,不然系統內的圖片就如同啟始畫面一樣

小小一張而已,放大就會失真,這是圖片一定會有的狀況,謝謝收看。

2012-08-05

Android的DisplayMetrics類別應用 - 取得螢幕尺寸

Android一個最讓開發者頭大的問題,就是手機的螢幕尺寸太雜、大小太多

造成開發者在開發應用程式上的難度,要兼顧每一個尺寸是讓人頗頭大

現在介紹使用DisplayMetrics類別取得手機螢幕尺寸大小,以改變控制元件

來配合螢幕尺寸。

main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/TextView01"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

    <EditText
        android:id="@+id/editText1"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:ems="10"
        android:inputType="textMultiLine"
        android:singleLine="false" >

        <requestFocus />

    </EditText>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:layout_marginRight="60dp"
            android:text="@android:string/cancel" />

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:layout_marginLeft="60dp"
            android:text="@android:string/ok" />

    </RelativeLayout>

</LinearLayout>

我先設定螢幕尺寸為2.7寸,中間EditText高度為300dp


執行後的畫面,因為實際螢幕比較大,所以程式小了一號


使用DisplayMetrics類別取得螢幕尺寸大小改變控制項尺寸大小以符合實際螢幕大小

DemoGetScreenActivity.java
package jim.demo.getscreen;

import android.app.Activity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.widget.EditText;
import android.widget.TextView;

public class DemoGetScreenActivity extends Activity {
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        DisplayMetrics metrics = new DisplayMetrics();  
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        
        TextView TextView1 = (TextView)findViewById(R.id.TextView01);
        TextView1.setText("手機螢幕大小為 "+metrics.widthPixels+" X "+metrics.heightPixels);
        
        
        EditText editText1 = (EditText)findViewById(R.id.editText1);
        
        //原QVGA 2.7吋螢幕解析度為240 * 320
        if(metrics.heightPixels > 320)
        {
        	//改變editText1的高度
        	editText1.getLayoutParams().height = 600;
        }
          
    }
}

改變後執行畫面


官方螢幕尺寸和解析度對照表



後記:

          android的螢幕尺寸是個很麻煩的問題,因為不像Apple的iphone一樣只有單一尺寸

每一家Android廠商就有不同的尺寸,所以開發時就只有靠著DisplayMetrics抓取的螢幕

尺寸來做適度的調整,正常來說抓最小尺寸(QVGA)、大尺寸(WVGA)、平板尺寸(WXGA)

三種來做測試就好,只要不會出現按不到鈕的情況就可以了,不然要寫完整的全部尺寸

調整是要花費不少時間的,以上給大家參考,感謝。
       
         

Android 手機資料庫(五) - SQLite之資料庫更新說明篇


如果你對資料庫還完全陌生,請參考之前的三篇文章(第一篇第二篇第三篇)

因為很多人都不了解Android的資料庫更新應該怎麼做,所以在此寫一篇說明文好了

希望不了解的人看完之後能比較有所了解,下面開始解釋:

先貼上資料庫的程式碼,裡面當然也包含一般更新資料庫(onUpgrade)


程式碼
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase.CursorFactory;

public class NewListDataSQL extends SQLiteOpenHelper {

  private static final int VERSION = 3;//資料庫版本  
  
  public NewListDataSQL(Context context, String name, CursorFactory factory,int version) { //建構子
   super(context, name, factory, version);
  }

  public NewListDataSQL(Context context,String name) { 
   this(context, name, null, VERSION); 
   } 
  
   public NewListDataSQL(Context context, String name, int version) {  
    this(context, name, null, version);  
      }  
   
  //輔助類建立時運行該方法
  @Override
  public void onCreate(SQLiteDatabase db) {
   String DATABASE_CREATE_TABLE =
     "create table newMemorandum("
       + "_ID INTEGER PRIMARY KEY  AUTOINCREMENT  NOT NULL,"
             + "date VARCHAR,"
             + "note VARCHAR,"
             + "pw VARCHAR,"
             + "reminder INT,"
             + "type VARCHAR,"
             + "memo VARCHAR"
         + ")";
            db.execSQL(DATABASE_CREATE_TABLE);
  }

  @Override
  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
   //oldVersion=舊的資料庫版本;newVersion=新的資料庫版本
     //db.execSQL("DROP TABLE IF EXISTS newMemorandum"); //刪除舊有的資料表
     //onCreate(db);
   
   
   if (newVersion > oldVersion) {
       db.beginTransaction();
    
       boolean success = true;
       
         
         switch (oldVersion) {
           case 2:           
            
            Cursor cursor = db.rawQuery("select _ID,date from newMemorandum", null);
            int[] iID = new int[cursor.getCount()];
            String[] sDate = new String[cursor.getCount()];
            
            int rows_num = cursor.getCount(); //取得資料表列數
            
            if(rows_num != 0) {
            cursor.moveToFirst();   //將指標移至第一筆資料
            for(int i=0; i<rows_num; i++) {
             int iCr = cursor.getInt(0);
             String strCr = cursor.getString(1);
             iID[i]=iCr;
             sDate[i]=strCr.split(" ")[0].split("/")[0] + "/" + String.valueOf(Integer.valueOf(strCr.split(" ")[0].split("/")[1])) + "/" + String.valueOf(Integer.valueOf(strCr.split(" ")[0].split("/")[2])) + " " + strCr.split(" ")[2];
             
             //因為日期格式有變,所以重新更新
             //格式改為2012/6/6 12:02
             ContentValues cv = new ContentValues();
             cv.put("date", sDate[i]);
             
             db.update("newMemorandum", cv, "_ID=" + iID[i], null);
             
             cv = null;//消滅物件
             
             
             cursor.moveToNext();  //將指標移至下一筆資料
            }
           }
           cursor.close();  //關閉Cursor
            
           
            db.execSQL("ALTER TABLE newMemorandum ADD COLUMN reminder integer DEFAULT 0");
            db.execSQL("ALTER TABLE newMemorandum ADD COLUMN type VARCHAR");
            db.execSQL("ALTER TABLE newMemorandum ADD COLUMN memo VARCHAR");
            oldVersion++;
            
               success = true;
             break;
           case 1:
                        
            Cursor cursor2 = db.rawQuery("select _ID,date from newMemorandum", null);
            int[] iID2 = new int[cursor2.getCount()];
            String[] sDate2 = new String[cursor2.getCount()];
            
            int rows_num2 = cursor2.getCount(); //取得資料表列數
            
            if(rows_num2 != 0) {
             cursor2.moveToFirst();   //將指標移至第一筆資料
            for(int j=0; j<rows_num2; j++) {
             int iCr2 = cursor2.getInt(0);
             String strCr = cursor2.getString(1);
             iID2[j]=iCr2;
             sDate2[j]=strCr.split(" ")[0].split("/")[0] + "/" + String.valueOf(Integer.valueOf(strCr.split(" ")[0].split("/")[1])) + "/" + String.valueOf(Integer.valueOf(strCr.split(" ")[0].split("/")[2])) + " " + strCr.split(" ")[2];
             
             //因為日期格式有變,所以重新更新
             //格式改為2012/6/6 12:02
             ContentValues cv2 = new ContentValues();
             cv2.put("date", sDate2[j]);
             
             db.update("newMemorandum", cv2, "_ID=" + iID2[j], null);
             
             cv2 = null;//消滅物件
             
             
             cursor2.moveToNext();  //將指標移至下一筆資料
            }
           }
            cursor2.close();  //關閉Cursor
           
            db.execSQL("ALTER TABLE newMemorandum ADD COLUMN pw VARCHAR");
            db.execSQL("ALTER TABLE newMemorandum ADD COLUMN reminder integer DEFAULT 0");
            db.execSQL("ALTER TABLE newMemorandum ADD COLUMN type VARCHAR");
            db.execSQL("ALTER TABLE newMemorandum ADD COLUMN memo VARCHAR");
            oldVersion = 3;
               success = true;
             break;
         }
           
    
       if (success) {
         db.setTransactionSuccessful();
       }
       db.endTransaction();
     }
     else {
       onCreate(db);
     }
   
  }
  
  @Override    
   public void onOpen(SQLiteDatabase db) {     
           super.onOpen(db);       
           // TODO 每次成功打開數據庫後首先被執行     
       } 

   @Override
        public synchronized void close() {
            super.close();
            // TODO 每次關閉數據庫後被執行     
        }
}


說明:

此為資料庫SQLiteOpenHelper類的程式碼,幾個地方分析

1.資料庫的執行方式  
當系統要new出SQLiteOpenHelper類時,會先去找應用程式的DB資料夾下是否有該資料庫
如果沒有就執行建構子及onCreate建構該類別
如果有就執行onUpgrade更新資料庫

2.private static final int VERSION = 3;//資料庫版本  代表的意義與作用
(1)如果手機中沒有該應用程式,也等於沒有該資料庫(因為資料庫是獨立個體)
就會執行建構子構建該資料庫,建構子會帶入此VERSION,也就是從第3版開始
之後的更新也是從第4版開始,不能再回到第1版開始。

(2)如果有資料庫就會跳到onUpgrade事件中
oldVersion=舊的資料庫版本
newVersion=新的資料庫版本
這兩個是怎麼出現的呢?
在要更新資料庫時,您之前的VERSION一定是寫成這樣VERSION = 2
VERSION = 2 就是  = oldVersion
程式有修改時,資料庫也有修改,這時也會把VERSION改為VERSION = 3
VERSION = 3 就是 = newVersion
當你更新資料庫時,程式判別出VERSION = 3比之前的VERSION = 2大時
就會自動跳到onUpgrade事件中,帶入oldVersion=2、newVersion=3
當然你的舊版也可能是VERSION = 1(因為沒有即時更新)
程式還是會帶入oldVersion=1、newVersion=3

3.onUpgrade資料庫更新
(1)當我們了解了程式是怎麼判別資料庫更新後,再來看資料庫是怎麼更新的
因為舊版本可能不一樣,有可能最新版是第3版,舊版有1、2兩版
所以這裡可以針對不同版本做不同的更新動作,因為各版更新的都不同
所以可以用switch case分開各版本再對各版本做不同的更新動作(如上面程式碼)

(2)更新資料庫不止可以下ALTER的SQL指令而已,因為資料本身是存在的
只要不下Drop,所以可以用Cursor cursor = db.rawQuery把資料撈出來做變更
我個人是把資料撈出來做日期格式的變更,最後再下ALTER新增欄位
注意看程式碼中1版是ALTER了4個欄位,2版是ALTER了3個欄位
所以如果你是放上google play上是要針對每個版本做不同的更新
因為你不知道下載者有沒有即時去更新你的應用程式,所以基本上要保留資料
就要這樣寫把之前的版本做不同的更新,這樣才能確保每一個版本都能更新
到最新的版本而不會出錯。

以上說明希望能幫助你對Android的資料庫有了進一步的了解,謝謝。



2012-08-02

Bitmap、Drawable、byte的轉換

當寫到圖片的處理時,比較常會遇到的是這三種圖片型態的轉換

所以就來介紹一下這三種資料型態該怎麼轉換。


Bitmap 轉 Drawable
Drawable drawable = new BitmapDrawable(Bitmap);




Drawable 轉 Bitmap
Drawable oDrawable = xxx; //xxx根據自己的情況獲取drawable
BitmapDrawable BD = (BitmapDrawable) oDrawable;
Bitmap BM = BD.getBitmap();




實體路徑圖片檔 轉 Drawable
//這句一定要在onCreate()里面調用
File tempFile = = new File("/sdcard/a.jpg");

Drawable drawable = Drawable.createFromPath(tempFile.getAbsolutePath());




從res\drawable中取出內存圖片為Bitmap
Resources res=getResources();

Bitmap bmp=BitmapFactory.decodeResource(res, R.drawable.ic_launcher); 
 



imageView 轉 Bitmap
  //圖片
  ImageView imageView_save = (ImageView) findViewById(R.id.img_newphoto);

  //imageView轉Bitmap
  imageView_save.buildDrawingCache();
  Bitmap bmp=imageView_save.getDrawingCache();




bitmap 轉 byte
  Bitmap newbm;

  // 把 bitmap 轉成 byte
  ByteArrayOutputStream stream = new ByteArrayOutputStream();
  newbm.compress(Bitmap.CompressFormat.JPEG, 100, stream );
  byte bytes[] = stream.toByteArray();



後記:

這是我常用到的轉換,還蠻實用的,所以PO出來給需要的人參考,謝謝。

2012-07-31

Android 手機資料庫(四) - 將圖片存入資料庫的方法

我們都知道一般照片都是放在手機的圖片資料夾下,很少會放到資料庫內

不過為了怕應用程式需要的照片不小心被刪了而讓應用程式出錯,所以

就需要把圖片存進資料庫內,這裡我就來介紹怎麼樣把照片存進資料庫和取出

注意:這部份因為有關係到資料庫,所以為了不讓程式碼太多,所以我只show出
如何取出和存入圖片的程式碼,所以對資料庫需要有一定的認識,這部份請參考
前三篇(第一篇第二篇第三篇)的介紹。


存入的程式碼
//圖片
 ImageView imageView_save = (ImageView) findViewById(R.id.img_newphoto);
               
        //imageView轉Bitmap
        //imageView_save.setDrawingCacheEnabled(true);
        //建立圖片的緩存,圖片的緩存本身就是一個Bitmap
        imageView_save.buildDrawingCache();
        //取得緩存圖片的Bitmap檔
        Bitmap bmp=imageView_save.getDrawingCache();
          
            //轉換為圖片指定大小
            //獲得圖片的寬高
            int width = bmp.getWidth();
            int height = bmp.getHeight();
            // 設置想要的大小
            int newWidth = 480;
            int newHeight = 525;
            // 計算缩放比例
            float scaleWidth = ((float) newWidth) / width;
            float scaleHeight = ((float) newHeight) / height;
            // 取得想要缩放的matrix參數
            Matrix matrix = new Matrix();
            matrix.postScale(scaleWidth, scaleHeight);
            // 得到新的圖片
            Bitmap newbm = Bitmap.createBitmap(bmp, 0, 0, width, height, matrix,true);
             
          
            // 先把 bitmap 轉成 byte
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            newbm.compress(Bitmap.CompressFormat.JPEG, 100, stream );
            byte bytes[] = stream.toByteArray();
            // Android 2.2以上才有內建Base64,其他要自已找Libary或是用Blob存入SQLite
            // 把byte變成base64
            String base64 = Base64.encodeToString(bytes, Base64.DEFAULT); 
           
            //放img進去SQLite
            ContentValues cv = new ContentValues();
            cv.put("image", base64);
           //添加方法
           long long1 = db.insert(table_name, "", cv)



取出的程式碼
//取出資料
        Cursor cursor = db.rawQuery("select * from newimg where season = '秋'", null);
        
        //用陣列存圖片,陣列大小 = 取出資料的筆數
 Drawable[] Drawablelist = new Drawable[cursor.getCount()];
 Bitmap[] bmplist = new Bitmap[cursor.getCount()];
        
        //取得資料表筆數
        int rows_num = cursor.getCount(); 
  if(rows_num != 0) {

          //將指標移至第一筆資料
   cursor.moveToFirst(); 
            
   for(int i=0; i<rows_num; i++) {
            // 把Base64變回bytes
     byte bytes[] = Base64.decode(cursor.getString(2), Base64.DEFAULT);

            //用BitmapFactory生成bitmap
     bmplist[i] = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); 
       
     //轉換Bitmap為Drawable
            Drawable drawable = new BitmapDrawable(bmplist[i]);

            //存入Drawable陣列中
     Drawablelist[i]=drawable;

            //將指標移至下一筆資料
            cursor.moveToNext();  
          }
        }

        //關閉Cursor
 cursor.close(); 
        //關閉資料庫,釋放記憶體 
 dbHelper.close(); 



後記:

          在存入時我有多用了縮放圖片,而在取出時因程式需要,所以有把Bitmap

再轉換為Drawable,這個可以看個人程式上的需求去做改變,不一定要照copy

程式是死的,人是活的,希望大家都能寫出一支好的程式,感謝。