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

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

Android Image應用(四) - 旋轉圖片

如果您有用到拍照或取得圖片功能時應該會知道,得到的照片或圖片會剛好跟我們想要的

差了90度,怎麼辦呢?這裡就為您介紹怎麼把圖片轉向90度的方法


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="300dp"
            android:layout_height="300dp"
            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/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="@string/right" />

        <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="@string/left" />

    </RelativeLayout>

</LinearLayout>



strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">DemoImageRotation</string>
    <string name="left">左旋90度</string>
    <string name="right">右旋90度</string>
</resources>


DemoImageRotationActivity.java
package jim.demo.ImageRotation;

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 DemoImageRotationActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
      //圖片左旋90
        Button button_left = (Button)findViewById(R.id.button1);
        View.OnClickListener listener_left = new View.OnClickListener() {  
         
         public void onClick(View view) { 
         //取得圖片
         ImageView imageView_left = (ImageView) findViewById(R.id.imageView1);
         //imageView_left.setDrawingCacheEnabled(true);
         //建立圖片的緩存,圖片的緩存本身就是一個Bitmap
         imageView_left.buildDrawingCache();
         //取得緩存圖片的Bitmap檔
         Bitmap bmp=imageView_left.getDrawingCache();
         //定義一個矩陣圖
         Matrix m=new Matrix();
         //取得圖片的寬度
                int width=bmp.getWidth();
                //取得圖片的長度
                int height=bmp.getHeight();
                //逆時針旋轉90度
                m.setRotate(-90);
              //產生新的旋轉後Bitmap檔
                Bitmap b=Bitmap.createBitmap(bmp, 0, 0, width, height, m, true);
                
                //顯示圖片
                imageView_left.setImageBitmap(b);
            }  
        };  
        button_left.setOnClickListener(listener_left); 
        
        
      //圖片右旋90
        Button button_right = (Button)findViewById(R.id.button2);
        View.OnClickListener listener_right = new View.OnClickListener() {  
         public void onClick(View view) {  
         //取得圖片
         ImageView imageView_right = (ImageView) findViewById(R.id.imageView1);
         //imageView_right.setDrawingCacheEnabled(true);
         //建立圖片的緩存,圖片的緩存本身就是一個Bitmap
         imageView_right.buildDrawingCache();
         //取得緩存圖片的Bitmap檔
         Bitmap bmp=imageView_right.getDrawingCache();
         //定義一個矩陣圖
         Matrix m=new Matrix();
         //取得圖片的寬度
                int width=bmp.getWidth();
                //取得圖片的長度
                int height=bmp.getHeight();
                //順時針旋轉90度
                m.postRotate(90); 
                //產生新的旋轉後Bitmap檔
                Bitmap b=Bitmap.createBitmap(bmp, 0, 0, width, height, m, true);
                
                //顯示圖片
                imageView_right.setImageBitmap(b);
            
            }  
        };  
        button_right.setOnClickListener(listener_right);
    }   
}


執行畫面



後記:

            旋轉圖片對有用到取得手機內圖片及拍照功能的人應該還蠻需要的

但有一個缺點,就是旋轉必須長寬都一樣時用,如果長和寬是不一樣時,比如說是2:1

會出現一種現象,就是會愈轉愈小-.-",原因是當比較大的長轉到比較小的寬時會因為

放不進去,所以會自動縮小,然後你愈轉它就縮的愈多,所以就會出現愈轉愈小的現象

這是我後來再處理照片時發現的,好了!就為您介紹到這了,感謝。

2012-07-30

Android 多國語系

Android手機有支援多國語系的功能,所以在應用程式的開發上也能輕鬆做出多國語系的功能

下面就開始介紹怎麼在應用程式中做出多國語系的功能

我們一樣新增一個專案叫:DemoLanguage

修改main.xml如下:
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:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/txt_accessories1" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/txt_accessories2" />

</LinearLayout>

修改res/values/strings.xml如下:
strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">DemoLanguage</string>
    <string name="txt_accessories1">飾品</string>
    <string name="txt_accessories2">照片說明</string>
</resources>

因為預設語系是繁體中文,所以values指定的是繁體中文語系

加入其他語系:






英文語系的strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="txt_accessories1">Accessories</string>
    <string name="txt_accessories2">Description</string>
</resources>

注意:string name要和繁系中文的string name一樣,如果不同,系統會自動帶入預設繁體中文

簡體也以此類推:
簡體語系的strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="txt_accessories1">饰品</string>
    <string name="txt_accessories2">照片说明</string>
</resources>

注意:因為簡體中文和繁體中文用的代碼都是zh,所以必須關閉Eclipse,去資料夾下手動
修改為"values-zh-rCN",不然系統是會錯亂的


執行後畫面






後記:

         多國語系這樣就設定完了,其實並不難,要注意的是繁體中文和簡體中文用的都是"zh"

所以要特別修改,不然用自建資料夾也是可以的,英文是"en"、日文是"ja",這是我所知道的

其他語系就上網去找一下,應該還蠻好找到代號的,就為你介紹到此,謝謝。

2012-07-29

Android Menu(菜單)應用

Android智慧型手機上都有最少三個按鍵:Menu、首頁、退後鍵

今天就來介紹Menu(菜單),可以幫助應用程式做一些共用功能如:設定、重新整理

結束、關於我、說明.....等,可以說也是一個蠻實用及常用的功能之一

下面就開始為您說明如果在應用程式中加入Menu功能:

因為main.xml是一個空白,所以在這就不放上程式碼了


strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="ok_label">關閉</string>
    <string name="app_name">DemoMenu</string>
     <string name="MENU_ABOUT">關於..</string>
     <string name="MENU_Refresh">重新整理</string>
     <string name="MENU_close">結束</string>
     <string name="about_title">關於..</string>
    <string name="about_msg">注意!你在看我嗎? \n\n
                                 你可以再近一點! \n\n
                                 你真的可以再近一點! </string>
     </resources>

DemoMenuActivity.java
package jim.demo.menu;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

public class DemoMenuActivity extends Activity {
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    
    //定義三個menu
    protected static final int MENU_ABOUT = Menu.FIRST;
    protected static final int MENU_Refresh = Menu.FIRST+2;
    protected static final int MENU_close = Menu.FIRST+1;
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        //加入應用程式menu中,分別是:關於我、重新整理、結束
        menu.add(0, MENU_ABOUT, 0, getString(R.string.MENU_ABOUT));
        menu.add(0, MENU_Refresh, 0, getString(R.string.MENU_Refresh));
        menu.add(0, MENU_close, 0, getString(R.string.MENU_close));
        return true;
   }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        super.onOptionsItemSelected(item);
        switch(item.getItemId()){
             //關於我
             case MENU_ABOUT:
              //顯示關於我對話方塊
                 openOptionsDialog();
                 break;
             //重新整理
             case MENU_Refresh:
               //本頁跳轉到本頁是最簡單的重新整理方式  
              Intent intent = new Intent();
              intent.setClass(DemoMenuActivity.this,DemoMenuActivity.class);
                 startActivity(intent);
                 
                 //記得結束掉本頁,不然會出現按下倒退鍵還是在本頁而不是跳出的狀況
                 this.finish();
                 
                 break;   
             //結束 
             case MENU_close:
                 finish();
                break;
          }
          return true;
    }
    
    private void openOptionsDialog() {
        AlertDialog.Builder dialog = new AlertDialog.Builder(DemoMenuActivity.this);
        //標題
        dialog.setTitle(R.string.about_title);
        //內容
        dialog.setMessage(R.string.about_msg);
        //中間的關閉按鈕
        dialog.setPositiveButton(R.string.ok_label,
            new DialogInterface.OnClickListener(){
                public void onClick(
                        DialogInterface dialoginterface, int i){
                        }
                });
        //顯示對話方塊
        dialog.show();
    }
}

執行後畫面



後記:

         Menu因為已經是預設的頁面功能了,所以不需要元件,只要加入onCreateOptionsMenu

        再設定按下Menu後的事件onOptionsItemSelected就可以了,記得這幾個是寫在onCreate

        之外的,有一點值得注意的是我在使用AlertDialog時,內容的換行是可以用"\n\n"


        以上為您說明到這,感謝您。

2012-07-26

Android Image應用(三) - 裁剪圖片 for 拍照之後

上篇介紹了取得圖片後的裁剪,此篇再為您介紹拍照後的裁剪,可能您會覺得

這兩種不一樣嗎?其實是一樣的,差別在於取得圖片後的資料流不一樣

處理的方式也不同,因此把它分開成兩篇來介紹,其實寫法是可以寫在一起的

因為拍照和從手機內取得圖檔在取得圖片後都是會回到onActivityResult內的

下面開始來看看怎麼做吧。


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" >
<Button
   android:id="@+id/captureimage"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="使用其他服務幫忙拍照 "
   />
<ImageView
   android:id="@+id/imagecaptured"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   />
</LinearLayout>

DemoCameraActivity.java
package jim.demo.camera;

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

public class DemoCameraActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        //調用其他服務拍照按鈕
        Button buttonCamera = (Button)findViewById(R.id.captureimage);
               
        buttonCamera.setOnClickListener(new Button.OnClickListener(){
   public void onClick(View v) {
    //使用Intent調用其他服務幫忙拍照
     Intent intent_camera = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
     startActivityForResult(intent_camera, 0);
   }
        });
    }
    
    @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      //拍照後顯示圖片
      ImageView iv = (ImageView)findViewById(R.id.imagecaptured);
   if (resultCode == RESULT_OK)
     {
    switch (requestCode) {  
          case 0:
    //取出拍照後回傳資料
    Bundle extras = data.getExtras();
    //將資料轉換為圖像格式
          Bitmap bmp = (Bitmap) extras.get("data");
           //如果有資料就丟doCropPhoto進行裁剪
           if(bmp!=null){
          doCropPhoto(bmp);
           }
           break; 
          case 1: 
           Bitmap photo1 = data.getParcelableExtra("data");
           //載入ImageView
              iv.setImageBitmap(photo1);
           break;   
    }
     }
   
     //覆蓋原來的Activity
     super.onActivityResult(requestCode, resultCode, data);
  }
    
    protected void doCropPhoto(Bitmap data){
     //進行照片裁剪
        Intent intent = getCropImageIntent(data);
        startActivityForResult(intent, 1);
    }
   
    public static Intent getCropImageIntent(Bitmap data) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setType("image/*");
        intent.putExtra("data", data);
        intent.putExtra("crop", "true");// crop=true 有這句才能叫出裁剪頁面.
        intent.putExtra("aspectX", 1);// 这兩項為裁剪框的比例.
        intent.putExtra("aspectY", 1);// x:y=1:1
        intent.putExtra("outputX", 300);//回傳照片比例X
        intent.putExtra("outputY", 300);//回傳照片比例Y
        intent.putExtra("return-data", true);
        return intent;
    }
}


執行後畫面




後記:

         看完程式碼應該就可以看出其實大同小異,主要都是用intent.putExtra("crop", "true")


叫出裁剪頁面進行裁剪,不同在拍照後圖檔的不同,所以需要進行不同的轉換


我在使用上其實是會把從手機內取得圖檔和拍照放在一起供使用者選擇,此處是因為介紹

所以把它分開,小弟我就介紹到這裡,有問題請留言或來信,感謝。



Android Image應用(二) - 裁剪圖片 for 取得手機內圖檔時

有介紹過取得手機內圖檔使用拍照功能,拍出來的大多都是1:2或2:1的長寬

如果我們想要的是1:1的圖片呢?怎麼辦?拿剪刀?從手機讀出來用圖片編輯軟體

裁剪後再放回去?當然不是這樣的,這樣太麻煩了,如果能直接裁剪當然是最好的

所以下面就為您介紹直接在取得圖檔時就執行裁剪圖片的動作。


main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    >  
   <Button   
        android:id="@+id/b01"  
        android:layout_width="fill_parent"   
        android:layout_height="wrap_content&
    />  
    <ImageView  
        android:id="@+id/iv01"  
        android:layout_width="fill_parent"   
        android:layout_height="wrap_content"   
     />  
</LinearLayout>  


GetPicturesActivity.java
package jim.demo.getpictures;

import java.io.File;
import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class GetPicturesActivity extends Activity {
 private File tempFile;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        this.tempFile = new File("/sdcard/a.jpg");// 這句一定要在onCreate()里面調用
        
        //找尋Button按鈕
        Button button = (Button)findViewById(R.id.b01);
        //設定按鈕內文字
        button.setText("選擇圖片");
        //設定按鈕監聽式
        button.setOnClickListener(new Button.OnClickListener(){
   public void onClick(View v) {
     Intent intent = new Intent();
          // 開啟Pictures畫面Type設定為image
          intent.setType("image/*");
          // 使用Intent.ACTION_GET_CONTENT這個Action
          // 會開啟選取圖檔視窗讓您選取手機內圖檔 
          intent.setAction(Intent.ACTION_GET_CONTENT); 
          intent.setType("image/*");
          intent.putExtra("crop", "true");// crop=true 有這句才能叫出裁剪頁面.
          intent.putExtra("aspectX", 1);// 这兩項為裁剪框的比例.
          intent.putExtra("aspectY", 1);// x:y=1:1
          intent.putExtra("output", Uri.fromFile(tempFile));
          intent.putExtra("outputFormat", "JPEG");//返回格式
                    
          // 取得相片後返回本畫面
           startActivityForResult(Intent.createChooser(intent, "選擇圖片"),1);
   }
         
        });
    }
    
    //取得相片後返回的監聽式
 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  //取得圖片控制項ImageView
  ImageView imageView = (ImageView) findViewById(R.id.iv01);
  
  //當使用者按下確定後
  if (resultCode == RESULT_OK) {
       
   // 設定到ImageView 
   imageView.setImageDrawable(Drawable.createFromPath(tempFile.getAbsolutePath()));
     
  }
  super.onActivityResult(requestCode, resultCode, data);
 }
}

執行畫面




後記:

          切割其實是使用intent.setAction(Intent.ACTION_GET_CONTENT)抓取圖片後

再多加一個動作使用intent.putExtra("crop", "true")叫出裁剪頁面達到裁剪效果

還蠻簡單的,下篇再為您介紹在拍照後如果要裁剪照片該怎麼做,感謝收看。

2012-07-25

Android camera應用(二) - 使用Android內部照相機功能

上一篇我們使用了呼叫其它一樣有照相功能的應用程式幫我們完成拍照這種比較簡單、

也較方便的用法,此篇我們來用比較原始的方法,使用的是Android內部的拍照功能

相對也比較複雜一點,使用的時機是客製化比較重而呼叫其他拍照應用程式也無法完成的


這時就必須用到原始的方法,直接用內部拍照預覽功能了,開始為您介紹

使用之前,因為調用照相功能有權限問題,所以必須在AndroidManifest.xml內加入照相權限


及相關我們需要用到的自動對焦功能


//拍照權限

<uses-permission android:name="android.permission.CAMERA" />     
//自動對焦      
 <uses-feature android:name="android.hardware.camera" />                
 <uses-feature android:name="android.hardware.camera.autofocus" />
//螢幕轉為橫向顯示,因為預設為橫向拍照,如果不設計成橫向
//預覽畫面和拍出來的照片會自動轉90度
android:screenOrientation="landscape"



AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="jim.camera"
    android:versionCode="1"
    android:versionName="1.0" android:installLocation="auto">

    <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="8"/>
 <uses-permission android:name="android.permission.CAMERA" />   
 <uses-feature android:name="android.hardware.camera" />   
 <uses-feature android:name="android.hardware.camera.autofocus" />  
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".CameraActivity"
            android:label="@string/app_name"
            android:screenOrientation="landscape" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


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


 <LinearLayout android:layout_height="wrap_content" android:id="@+id/linearLayout1" android:layout_width="fill_parent">

  <SurfaceView
      android:id="@+id/surfaceView1"
      android:layout_width="250dp"
      android:layout_height="250dp" />

  <Button android:text="拍照" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>




  <ImageView
      android:id="@+id/imageView1"
      android:layout_width="250dp"
      android:layout_height="250dp" />

 </LinearLayout>
</LinearLayout>

CameraActivity.java
package jim.camera;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
 
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

public class CameraActivity extends Activity implements SurfaceHolder.Callback{
 SurfaceHolder surfaceHolder;
 SurfaceView surfaceView1;
 Button button1;
 ImageView imageView1;
 Camera camera;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        button1=(Button)findViewById(R.id.button1);
        //在AndroidManifest.xml中設定或是用下面的setRequestedOrientation(0)設定也可以
        //0代表橫向、1代表縱向
        setRequestedOrientation(0);
        //設為横向顯示。因為攝影頭會自動翻轉90度,所以如果不横向顯示,看到的畫面就是翻轉的。
         
        surfaceView1=(SurfaceView)findViewById(R.id.surfaceView1);
        imageView1=(ImageView)findViewById(R.id.imageView1);
        surfaceHolder=surfaceView1.getHolder();
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        surfaceHolder.addCallback(this);
        button1.setOnClickListener(new OnClickListener(){
 
   public void onClick(View v) {
    
    //自動對焦
    camera.autoFocus(afcb);
    
   }});
 
    }
    PictureCallback jpeg =new PictureCallback(){
 
  public void onPictureTaken(byte[] data, Camera camera) {
   
   Bitmap bmp=BitmapFactory.decodeByteArray(data, 0, data.length);
   //byte數组轉換成Bitmap
   imageView1.setImageBitmap(bmp);
   //拍下圖片顯示在下面的ImageView裡
   FileOutputStream fop;
   try {
    fop=new FileOutputStream("/sdcard/dd.jpg");
    //實例化FileOutputStream,參數是生成路徑
    bmp.compress(Bitmap.CompressFormat.JPEG, 100, fop);
    //壓缩bitmap寫進outputStream 參數:輸出格式  輸出質量  目標OutputStream
    //格式可以為jpg,png,jpg不能存儲透明
    fop.close();
    System.out.println("拍照成功");
    //關閉流
   } catch (FileNotFoundException e) {
    
    e.printStackTrace();
    System.out.println("FileNotFoundException");
 
   } catch (IOException e) {
    
    e.printStackTrace();
    System.out.println("IOException");
   }
   camera.startPreview();
   //需要手動重新startPreview,否則停在拍下的瞬間
  }
 
    };
 
 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
  
 
 }
 
 public void surfaceCreated(SurfaceHolder holder) {
  
  camera=Camera.open();
  try {
 
   Camera.Parameters parameters=camera.getParameters();
   parameters.setPictureFormat(PixelFormat.JPEG);
   parameters.setPreviewSize(320, 220);
   camera.setParameters(parameters);
   //設置參數
   camera.setPreviewDisplay(surfaceHolder);
   //鏡頭的方向和手機相差90度,所以要轉向
   //camera.setDisplayOrientation(90);
   //攝影頭畫面顯示在Surface上
   camera.startPreview();
  } catch (IOException e) {
   
   e.printStackTrace();
  }
 
 }
 
 public void surfaceDestroyed(SurfaceHolder holder) {
  
  System.out.println("surfaceDestroyed");
  camera.stopPreview();
  //關閉預覽
  camera.release();
  // 
 }
 
 //自動對焦監聽式
 AutoFocusCallback afcb= new AutoFocusCallback(){
 
  public void onAutoFocus(boolean success, Camera camera) {
   
   if(success){
    //對焦成功才拍照
    camera.takePicture(null, null, jpeg);
   }
  }
 
 
 };
}

執行後畫面



說明:

         1.Android的照相功能預計是橫向拍照,所以如果您是用直立的方式拍照

您就需要把預覽畫面轉向90度在surfaceCreated方法中加入camera.setDisplayOrientation(90);

預覽畫面就會轉90度,再來把得到的照片也要轉90度,不然得到的照片還是會是轉了90度

這方面可以自行實驗一下就會大概知道它的原理了。

public class CameraActivity extends Activity implements SurfaceHolder.Callback

        2.相機功能除了繼承Activity之外,也需要實現SurfaceHolder.Callback這個預覽界面接口

用來接收攝影鏡頭預覽界面變化的訊息,它有三個方法:

(1)surfaceCreated:當預覽界面創建時調用此方法

(2)surfaceChanged:當預覽界面的格式和大小改變時調用此方法

(3)surfaceDestroyed:當預覽界面被關閉時調用此方法

         3.照相的流程大概是:

(1)在佈局檔main.xml中會有一個SurfaceView

(2)加入surfaceHolder以控制隨時在變動的SurfaceView


(3)創始應用程式時觸發surfaceCreated,開啟攝影鏡頭及設定相關參數(相片格式及尺寸)
    攝影頭畫面顯示在 SurfaceView 


(4)Button內的onClick事件中使用自動對焦camera.autoFocus(afcb);


(5)自動對焦監聽式AutoFocusCallback afcb= new AutoFocusCallback()
    對焦成功才會調用camera.takePicture(null, null, jpeg);拍照

(6)得到的照片進入PictureCallback jpeg =new PictureCallback()處理

(7)完成關閉程式時會觸發surfaceDestroyed關閉預覽及釋放資源


後記:

          本人在使用上是比較習慣直接用Intent呼叫其它拍照服務的方法在做


除非呼叫的方法不能達到我想要的目的,我才會想要用這個方法做,不然這個方法


是比較麻煩的,因為看程式碼和說明也知道,比上一篇複雜上很多倍,以上就是為


您介紹使用內部照相功能,有問題請留言或來信告知,感謝。

2012-07-24

Android camera應用(一) - 使用Intent調用其他服務幫忙拍照

使用相機功能應該也是很多寫應用程式的人想學習的

今天介紹用最簡單的方式調用其他有相機功能的服務幫我們拍照

這樣可以省去很多不必要的麻煩,簡化應用程式,下面就開始為您介紹


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" >
<Button
   android:id="@+id/captureimage"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="使用其他服務幫忙拍照 "
   />
<ImageView
   android:id="@+id/imagecaptured"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   />
</LinearLayout>

DemoCameraActivity.java
package jim.demo.camera;

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

public class DemoCameraActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        //調用其他服務拍照按鈕
        Button buttonCamera = (Button)findViewById(R.id.captureimage);
        
        
       
        buttonCamera.setOnClickListener(new Button.OnClickListener(){
   public void onClick(View v) {
    //使用Intent調用其他服務幫忙拍照
     Intent intent_camera = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
     startActivityForResult(intent_camera, 0);
   }
         
        });
        
        
    }
    
    @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      //拍照後顯示圖片
      ImageView iv = (ImageView)findViewById(R.id.imagecaptured);
   if (resultCode == RESULT_OK)
     {
    //取出拍照後回傳資料
    Bundle extras = data.getExtras();
    //將資料轉換為圖像格式
          Bitmap bmp = (Bitmap) extras.get("data");
          //載入ImageView
          iv.setImageBitmap(bmp);
     }
   
     //覆蓋原來的Activity
     super.onActivityResult(requestCode, resultCode, data);
  }
}

執行後畫面




說明:

          使用Intent調用其他服務幫忙拍照主要只有簡單的二行


         Intent intent_camera = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
        startActivityForResult(intent_camera, 0);

第一行是啟用呼叫其他有拍照功能的Intent 
         
第二行是執行呼叫,後面的"0"是參數,可以用來分辨用,下面說明(注)


//拍照後回傳監聽式
 protected void onActivityResult(int requestCode, int resultCode, Intent data)


data是照片資料

requestCode是剛剛回傳的參數 = 0(注)

resultCode判別按下的是確定或取消


注:為什麼會有這個參數,主要是因為不管是抓取手機內圖片或是拍照後


都是會回到onActivityResult這個監聽式,如果沒有用這個參數,就分辨不出是用哪個功能


也就沒辦法去接收相關的資料,拍照和抓取手機內圖片的接收方法是不同的


所以如果無法分辨,只用單一種方式接取是會出現錯誤的


後記:

           一般如果應用程式要做用拍照功能,需要在AndroidManifest.xml內


授予使用照相機權限, <uses-permission android:name="android.permission.CAMERA" />


而使用調用其他服務幫忙拍照不需要加入此權限也能拍照,因為拍照的是其他的服務


所以本身程式不需要加入權限,這是比較特別的地方。

2012-07-23

Android Image應用(一) - 取得手機內的圖檔

今天介紹多媒體應用中兩個重要的圖片、相機應用的其中一個:圖片

如果取得手機內的圖檔應該是要做有關多媒體應用程式常會遇到的事

下面就開始實作如果取得手機內的圖檔資料


main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    >  
   <Button   
        android:id="@+id/b01"  
        android:layout_width="fill_parent"   
        android:layout_height="wrap_content&
    />  
    <ImageView  
        android:id="@+id/iv01"  
        android:layout_width="fill_parent"   
        android:layout_height="wrap_content"   
     />  
</LinearLayout>  



GetPicturesActivity.java
package jim.demo.getpictures;

import java.io.FileNotFoundException;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class GetPicturesActivity extends Activity {
	 /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        //找尋Button按鈕
        Button button = (Button)findViewById(R.id.b01);
        //設定按鈕內文字
        button.setText("選擇圖片");
        //設定按鈕監聽式
        button.setOnClickListener(new Button.OnClickListener(){
	  public void onClick(View v) {
	 	Intent intent = new Intent();
	    //開啟Pictures畫面Type設定為image
	       intent.setType("image/*");
            //使用Intent.ACTION_GET_CONTENT這個Action                                            //會開啟選取圖檔視窗讓您選取手機內圖檔
	        intent.setAction(Intent.ACTION_GET_CONTENT); 
	    //取得相片後返回本畫面
	        startActivityForResult(intent, 1);
	  }
        	
        });
    }
    
    //取得相片後返回的監聽式
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
	//當使用者按下確定後
	if (resultCode == RESULT_OK) {
	   //取得圖檔的路徑位置
	   Uri uri = data.getData();
	   //寫log
	   Log.e("uri", uri.toString());
	   //抽象資料的接口
	   ContentResolver cr = this.getContentResolver();
	 try {
	   //由抽象資料接口轉換圖檔路徑為Bitmap
  	   Bitmap bitmap = BitmapFactory.decodeStream(cr.openInputStream(uri));
	   //取得圖片控制項ImageView
	   ImageView imageView = (ImageView) findViewById(R.id.iv01);
	   // 將Bitmap設定到ImageView
	   imageView.setImageBitmap(bitmap);
	  } catch (FileNotFoundException e) {
	    Log.e("Exception", e.getMessage(),e);
	  }
	}
	  super.onActivityResult(requestCode, resultCode, data);
	}
}


執行畫面



後記:

          呼叫android取得手機內圖片很簡單,只要用Intent.ACTION_GET_CONTENT

重點在於取得圖檔後面的處理,因為取得只是取出該圖檔的存放路徑,所以必須經由

抽象接口ContentResolver再把該圖檔轉換為Bitmap,轉換為Bitmap主要是用來餵給imageView


下面是幾種常用可以設定imageView內圖片的型式
          imageView.setImageBitmap(bitmap) //bitmap圖檔型式
  imageView.setImageDrawable(drawable) //drawable圖檔型式
  imageView.setImageResource(resId) //存在應用程式中res/drawable內的圖片
  imageView.setImageURI(uri)//網路圖片路徑

bitmap和drawable是可以互轉,我再另外開一篇介紹bitmap和drawable轉換


有問題再留言或寫信給我,謝謝。

2012-07-22

Android對話方塊(AlertDialog)應用(二) - 自定義對話方塊

上篇基本介紹之後,此篇來為您介紹更為實用的自定義型式對話方塊

自定義對話方塊可以算是個簡單型的Activity,可以讓我們做一此簡單的選取

不用再另外加開一個Activity,再用Intent把資料傳來傳去的很麻煩

下面就用一個實例:點餐系統,實作自定義對話方塊


main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" android:text="@string/welcome" android:gravity="center_horizontal"/>
<Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/btn" android:id="@+id/btn"></Button>
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/textView1" android:text="@string/str2"></TextView>
</LinearLayout>


strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
   <string name="welcome">歡迎光臨蟹堡王</string>
    <string name="app_name">點餐系統</string>
    <string name="btn">進入點餐系統</string>
    <string name="str2">您點的餐點有:</string>
</resources>

OrderingsystemActivity.java
package com.orderingsystem;


import android.app.AlertDialog; 
import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.DialogInterface.OnMultiChoiceClickListener;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class OrderingsystemActivity extends Activity {
	 //複選框項目  
	public String[] choices={"美味蟹堡","義式香腸堡","蔬菜水果堡","香蕉潛艇堡","香烤雞肉堡"};
	 //Check判斷,注意數量比較和複選框內數量相同
	public boolean[] chsBool = {false,false,false,false,false};
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        Button btn = (Button)findViewById(R.id.btn);
        btn.setOnClickListener(new Button.OnClickListener(){
			@Override
			public void onClick(View v) {
				   
                 //包含多個選項及複選框的對話框  
				AlertDialog  dialog = new AlertDialog.Builder(OrderingsystemActivity.this)
				.setIcon(android.R.drawable.btn_star_big_on)
				.setTitle("您點的餐點有:")  
				.setMultiChoiceItems(choices, chsBool, multiClick)
                .setPositiveButton("確認", onclick)
                .setNegativeButton("離開",  onclick).create(); 
				dialog.show();  
			}
        	
        });
    }
    
 // 對話複選框事件監聽器 
    
    OnMultiChoiceClickListener multiClick = new OnMultiChoiceClickListener(){  
        @Override  
        public void onClick(DialogInterface dialog, int which, boolean isChecked) {  
            //記錄選取的項目
        	chsBool[which]=isChecked;  
        }  
          
    };  
    
    // 對話框按鈕點擊事件監聽器 
      
   OnClickListener onclick = new OnClickListener() {  
	   
 	@Override
 	public void onClick(DialogInterface dialog, int which) {  
         switch (which) {  
             case Dialog.BUTTON_NEGATIVE:  
                 Toast.makeText(OrderingsystemActivity.this, "暫時不點了!",  
                         Toast.LENGTH_LONG).show();  
                 break;  
             case Dialog.BUTTON_POSITIVE:  
                 //點選確認時寫到"你點的餐點有:"後面
            	 TextView Ans = (TextView)findViewById(R.id.textView1);
            	 String selectedStr = ""; 
            	 for(int i=0; i<chsBool.length; i++) { 
            		 if (chsBool[i]==true)
            		 {
            			//加入"\n"自動換行
            			 selectedStr = selectedStr + "\n" +  choices[i];
            		 }
            	 }
            	 Ans.setText("您點的餐點有:" + selectedStr);
                 break;  
         }  
 	}
   };  
}

執行畫面




後記:

像這種選取的動作使用自定義對話方塊就能簡單的完成

不用再麻煩的使用Activity,畫面比較複雜時才需另開一個Activity


不然如果是簡單的選取,其實用這個就綽綽有餘了。

Android對話方塊(AlertDialog)應用(一) - 基本型及自定義按鈕

今天介紹的是也蠻常用的對話方塊AlertDialog

此功能就如同window上的MessageBox一樣

只是比它還強大一點,因為AlertDialog除了基本的訊息和設定按鈕外


它也能變成自定義對話方塊,自由改變AlertDialog內容


自定義對話方塊下篇再來說明,此篇先介紹基本型的就好

廢話不要太多,直接貼出程式碼和說明:

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" >

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="訊息方塊" />

</LinearLayout>

DemoAlertDialogActivity.java
package jim.demo.alertdialog;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class DemoAlertDialogActivity extends Activity {
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        //跳出對話方塊的按鈕
        Button btn = (Button)findViewById(R.id.button1);
        
        btn.setOnClickListener(new Button.OnClickListener(){
	  @Override
	  public void onClick(View v) {
				   
          /*基本型對話方塊
	    setIcon:設置Icon圖片,我是使用內建圖片
	    setTitle:設置標題
	    setmessage:設置內容*/
	  Builder  dialog = new AlertDialog.Builder(DemoAlertDialogActivity.this)
	  .setIcon(android.R.drawable.btn_star_big_on)
	  .setTitle("標題")  
	  .setMessage("我只是個內容");
	  dialog.show();  
	  }
        	
        });
    }
}


畫面



自定義按鈕
package jim.demo.alertdialog;


import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class DemoAlertDialogActivity extends Activity {
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        //跳出對話方塊的按鈕
        Button btn = (Button)findViewById(R.id.button1);
        
        btn.setOnClickListener(new Button.OnClickListener(){
			@Override
			public void onClick(View v) {
				   
               /*基本型對話方塊
				 setIcon:設置Icon圖片,我是使用內建圖片
				 setTitle:設置標題
				 setmessage:設置內容*/
				Builder  dialog = new AlertDialog.Builder(DemoAlertDialogActivity.this)
				.setIcon(android.R.drawable.btn_star_big_on)
				.setTitle("標題")  
				.setMessage("我只是個內容");
				
				//建立三個按鈕的監聽式
				 DialogInterface.OnClickListener Click = new DialogInterface.OnClickListener()
				 {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						//which可以用來分辨是按下哪一個按鈕
						 switch (which) {
						 case Dialog.BUTTON_POSITIVE:  
							 //快顯訊息
							 Toast.makeText(DemoAlertDialogActivity.this, "左邊按鈕",  
			                         Toast.LENGTH_SHORT).show();
							 break; 
						 case Dialog.BUTTON_NEUTRAL:  
							//快顯訊息
							 Toast.makeText(DemoAlertDialogActivity.this, "中間按鈕",  
			                         Toast.LENGTH_SHORT).show();
							 break; 
						 case Dialog.BUTTON_NEGATIVE:  
							//快顯訊息
							 Toast.makeText(DemoAlertDialogActivity.this, "右邊按鈕",  
			                         Toast.LENGTH_SHORT).show();
							 break; 
						 }
					}
					 
				 };
				 
				 dialog.setPositiveButton("左邊按鈕",Click );
				 dialog.setNeutralButton("中間按鈕",Click );
				 dialog.setNegativeButton("右邊按鈕",Click );
				dialog.show();  
			}
        	
        });
    }
}


畫面


後記:

AlertDialog在Android手機應用程式中還蠻常用到的

因為如果只是一個簡單的選取而不需要另外開Activity的話

基本上都會用AlertDialog直接代替,也就是說AlertDialog除了


可顯示訊息外,還可以當做一個簡單的Activity來用


但這就要用到自定義的方式才處理,下面一篇就來為您介紹


自定義的方式顯示對話方塊它的實例運用。


2012-07-20

Android列表(ListView)應用(二) - 自定義列表

列表(ListView)的應用上,很少是簡簡單單而已xd,很多都是要加東加西,又是加圖片

又是加標題、加內容的,所以事情很常不是我們想的那麼簡單的xd,這時就一定要用到

自定義這個東西,自定義顧名思義就是隨便您定,只要您高興、您開心,愛怎麼定都可以

方便是很方便,不過相對的會比較複雜一些,既然會需要用到,那我們就來看看怎麼做吧!


首先想要自定義的都需要多一個模板,所以新增一個List.xml

adapter.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="horizontal" 
	android:layout_width="fill_parent"
	android:layout_height="fill_parent">
    <ImageView
        android:id="@+id/MyAdapter_ImageView_icon"
        android:layout_width="110dp"
        android:layout_height="70dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="5dp"
    />
 <LinearLayout android:orientation="vertical"
		android:layout_width="wrap_content" 
		android:layout_height="wrap_content">

     <TextView
         android:id="@+id/MyAdapter_TextView_title"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginLeft="20dp"
         android:textColor="#ffbf00" />
      
    <TextView
        android:id="@+id/MyAdapter_TextView_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="15dp"
        android:textColor="#FFFFFFFF" />

  </LinearLayout>  
</LinearLayout>


新增一個適配器,也是資料的橋接器MyAdapter,說明資料應該對應到模板的哪個位置
MyAdapter.java
package jim.demo.listview;

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

public class MyAdapter extends BaseAdapter {

	private LayoutInflater myInflater;
    CharSequence[] title = null;
    CharSequence[] info = null;
    
    public MyAdapter(Context ctxt, CharSequence[] title, CharSequence[] info){
        myInflater = LayoutInflater.from(ctxt);
        this.title = title;
        this.info = info;
    }
    
	@Override
	public int getCount() {
		 return title.length;
	}

	@Override
	public Object getItem(int position) {
		 return title[position];
	}

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

	@Override
	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;
	}

	//自訂類別,表達個別listItem中的view物件集合。
    class ViewTag{
        ImageView icon;
        TextView title;
        TextView info;
    
        public ViewTag(ImageView icon, TextView title, TextView info){
            this.icon = icon;
            this.title = title;
            this.info = info;
        }
    }
}

再來當然是我們的主程式DemoListViewActivity
修改繼承自ListActivity,也可以不改變繼承,延用預設的Activity
只是還要用findViewById去找到該ListView再把資料載入而已
如果您的頁面上只是很單純的一個ListView,就直接用ListActivity會比較快

MyAdapter.java
package jim.demo.listview;

import android.app.ListActivity;
import android.os.Bundle;

public class DemoListViewActivity extends ListActivity {
    
	private String[] mtitle = new String[]{"台北","台中","高雄"} ;
	private String[] minfo =  new String[]{"台北101.故公博物院.中正記念堂","都會公園.高美濕地.大坑風景區","西子灣.英國領事館.愛河"};
	
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
                
        //標題資料
        CharSequence[] Mtitle = mtitle;
        //內容
        CharSequence[] Minfo = minfo;
        //載入列表中,new出MyAdapter時帶入所需"標題"."內容"資料
        setListAdapter(new MyAdapter(this, Mtitle, Minfo));
        
    }
}

執行後畫面

後記:

           自定義ListView的重點在於adapter.xml這個模板及MyAdapter.java這個適配器

只要修改模板及適配器就能做出自己想要的列表形式,這個對剛接觸android程式設計

的人來說可能會有點不太習慣這樣的設計模式,但android很多地方都是這種設計模式的

只要是自定義的地方,大多都會是此種形式,就為你介紹到此,謝謝。

2012-07-18

Android列表(ListView)應用(一) - 基本

列表(ListView)是蠻常會用到的一個控制元件,在很多的應用程式內常常會看到此一控制元件

我就來為你介紹請怎麼使用列表(ListView)

新增專案我這邊就直接跳過了,不了解的可以參考其他篇文章

我們直接在main.xml的設計介面中拉進一個ListView



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" >

    <ListView
        android:id="@+id/listView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

</LinearLayout>

DemoListViewActivity.java
package jim.demo.listview;

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

public class DemoListViewActivity extends Activity {
    
 private ListView listcity;
 private String catsName[]={"台北","桃園","新竹","苗栗","台中","彰化","雲林","嘉義","台南","高雄","屏東","台東","花蓮","宜蘭"};
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        //指定該列表
        listcity=(ListView)findViewById(R.id.listView1);
        //這是簡單的快速寫法,直接設定資料橋接器ArrayAdapter到ListView內
        listcity.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1 , catsName));
    }
}

執行後畫面

後記:
          我們可以看到,在這種需要和資料連結的控制項,都會有ArrayAdapter橋接器


橋接器是Android中做為資料和控制項連結之用。


ArrayAdapter(this,android.R.layout.simple_list_item_1 , catsName)中我們可以


看到android.R.layout.simple_list_item_1,這個是內建的ListView設計樣式,你可以試著


改變為android.R.layout.simple_list_item_multiple_choice,你會發現ListView就會出現不


同之變化了,這是最基本的ListView,後續我們再來做點變形,感謝您的收看。

2012-07-17

Android快顯訊息(Toast)應用(二) - 自定義快顯

上一章,快顯訊息(Toast)是用默認的型式呈現,這一章中我們來使用自定義方式呈現我們

自己所想要的快顯訊息(Toast)

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" >

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="默認樣式" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="自定義樣式" />

</LinearLayout>

注意:因為是自定義的,所以必須新增一個自定義樣式的模板
custom.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_height="wrap_content" android:layout_width="wrap_content"
 android:background="#ffffffff" android:orientation="vertical"
 android:id="@+id/llToast" >
 <TextView
  android:layout_height="wrap_content"
  android:layout_margin="1dip"
  android:textColor="#ffffffff"
  android:layout_width="fill_parent"
  android:gravity="center"
  android:background="#bb000000"
  android:id="@+id/tvTitleToast" />
 <LinearLayout
  android:layout_height="wrap_content"
  android:orientation="vertical"
  android:id="@+id/llToastContent"
  android:layout_marginLeft="1dip"
  android:layout_marginRight="1dip"
  android:layout_marginBottom="1dip"
  android:layout_width="wrap_content"
  android:padding="15dip"
  android:background="#44000000" >
  <ImageView
   android:layout_height="wrap_content"
   android:layout_gravity="center"
   android:layout_width="wrap_content"
   android:id="@+id/tvImageToast" />
  <TextView
   android:layout_height="wrap_content"
   android:paddingRight="10dip"
   android:paddingLeft="10dip"
   android:layout_width="wrap_content"
   android:gravity="center"
   android:textColor="#ff000000"
   android:id="@+id/tvTextToast" />
 </LinearLayout>
</LinearLayout>



DemoToastActivity.java
package jim.demo.toast;

import android.app.Activity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class DemoToastActivity extends Activity{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        
        Button type = (Button)findViewById(R.id.button1);
        Button type2 = (Button)findViewById(R.id.button2);
        //建立"默認樣式"的監聽式
        View.OnClickListener listener1 = new View.OnClickListener() {

   @Override
   public void onClick(View arg0) {
   //要顯示的訊息 
   Toast.makeText(getApplicationContext(), "默認樣式",
   Toast.LENGTH_SHORT).show();
   }  
        };
        //加入默認樣式按鈕內
        type.setOnClickListener(listener1);
        
        //建立"完全自定義"的監聽式
        View.OnClickListener listener2 = new View.OnClickListener() {

   @Override
   public void onClick(View arg0) {
   //要顯示的訊息 
    //自定義樣式必須有一個自定義的樣板
    LayoutInflater inflater = getLayoutInflater();
    View layout = inflater.inflate(R.layout.custom,
   (ViewGroup) findViewById(R.id.llToast));
      
    //自定義樣板中的圖片
    ImageView image = (ImageView) layout
     .findViewById(R.id.tvImageToast);
       
    //載入圖片,我用內建icon(android.R.drawable.sym_def_app_icon)
    image.setImageResource(android.R.drawable.sym_def_app_icon);
       
    //標題文字
    TextView title = (TextView) layout.findViewById(R.id.tvTitleToast);
    title.setText("我是標題");
       
    //內容文字
    TextView text = (TextView) layout.findViewById(R.id.tvTextToast);
    text.setText("自定義樣式");
       
    //快顯設定
    Toast toast = null;
    toast = new Toast(getApplicationContext());
       
    //快顯位置
    toast.setGravity(Gravity.RIGHT | Gravity.TOP, 12, 40);
     
    //顯示時間(長時間為Toast.LENGTH_LONG,短時間為Toast.LENGTH_SHORT)
    toast.setDuration(Toast.LENGTH_LONG);
      
    //載入自定樣式
    toast.setView(layout);
       
    //顯示快顯訊息
    toast.show();
   }  
        };
        //加入"自定義樣式"按鈕內
        type2.setOnClickListener(listener2);
    }
}

執行後畫面




後記:

  自定義樣式最大的不同在於必須多加一個模板custom.xml,做為我們想自定快顯訊息內

樣式之用,這個做法在Android的蠻多地方如果想要自定樣該控制項都是這樣用的

都是必須新增一個模板,再對該模板做您想做的事,這樣的做法其實還蠻方便的

而且彈性也很大,以上就是為你做的自定樣快顯介紹,說明都寫在程式碼內了

如有不明白請留言,感謝。

2012-07-16

Android快顯訊息(Toast)應用(一) - 基本

在應用程式裡,在做了某項工作後都需要show出訊息通知使用者

所以此篇我們就來介紹快顯訊息(Toast)該怎麼使用

一開始我們還是先建立起一個Demo用的Android Project名叫:DemoToast


進入main.xml拉兩個按鈕Button就好


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" >

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="新增" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="更新" />

</LinearLayout>

DemoToastActivity.java
package jim.demo.toast;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class DemoToastActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        
        Button insert = (Button)findViewById(R.id.button1);
        Button update = (Button)findViewById(R.id.button2);
        //建立insert的監聽式
        View.OnClickListener listener1 = new View.OnClickListener() {

 @Override
 public void onClick(View arg0) {
 //要顯示的訊息 
   Toast.makeText(getApplicationContext(), "新增成功!",
   Toast.LENGTH_SHORT).show();
   }  
        };
        //加入insert按鈕內
        insert.setOnClickListener(listener1);
        
        //建立update的監聽式
        View.OnClickListener listener2 = new View.OnClickListener() {

 @Override
 public void onClick(View arg0) {
 //要顯示的訊息 
   Toast.makeText(getApplicationContext(), "更新成功!",
   Toast.LENGTH_SHORT).show();
 }
  
        };
        //加入update按鈕內
        update.setOnClickListener(listener2);
    }
}

執行後畫面



後記:

           你只要在想完成的動作後面加上
Toast.makeText(getApplicationContext(), "更新成功!",Toast.LENGTH_SHORT).show();
然後中文字改為你想要的訊息就可以了,當然也可以是個字串變數,此為基本型
的快顯訊息,後面會再為您介紹其他的變化。