2010年11月14日 星期日

[Android] 如何在Layout檔案中使用自訂的View



如果現在在Layout檔案裡面拉了一個View的物件 , 但是想對這個View進行修改的動作自訂成我們想要的樣式和功能 , 假設現在在main.xml檔案裡面拉了一個VideoView





  




如果我們想要修改這個ViedoView的樣貌和功能的話 , 那必定要寫一個class extends VideoView
程式碼如下:
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.VideoView;

public class CustomVideoView extends VideoView
{

 public CustomVideoView(Context context)
 {
  super(context);
  // TODO Auto-generated constructor stub
  Log.d("Go to", "Context context");
 }

 public CustomVideoView(Context context, AttributeSet attrs)
 {
  super(context, attrs);
  // TODO Auto-generated constructor stub
  Log.d("Go to", "Context context, AttributeSet attrs");
 } 
 //可以發現進入的是CustomVideoView(Context context, AttributeSet attrs)這個建構子
    //所以留著覆寫他 , 否則程式會強制關閉
}


接著我們要修改main.xml裡原本VideoView的定義名稱







那在Activity中該如何取用呢?


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

public class CustomVideoViewTest extends Activity
{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        CVView=(CustomVideoView)findViewById(R.id.VideoView);
    }
    
    CustomVideoView CVView;
}



大功告成!!!!

[Android] 如何自訂ListView的內容 (使用SimpleAdapter同時加入Image和Text)



這篇的內容是修改自前面的 [Android Tips] 如何自訂ListView的內容 (使用ArrayAdapter同時加入Image和Text)這篇主旨是要使用SimpleAdapter來實現 , 此外可以動態的新增和刪除資料 , 首先Layout檔案的內容沒有更改和之前的文章一樣 , 至於程式碼的部分如下




package com.android;

import java.util.ArrayList;
import java.util.HashMap;
import android.app.TabActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TabHost;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;


public class TabWidgetListViewTest extends TabActivity implements Button.OnClickListener
{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    
        EPlayer = getResources().getStringArray(R.array.EPlayer);
        WPlayer = getResources().getStringArray(R.array.WPlayer);
        Postion = getResources().getStringArray(R.array.Position);
        //分別將東西區先發球員和球員位置的資料當作ListView 的內容        
        //res/values/strings.xml 已經宣告了string-array
        
        icons = new int[]{R.drawable.marketplace , R.drawable.email , R.drawable.contacts , R.drawable.mms , R.drawable.application};
        
        //首先我們先處理ListView所要呈現的內容            
        
        ListTextImageItemEast = new ArrayList[HashMap[String, Object]();  
        //宣告ArrayList裡面的元素為HashMap
        
        for(int i = 0;i < 5;i++)  
        {  
          HashMap[String, Object] map = new HashMap[String, Object](); 
          // key使用String變數 , element存放Object元素
          map.put("ImageItem", icons[i]); 
          map.put("PlayerItem",EPlayer[i]); 
          map.put("PostionItem", Postion[i]);  
          ListTextImageItemEast.add(map); // 加入到ArrayList中 
        }
        
        ListEPlayer = (ListView) findViewById(R.id.ListViewEast);
        SAE = new SimpleAdapter(this,   
          ListTextImageItemEast, //使用的ArrayList
                R.layout.listviewrow, //相對應的Layout檔案
                new String[] {"ImageItem","PlayerItem","PostionItem"},   
                new int[] {R.id.icon,R.id.name,R.id.position});  
                // 每個HashMap中的Title對應到RowView裡的subView Id
        ListEPlayer.setAdapter(SAE);  
        ListEPlayer.setOnItemClickListener(OICL);
        //然後再判斷Item點擊事件
        
        ListEPlayer.setTextFilterEnabled(true);
        //添加按鍵過濾的功能
         
        
        ListWPlayer = (ListView) findViewById(R.id.ListViewWest);
        ListTextImageItemWest = new ArrayList[HashMap[String, Object]]();  
        
        for(int i = 0;i < 5;i++)  
        {  
          HashMap[String, Object] map = new HashMap[String, Object]();  
          map.put("ImageItem", icons[i]);
          map.put("PlayerItem",WPlayer[i]);  
          map.put("PostionItem", Postion[i]);  
          ListTextImageItemWest.add(map);  
        }
        
        ListWPlayer = (ListView) findViewById(R.id.ListViewWest);
        SAW = new SimpleAdapter(this,   
          ListTextImageItemWest,
                R.layout.listviewrow,
                new String[] {"ImageItem","PlayerItem", "PostionItem"},   
               
                new int[] {R.id.icon,R.id.name,R.id.position});  
 
        ListWPlayer.setAdapter(SAW);  
        ListWPlayer.setOnItemClickListener(OICL);
        ListWPlayer.setTextFilterEnabled(true);
        //對另一個ListView做同樣的操作載入西區先發球員的資料
        
        mTabHost = getTabHost();
        //我們的TabWidgetListViewTest 是繼承 TabActivity的
   //所以這邊是透過他的method getTabHost()
   //來取得我們在main.xml中宣告的TabHost   
        
        mTabHost.addTab(mTabHost.newTabSpec("tab_test1")
          //將Tab加入我們要的資料
          .setIndicator("東區先發球員" , this.getResources().getDrawable(R.drawable.aemail))
          //在Tab上標示名稱和加上Icon
          .setContent(R.id.ListViewEast));
                //Tab內容為main.xml檔案中宣告的ListView , 而ListView的內容我們先前已經處理好了
        
        mTabHost.addTab(mTabHost.newTabSpec("tab_test2").setIndicator("西區先發球員" , this.getResources().getDrawable(R.drawable.browser)).setContent(R.id.ListViewWest));
         
        mTabHost.setCurrentTab(0);
        //預設該顯示哪個Tab的資料
        
        Button buttongernerate = (Button) findViewById(R.id.buttongernerate);
        Button buttondelete = (Button) findViewById(R.id.buttondelete);
        buttongernerate.setOnClickListener(this);
        buttondelete.setOnClickListener(this);
        //對新增和刪除按鈕設置點擊事件
    }
    
    TabHost mTabHost;
    ListView ListEPlayer , ListWPlayer , TempLV;
    SimpleAdapter SAE , SAW , TempA;
    String[] EPlayer , WPlayer , Postion;
    int[] icons;
    ArrayList[HashMap[String, Object]] ListTextImageItemEast;
    ArrayList[HashMap[String, Object]] ListTextImageItemWest;
    
    HashMap TempHMap;    
    boolean Choose = false; //按鈕開關
    int TempPosition;
    
    public OnItemClickListener OICL =  new OnItemClickListener()
    {
  @Override
  public void onItemClick(AdapterView[?] parent, View view, int position, long id)
  {
   String where;
   if(parent.equals(ListEPlayer))
   where = "你選擇了東區的";   
   else
   where = "你選擇了西區的";
   
   TempHMap = (HashMap [String, Object]) parent.getItemAtPosition(position);
   
   setTitle(where + ((TextView)view.findViewById(R.id.position)).getText() 
            + ":" + TempHMap.get("PlayerItem"));
   //這邊提供兩種方法來取得被點選RowView的內容
   
   /*
    * getItemAtPosition(position)在官網的敘述是這樣的
    * Gets the data associated with the specified position in the list.
    * 上面所說的the data就是當初我們 super(context, textViewResourceId, itemname);
    * 所回傳的itemname了 , 可以參考父類別ArrayAdapter的建構子
    * ArrayAdapter(Context context, int textViewResourceId, T[] objects)
    * */
   TempLV = (ListView) parent;
   TempPosition = position;
   Choose = true;
  }  
    };

 @Override
 public void onClick(View ButtonView)
 {
  // TODO Auto-generated method stub
  
  if(Choose)
  {
   switch(ButtonView.getId())
   {
       case R.id.buttongernerate: //新增所選擇的資料           
     if(TempLV.equals(ListEPlayer))
     {
      ListTextImageItemEast.add(TempHMap);;
      TempA = SAE;
     }
     else
     {
      ListTextImageItemWest.add(TempHMap);;
      TempA = SAW;
     }
     TempA.notifyDataSetChanged();
      //提醒SimpleAdapter作資料得更新
    break;
    
       case R.id.buttondelete: //刪除所選擇的資料
        if(TempLV.equals(ListEPlayer))
     {
         ListTextImageItemEast.remove(TempPosition);
      TempA = SAE;
     }
     else
     {
      ListTextImageItemWest.remove(TempPosition);
      TempA = SAW;
     }
        TempA.notifyDataSetChanged();
       break;
   }
  }
  Choose = false;
  //Log.d("Choose" , Choose+"");
 }
}

當你點選了ListView中的Item之後 , 新增或是刪除的按鈕才會發揮作用


此外為了避免 HTML Tag is broken的錯誤 , 所以使用[] 代替<> , 程式要能work需要作符號的修改



相關文章:

[Android Tips] 如何在TabWidget中加入ListView


2010年11月8日 星期一

[Android] 如何隱藏Title Bar和Notification Bar



有時候想呈現繪圖背景或是想播放Video影像時 , 會想在狹小的螢幕多爭取一點空間
這時候乾脆就把Title Bar和Notification Bar隱藏獲取更多螢幕空間吧!!!! 步驟很簡單


先看下面的圖片 , 這時候Title Bar和Notification Bar都還在



接下來為了要隱藏Title Bar這邊有幾個方法 , 首先可以在AndroidMenifest.xml , 在對Activity 作屬性定義的時候可以加上 android:theme 來設置 Activity 的主題 


    
        
                  
                                    
            
                
                
            
        
    
 

仔細看可以發現 AndroidMenifest.xml多了兩行註解
<!-- android:theme="@style/myThemeOne" -->
<!-- android:theme="@style/myThemeTwo" -->
這是我們自定義的style , 使用他們來替換都可以得到一樣的效果 , 而style Resource是要放置在res/values下的 , 可以參考這邊 , 在這邊我把
@style/myThemeOne放在原本的string.xml檔案裡

android:theme="@style/myThemeTwo放在style.xml裡 , 但是都必須放在res/values下


    Hello World, Test
    ThereIsTitleBar    
     




 



成功之後就會出現下圖的結果





如果說還想把Notification Bar隱藏的話 , 只要加上這段程式碼

public class NoTitleBar extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        //這行程式碼也可以隱藏Title Bar但是位置要放對
        setContentView(R.layout.main);        
        //Remove notification bar
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
     //this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
     }
}


成功之後如下



連Notification Bar都消失了

其實想達到同樣的效果還可以這樣 , 在AndroidMenifest.xml Activity Theme這個定義
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"

另外下面這篇文章對於 Android提供的Theme資料整理的很詳細 , 很棒


2010年10月30日 星期六

[Android] 如何自訂ListView的內容 (使用ArrayAdapter同時加入Image和Text)



這邊的程式碼延續上一篇文章的結果 , 如果說我們現在想要在ListView中每一個row
所呈現的資料內容更豐富些 , 不單單只有文字還想加入圖片 , 並且選取ListView裡的
資料時能觸發Click事件 , 如下圖TitleBar會顯示我們所選擇的球員






首先我們要自訂ListView中row的資料呈現內容 , 上圖是在左邊擺了一個ImageView然後右上方擺一個TextView , 下方也擺一個TextSize較小的TextView , 為了達成這樣的效果 , 我們必須把想呈現的佈局方式寫在一個Layout xml檔案裡 , 如下


    
    
                              
        
                
    


將row裡該呈現的佈局都搞定之後 , 接下來就是程式碼的部分


import android.app.TabActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TabHost;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;


public class TabWidgetListViewTest extends TabActivity
{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    
        EPlayer = getResources().getStringArray(R.array.EPlayer);
        WPlayer = getResources().getStringArray(R.array.WPlayer);
        Postion = getResources().getStringArray(R.array.Position);
        // 分別將東西區先發球員和球員位置的資料當作ListView 的內容        
        // res/values/strings.xml 已經宣告了string-array
        
        icons = new int[]{R.drawable.marketplace , R.drawable.email , R.drawable.contacts , R.drawable.mms , R.drawable.application};
        
        
        // 首先我們先處理ListView所要呈現的內容
              
        
        ListEPlayer = (ListView) findViewById(R.id.ListViewEast);
        ListEPlayer.setAdapter(new IconTextAdapter(this , android.R.layout.simple_list_item_1 , EPlayer , Postion , icons));
        ListEPlayer.setOnItemClickListener(OICL);
        
        // 這邊的例子選用原本的範本 android.R.layout.simple_list_item_1 
        // 然後都丟入我們自己的接收器IconTextAdapter中 , 參數多了一個String[] Position
        // 然後再判斷Item點擊事件
        
        
        ListEPlayer.setTextFilterEnabled(true);
        //添加按鍵過濾的功能
         
        
        ListWPlayer = (ListView) findViewById(R.id.ListViewWest);
        ListWPlayer.setAdapter(new IconTextAdapter(this , android.R.layout.simple_list_item_1 , WPlayer , Postion , icons));
        ListWPlayer.setOnItemClickListener(OICL);
        ListWPlayer.setTextFilterEnabled(true);
        //對另一個ListView做同樣的操作載入西區先發球員的資料
        
        mTabHost = getTabHost();
        //我們的TabWidgetListViewTest 是繼承 TabActivity的
 //所以這邊是透過他的method getTabHost()
 //來取得我們在main.xml中宣告的TabHost
 
        
        mTabHost.addTab(mTabHost.newTabSpec("tab_test1")
          //將Tab加入我們要的資料
          .setIndicator("東區先發球員" , this.getResources().getDrawable(R.drawable.aemail))
          //在Tab上標示名稱和加上Icon
          .setContent(R.id.ListViewEast));
                //Tab內容為main.xml檔案中宣告的ListView , 而ListView的內容我們先前已經處理好了
        
        mTabHost.addTab(mTabHost.newTabSpec("tab_test2").setIndicator("西區先發球員" , this.getResources().getDrawable(R.drawable.browser)).setContent(R.id.ListViewWest));
         
        mTabHost.setCurrentTab(0);
        //預設該顯示哪個Tab的資料
    }
    
    TabHost mTabHost;
    ListView ListEPlayer , ListWPlayer;
    String[] EPlayer , WPlayer , Postion;
    int[] icons;
    
    public class IconTextAdapter extends ArrayAdapter
    {
        int[] icons;
        String[] textname , textpostion;
        
  public IconTextAdapter(Context context, int textViewResourceId, String[] itemname, String[] itempostion , int[] images)
  {
   super(context, textViewResourceId, itemname);
   icons = images;
   textname = itemname;
   textpostion = itempostion;
  }
  
  public View getView(int position, View convertView, ViewGroup parent)
   {
            View rowview = convertView;
            if (rowview == null) {
                    LayoutInflater inflater = getLayoutInflater();
                    rowview = inflater.inflate(R.layout.listviewrow, parent, false);
                    //為了要把xml所描述的Layout轉變為View , 也就是我們要的rowview
                    //所以必須使用LayoutInflater來轉化 , 而要取得LayoutInflater的Instance方式還包括
                    //LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    //接著再使用inflate (int resource, ViewGroup root, boolean attachToRoot)
                    //傳回我們要的rowview
            }
            TextView Nmae = (TextView) rowview.findViewById(R.id.name);
            Nmae.setText(textname[position]);
                         
            TextView Postion = (TextView) rowview.findViewById(R.id.position);
            Postion.setText(textpostion[position]);
            
            ImageView icon = (ImageView) rowview.findViewById(R.id.icon);
            icon.setImageResource(icons[position]);
            
            // 我們在listviewrow.xml裡已經把ListView中Row的佈局都排好了 
            // 而這裡的rowview可以想成是之前被我們在佈局中組合出來的
            // 現在我們要為rowview裡面的元件設定Text和Icon
            // 最後再回傳rowview作為ListView中每一個row的顯示內容
            
            
            return rowview;
        }
     }

    public OnItemClickListener OICL =  new OnItemClickListener()
    {
  @Override
  public void onItemClick(AdapterView parent, View view, int position, long id)
  {
   String where;
   if(parent.equals(ListEPlayer))
   where = "你選擇了東區的";   
   else
   where = "你選擇了西區的";
   setTitle(where + ((TextView)view.findViewById(R.id.position)).getText() 
            + ":" + parent.getItemAtPosition(position));
   
   // getItemAtPosition(position)在官網的敘述是這樣的
   // Gets the data associated with the specified position in the list.
   // 上面所說的the data就是當初我們 super(context, textViewResourceId, itemname);
   // 所回傳的itemname了 , 可以參考父類別ArrayAdapter的建構子
   // ArrayAdapter(Context context, int textViewResourceId, T[] objects)
   
  }  
    };     
}






相關文章:

[Android] 如何在TabWidget中加入ListView

[Android] 如何在TabWidget中加入ListView



對於設計Android的使用者介面來說 , TabWidget 和 ListView 都是使用頻率很
的View , 在Android 模擬器中也會常常看的到 , 而現在就是想把這兩個View結合
一起呈現 , 如下圖一樣。





分別有東西區先發球員的兩個Tab , 然後內容使用ListView來呈現球員名單
此外在底下再放置兩個Button , 日後可以用來新增刪除資料


首先直接來看 Layout 檔案
    
        
        
            
            
            
                       
                
                
        
        
        
    



這邊Layout佈局的原因可以搭配著官網的Hello , TabWidget 來看, 首先需要TabHost來裝載整個Activity所要呈現的物件 , 而TabHost有兩個必要的元件 , 分別是TabWidget  FrameLayout , 那麼把他放在一個直立方向(Vertical)的LinearLayout 而根據切換到不同的Tab , 我們想要呈現不一樣的內容 , 而這些不一樣的內容就擺在FrameLayout 裡面 , 因為FrameLayout 的佈局本來就有"層次"的概念 , 所以蠻好理解的接著要注意的就是 , TabWidget 的ID一定要是tabs 而 FrameLayout的ID名稱一定要為tabcontent 否則會出錯 , 然後放入兩個ListView , 此外在外面的LinearLayout 中, 再擺一個LinearLayout(水平方向) , 裡面放入兩個Button 就完成 Layout佈局了。


接著回到我們的程式碼中

import android.app.TabActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TabHost;


public class TabWidgetListViewTest extends TabActivity
{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    
        EPlayer = getResources().getStringArray(R.array.EPlayer);
        WPlayer = getResources().getStringArray(R.array.WPlayer);
        // 分別為東西區先發球元的資料要當作ListView 的內容        
        // res/values/strings.xml 已經宣告了string-array
               
        
        //首先我們先處理ListView所要呈現的內容
              
        
        ListEPlayer = (ListView) findViewById(R.id.ListViewEast);
        ListEPlayer.setAdapter(new ArrayAdapter(this , android.R.layout.simple_list_item_1 , EPlayer));
        
        // ListView中Item的內容是需要Adapter來連接的
        // 所以現在把要呈現在ListView中的Item (String[] EPlayer)
        // 和範本 android.R.layout.simple_list_item_1 都丟入接收器ArrayAdapter中
        // 除了ArrayAdapter之外還有許多其他的接受器像是SimpleAdapter等等
        
        
        ListEPlayer.setTextFilterEnabled(true);
        //添加按鍵過濾的功能
         
        
        ListWPlayer = (ListView) findViewById(R.id.ListViewWest);
        ListWPlayer.setAdapter(new ArrayAdapter(this , android.R.layout.simple_list_item_1 , WPlayer));
        ListWPlayer.setTextFilterEnabled(true);
        //對另一個ListView做同樣的操作載入西區先發球員的資料
        
        mTabHost = getTabHost();
        //我們的TabWidgetListViewTest 是繼承 TabActivity的
 //所以這邊是透過他的method getTabHost()
 //來取得我們在main.xml中宣告的TabHost
 
        
        mTabHost.addTab(mTabHost.newTabSpec("tab_test1")
          //將Tab加入我們要的資料
          .setIndicator("東區先發球員" , this.getResources().getDrawable(R.drawable.aemail))
          //在Tab上標示名稱和加上Icon
          .setContent(R.id.ListViewEast));
                //Tab內容為main.xml檔案中宣告的ListView , 而ListView的內容我們先前已經處理好了
        
        mTabHost.addTab(mTabHost.newTabSpec("tab_test2").setIndicator("西區先發球員" , this.getResources().getDrawable(R.drawable.browser)).setContent(R.id.ListViewWest));
         
        mTabHost.setCurrentTab(0);
        //預設該顯示哪個Tab的資料
    }
    
    TabHost mTabHost;
    ListView ListEPlayer , ListWPlayer;
    String[] EPlayer , WPlayer;
}

如果對於註解中提到的按鍵過濾不清楚的話 , 可以參考盧老師的
如何在 ListView 上加上按鍵過濾的功能這篇文章


到這邊就完成了一開始圖片所呈現的佈局了 , 可是我們可以發現最下面一筆資料會被
Button擋住 , 造成我們需要移動捲軸 , 可不可以把每一列的TextView改小呢?
偶然看到盧老師的這篇文章:親愛的,我把 AutoCompleteTextView 縮小了
裡面提到把Android Native Layout:simple_list_item_1.xml 抓出來修改
就可以對TextView的格式作更改了 , 所以我們可以自己做一個TextView格式
的xml檔案 , 然後擺在res/layout中當範本 , 這個檔案可以在下面的目錄找到
Your_Android_SDK_Location\platforms\android-Version\data\res\layout


原始的 simple_list_item_1 內容如下



對內容稍作修改 , 順便修改檔名




接著把程式碼稍作修改

ListEPlayer.setAdapter(new ArrayAdapter(this , R.layout.simplelistitem1 , EPlayer));
ListWPlayer.setAdapter(new ArrayAdapter(this , R.layout.simplelistitem1 , WPlayer));

下圖是修改後的佈局結果




下一篇文章會提到在對ListView每一列作修改不要只單純顯示文字 , 另外再對選擇item作事件判斷




相關文章:

[Android] 如何自訂ListView的內容 (使用SimpleAdapter同時加入Image和Text)

[Android] 如何自訂ListView的內容 (使用ArrayAdapter同時加入Image和Text)

Google Analytics