素人プログラマ奮闘記

javaの初心者がAndroidのことを独学で勉強しつつ、メモを残していきます。

リストビュー(ListView)について勉強してみる(1)

今回はリストビューについて勉強します。
画面に何らかのデータを一覧で表示する際に使用します。
下記のようなリストを表示する画面を作成していきます。



1.ArrayAdapterクラスの使い方

準備としてListViewを使用するにあたって、ArrayAdapterクラスのことを勉強していきます。
ArrayAdapterクラスは、データの一覧をViewに渡すために使う、箱のようなクラスです。
ArrayAdapterクラスを使用するには、ArrayAdapterクラスのコンストラクタを用いてArrayAdapterクラスのオブジェクトを作成します。

ArrayAdapterクラスのコンストラクタを見ていきましょう
ArrayAdapter(Context context, int textViewResourceId, T[] objects);
第一引数:context(Contextオブジェクトを指定します、大体はthisでOKです)
第二引数:textViewResourceId(登録されているTextViewのリソースIDを指定します)
第三引数:objects(Viewに渡すオブジェクトのデータを指定します。)
使用例として下記を参考にしてください。


//配列準備	
String[] members = 
		{ "お茶","ビール","焼酎","カクテル","ウイスキー" };	
//ArrayAdapterクラス作成	
ArrayAdapter<String> adapter = 
	new ArrayAdapter<String> (this,
		android.R.ListViewTest, members);	

これでリストビューに一覧が表示されます。

2.プロジェクト作成

プロジェクトの作成をします。
プロジェクト名:TestListView、アクテビティ名:MainActivity、レイアウト名:main、にして作成します。

3.文字列定義

次にアプリで使用する文字列を定義します。(定義方法はStrings.xmlについての勉強を参照)
・飲み物リスト(drink_list)
・終了(project_end)

4.レイアウト作成(main.xml)

メニュー画面(MainActivity)の画面レイアウトを作成します。
画面上段にTextView、画面中段にListView、画面下段にButtonを配置するのですが、いやーはまっちゃいました。
どうしてもListViewのしたにボタンを配置するレイアウトになりません。

はまり中のレイアウト



単純にLinearLayout3三個並べて上から順に表示しようと配置したのですが
どうしても一番下部のボタンが表示されませんヽ(`Д´)ノ



色々調べた結果
ListViewの下にボタンを配置したい場合は少し工夫がひつようみたいです。

http://d.hatena.ne.jp/windbell/20120701
上のサイトを参考にレイアウトを下記のように修正しました。



これでうまく表示されました(∩´∀`)∩



以下にmain.xmlのソースを示します。


<LinearLayout		
    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"		
    android:paddingBottom="@dimen/activity_vertical_margin"		
    android:paddingLeft="@dimen/activity_horizontal_margin"		
    android:paddingRight="@dimen/activity_horizontal_margin"		
    android:paddingTop="@dimen/activity_vertical_margin"		
    android:orientation="vertical"		
    tools:context=".MainActivity" >        		
	<LinearLayout 	
	    android:layout_width="fill_parent"	
        android:layout_height="wrap_content"		
        android:orientation="horizontal" 		
        android:background="#FFAAFF" > 		
      	<TextView 	
        android:layout_width="fill_parent"		
        android:layout_height="wrap_content" 		
        android:text="@string/drink_list"		
        android:textSize="30sp"		
        android:gravity="center"		
        />		
	</LinearLayout>	
    <LinearLayout 		
	    android:layout_width="match_parent"	
        android:layout_height="match_parent"		
        android:orientation="vertical"		
        android:background="#FFFFAA" 		
        > 		
      	<ListView	
      	    android:id="@+id/drinkListView"	
      	    android:layout_width="match_parent"	
      	    android:layout_height="0dp"	
      	    android:background="#40FF0000"	
      	    android:layout_weight="1"/>	
      	<LinearLayout	
	    	android:id="@+id/linearLayout1"
	    	android:layout_width="fill_parent"
        	android:layout_height="wrap_content"	
        	android:orientation="horizontal"	
        	android:layout_gravity="center"	
        	android:background="#AAFFFF">    	
   	    <Button android:id="@+id/projectEnd"	
        	android:layout_width="fill_parent"	
        	android:layout_height="wrap_content"	
        	android:layout_gravity="bottom"	
        	android:text="@string/project_end" />	
		</LinearLayout>
      		
	</LinearLayout>	
		    
</LinearLayout>	


カテゴリーへ

リストビュー(ListView)について勉強してみる(2)

リストビュー(ListView)について勉強してみる(1)からの続きです

2.MainActivity.java編集

MainActivity.javaを編集していきます。実装する主な機能は下記の4点です。
1.初期表示時のリスト表示
2.リストの項目がクリックされた時にトースト表示
3.リストの項目が長押しされた時にトースト表示
4.終了ボタン押下時の処理

まずは初期リスト表示処理の実装からしていきます。下記にソースを示します。


	ListView drinkListView = null;			
				
	@Override			
	protected void onCreate(Bundle savedInstanceState) {			
		super.onCreate(savedInstanceState);		
		setContentView(R.layout.main);		
		//配列準備		
		String[] members = { "お茶", "ビール", "焼酎", "カクテル","ウイスキー" };		
		//ArrayAdapterクラス作成		
		ArrayAdapter<String> adapter = new ArrayAdapter<String> (this,android.R.layout.simple_expandable_list_item_1, members);		
		drinkListView = (ListView) findViewById(R.id.drinkListView);		
		drinkListView.setAdapter(adapter);		
	}						

初めに、文字列の配列を作ります。これが初期表示のリストになります。
String[] members = { "お茶", "ビール", "焼酎", "カクテル","ウイスキー" };

次にアダプタを作成します
第二引数にandroid.R.layout.simple_expandable_list_item_1を指定していますが、意味は 初めから標準で用意されているListViewレイアウトです。あまり気にしなくてもいいです。おまじないみたいなものです。
ArrayAdapter<String> adapter = new ArrayAdapter<String> (this,android.R.layout.simple_expandable_list_item_1, members);

最後にmain.xmlに配置されたコントロールをプログラム内から操作できるようにします。
drinkListView = (ListView) findViewById(R.id.drinkListView);

ListViewクラスのsetAdapterメソッドの引数として渡すと、ArrayAdapterに設定したデータがListViewとして表示されます。
drinkListView.setAdapter(adapter);

次は、リストの項目がクリックされた時にトースト表示と、リストの項目が長押しされた時にトースト表示の処理です


public class MainActivity extends Activity implements OnItemClickListener,OnItemLongClickListener{				
				
	ListView drinkListView = null;			
				
	@Override			
	protected void onCreate(Bundle savedInstanceState) {			
		super.onCreate(savedInstanceState);		
		setContentView(R.layout.main);		
		//アイテムクリックイベント実装		
		drinkListView.setOnItemClickListener(this);		
		//アイテム長押しクリックイベント実装		
		drinkListView.setOnItemLongClickListener(this);

	}			
				
	@Override			
	public boolean onCreateOptionsMenu(Menu menu) {			
		// Inflate the menu; this adds items to the action bar if it is present.		
		getMenuInflater().inflate(R.menu.main, menu);		
		return true;		
	}			
				
	@Override			
	public void onItemClick(AdapterView<?> arg0, View view, int arg2, long arg3) {			
		// TODO 自動生成されたメソッド・スタブ		
				
				
		switch(arg0.getId()) {		
	    	case R.id.drinkListView:		
	    		ListView listView = (ListView) arg0;	
	    		String item = (String) listView.getItemAtPosition(arg2);	
	    		Toast.makeText(getApplicationContext(), item + " clicked",Toast.LENGTH_LONG).show();	
	    		break;	
	        default:   			
	            // 通常のonItemClick()の時の処理   			
	            break;   			
		}		
	}			
				
	@Override			
	public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {			
		// TODO 自動生成されたメソッド・スタブ		
		switch(arg0.getId()) {		
		    case R.id.drinkListView:		
		        ListView listView = (ListView) arg0;		
		        String item = (String) listView.getItemAtPosition(arg2);		
		        Toast.makeText(getApplicationContext(), item + "long clicked",Toast.LENGTH_LONG).show();		
		        break;		
	        default:   			
	            // 通常のonItemLongClick()の時の処理   			
	            break;   			
		}		
		return false;		
	}
			
}	

まずリストの項目がクリックされた時の処理実装ですが、OnItemClickListenerインターフェイスを継承します。 次にリストの項目が長押しされた時の処理実装ですが、OnItemLongClickListenerインターフェイスを継承します。

onItemClickメソッドが追加されるのでその中でトースト表示処理を実装します。
onItemLongClickメソッドが追加されるのでその中でトースト表示処理を実装します。

※トースト(Toast)とは、アプリケーションからユーザーに対して動的に情報を表示するための機能です。実行すると画面に指定した文字のポップアップ画面が表示されます。
最後に終了ボタン押下時の処理を実装します。 ボタン処理の詳細については画面遷移を勉強しみる(1)~(3)のボタン操作処理を参考にしてください。


		Button projectEndButton = null;			
@Override				
	protected void onCreate(Bundle savedInstanceState) {			
				
			//終了ボタン	
			projectEndButton = (Button)findViewById(R.id.projectEnd);	
				
			projectEndButton.setOnClickListener(this);	
		}		
	@Override			
	public void onClick(View v) {			
		// TODO 自動生成されたメソッド・スタブ		
		switch(v.getId()) {		
		    case R.id.projectEnd:	    	
		    	this.finish();	
		    	break;	
		    default:   		
	            // 通常のonClick()の時の処理   			
	            break;   			
		}		
	}			

これで、全実装が終了したので、あとは画面で動作確認をおこなっていみてください
もう少しリストビューについては勉強していきたいと思います

カテゴリーへ

ファイル読込、書込み、表示の勉強(1)

今回はAndroidでのファイル操作について勉強します。
データの保存について、シリアライズ、デシリアライズも勉強していきます

大まかな処理内容は下記の通りでソフトを作っていきます

・ファイルを読み込んで名前リストをリストビューに表示
・ビューアイテム長押しで表示順を末尾に移動する
・登録用のテキストで記入された内容を登録ボタンによりビューに追加(追加の際は末尾)
・終了ボタンで現状の順番をファイルに保存
・画面レイアウト


このソフトが、なにに使えるかは謎ですが(笑) 勉強ということで。

プロジェクト作成

では、プロジェクトの作成からしていきます。
プロジェクト名:OrderDisp、アクテビティ名:MainActivity、レイアウト名:mainで作成

Personクラスファイル作成

次に、名前と表示順をプロパティに持つクラスを作成します。
作成場所:src>パッケージ名>Person.java
クラス名:Person
プロパティ:名前(name)
プロパティ:値(order)

このクラスのリストをシリアライズ、デシリアライズしてファイルに保存、読み込みを行います。
よって、Parsonクラスにava.io.Serializableインタフェースを実装してください。

public class Person implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -469800893038565751L;
	private String m_name;
	private int m_order;

	public String GetName(){
		return m_name;
	}	
	public void SetName(String name){
		m_name = name;
	}
	public int GetOrder(){
		return m_order;
	}	
	public void SetOrder(int order){
		m_order = order;
	}
}

(Strings.xml)編集

次にアプリで使用する文字列を定義します。
(定義方法はStrings.xmlについての勉強を参照)
・順番(order)
・追加したい名前を入力(add_name)
・登録(add)
・終了(project_end)

(main.xml)の画面レイアウト編集

次は(main.xml)の画面レイアウトを作成します。

<LinearLayout
    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"
    android:orientation="vertical"
    tools:context=".MainActivity" >        
	<LinearLayout 
	    android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" 
        android:background="#FFAAFF" > 
      	<TextView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" 
        android:text="@string/order"
        android:textSize="30sp"
        android:gravity="center"
        />
	</LinearLayout>	
	<LinearLayout 
	    android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" 
        > 

		lt;!-- フォーカスダミー -->
		<TextView
		    android:layout_height="0dp"
		    android:layout_width="0dp"
		    android:focusable="true"
		    android:focusableInTouchMode="true"
		    android:text="" >
		    <requestFocus />
		</TextView>

	    	<ListView
      	    android:id="@+id/nameList"
      	    android:layout_width="match_parent"
      	    android:layout_height="0dp"
      	    android:layout_weight="1"/>
      	<LinearLayout
	    	android:id="@+id/linearLayout1"
	    	android:layout_width="fill_parent"
        	android:layout_height="wrap_content"
        	android:orientation="horizontal"
        	android:layout_gravity="center"	
        	android:background="#AAFFFF">    
   	    <EditText android:id="@+id/personEditText"
        	android:layout_width="0dp"
        	android:layout_height="fill_parent"
        	android:maxLength="10"
			android:layout_weight="2"
			android:inputType="text"
			android:hint="@string/add_name"/>
        <Button android:id="@+id/personAddButton"
        	android:layout_width="0dp"
        	android:layout_height="fill_parent"
        	android:layout_gravity="bottom"			
        	android:layout_weight="1"
        	android:text="@string/add" />			
		</LinearLayout>
        <LinearLayout
	    	android:id="@+id/linearLayout2"
	    	android:layout_width="fill_parent"
        	android:layout_height="wrap_content"
        	android:orientation="horizontal"
        	android:layout_gravity="center"	>    
   	    <Button android:id="@+id/projectEndButton"
        	android:layout_width="fill_parent"
        	android:layout_height="wrap_content"
        	android:layout_gravity="bottom"			
        	android:text="@string/project_end" />
		</LinearLayout>      		
	</LinearLayout>		    
</LinearLayout>

画面イメージ


レイアウト内にサイズが0のテキストを配置しています。
これは、ソフト起動時に、EditViewにフォーカスが当たってしまい。ソフトキーボードが表示される問題の解決策です。
もっといい方法があるかもしれませんが、とりあえず今回は力技で回避します。

MainActivity編集

続いて、MainActivityの編集です。
まずは各コントロールを操作できるように設定します。

public class MainActivity extends Activity {

	private Button projectEndButton = null;
	private Button addButton = null;
	private ListView orderListView = null;
	private EditText parsonNameText = null;
	private ArrayList<Person> personList = null;
	private ArrayAdapter<Person> adapter = null;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		
		projectEndButton = (Button)findViewById(R.id.projectEndButton);
		addButton = (Button)findViewById(R.id.personAddButton);
		parsonNameText = (EditText)findViewById(R.id.personEditText);
		orderListView = (ListView)findViewById(R.id.nameList);
	}

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

}

この辺の実装は、毎回ほぼ変わらない内容ですね。そろそろ見慣れてきました。
次は、終了ボタン、追加ボタン、リストビュー長押しイベント登録です。

public class MainActivity extends Activity implements OnClickListener,OnItemLongClickListener {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		projectEndButton.setOnClickListener(this);
		addButton.setOnClickListener(this);
		orderListView.setOnItemLongClickListener(this);
	}
	
	@Override
	public void onClick(View v) {
		// TODO 自動生成されたメソッド・スタブ
		switch(v.getId()) {
		case R.id.personAddButton :
			//リスト追加
			break;
		case R.id.projectEndButton :
			//アプリ終了
			break;		
		}		
	}
	
	@Override
	public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
		// TODO 自動生成されたメソッド・スタブ
		switch(arg0.getId()) {
		case R.id.nameList:
			//選択アイテムを最後尾に移動
			break;
		}
		return false;
	}		
}


今回はここまでにしておきます。一度デバッグ実行して画面が動くかを確認しておきましょう。
次回はリストビューの表示から始めます。

カテゴリーへ

ファイル読込、書込み、表示の勉強(2)

前回の続きで、初期表示時にファイルから読込んで、リストビューに表示するところから始めます。
まずは初期表示処理から実装していきます。


@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	
	
	adapter = new ArrayAdapter<erson> (this, simple_expandable_list_item_1);
	orderListView = (ListView)findViewById(R.id.nameList);		
	orderListView.setAdapter(adapter);
	
	//読込
	if(this.readFile()){
		if(personList.size() != 0){
		    for (int i = 0 ; i < personList.size() ; i++){
		    	adapter.add(personList.get(i));
		      }					
		}
	}

{	

//メンバ変数
private ArrayList<Person> personList = null;

/*
 * ファイル読込
 */
private boolean readFile(){
	try {
		
		FileInputStream fis = openFileInput("SaveData.dat");
	    ObjectInputStream ois = new ObjectInputStream(fis);
	    personList = (ArrayList<Person> ) ois.readObject();
	    ois.close();
	    fis.close();
	    
		return true;
	} catch (FileNotFoundException e) {
		// TODO 自動生成された catch ブロック
		e.printStackTrace();
		return false;
	} catch (StreamCorruptedException e) {
		// TODO 自動生成された catch ブロック
		e.printStackTrace();
		return false;
	} catch (IOException e) {
		// TODO 自動生成された catch ブロック
		e.printStackTrace();
		return false;
	} catch (ClassNotFoundException e) {
		// TODO 自動生成された catch ブロック
		e.printStackTrace();
		return false;
	}
}

FileInputStream fis = openFileInput("SaveData.dat");

FileInputStream は指定したファイルをバイナリファイルとして読み込みます。
openFileInputは第1引数にオープンするファイル名を指定します。今回は"SaveData.dat"にしています。

openFileInputの戻り値がjava標準クラスのFileInputStreamになるため、fisで受け取っています。

例外処理としてFileNotFoundExceptionが有ります。
プログラムによって指定されたファイルを見つけることができない時投げられます。

ObjectInputStream ois = new ObjectInputStream(fis);

ObjectInputStreamは、Serializableインターフェイスの実装クラスを取り出す際に使用します。今回でたとえるとPersonクラスです。

つまり、「直列化」されたクラスを取り出す際に使用します。
※クラスの「保存」を行う際に、フィールドそれぞれを保存するのではなく、「まるごと」保存することを「直列化」と表現します。

personList = (ArrayList<Person> ) ois.readObject();

personListはPersonクラス配列のメンバ変数です。
オブジェクトをストリームから読み込むには readObject メソッドを使います。
直列化ブジェクトを読み込んだ場合objectとして扱われるため、希望の型にキャストされている必要があります。

ois.close();fis.close();

最後に closeで終了処理をします。

次は、リストに追加する処理を実装します。
				
@Override
public void onClick(View v) {
	// TODO 自動生成されたメソッド・スタブ
	switch(v.getId()) {
	case R.id.personAddButton :
		//リスト追加
		this.addList();
		break;
		
		
		:
		:
		:
	}		
}


/*							
 * リスト追加						
 */						
private boolean addList(){						
	//入力値取得					
	String str = parsonNameText.getText().toString();					
	if(str.equals("")) {					
		AlertDialog.Builder alertDialog = new AlertDialog.Builder(MainActivity.this);				
		//タイトルを設定する				
		alertDialog.setTitle("入力エラー");				
		//メッセージ内容を設定する				
		alertDialog.setMessage("入力内容が不正です。");				
		break;				
	}					
						
	//リストに追加
	Person p = new Person();        	
	p.SetName(str);
	p.SetOrder(0);
			
	adapter.add(str);					
	parsonNameText.setText("");					
}						

追加処理は、難しい処理はしていません。parsonNameTextに入力された値を取得して、adapterに追加しているだけです。

次に、終了時にファイルに保存をする処理の実装します。

/*
 * ファイル保存
 */
private boolean saveFile(){
	ArrayList<Person> data = new ArrayList<Person>();
    for (int i = 0 ; i < adapter.getCount() ; i++) {	    	
    	String item = ((Person)adapter.getItem(i)).GetName();
    	Person p = new Person();
    	p.SetName(item);
    	p.SetOrder(i+1);
    	
    	data.add(p);
      }		
    
    if(data.size() != 0){
    	try {
    		
		    FileOutputStream fos = openFileOutput("SaveData.dat", MODE_PRIVATE);
		    ObjectOutputStream oos = new ObjectOutputStream(fos);
		    oos.writeObject(data);
		    oos.close();
		    fos.close();
		    
		} catch (Exception e) {
		    Log.d("saveFile", "Error");
		}
    }
    
    return true;
}

FileOutputStream fos = openFileOutput("SaveData.dat", MODE_PRIVATE);

FileOutputStream は指定された名前のファイルに書き込むためのファイル出力ストリームです。。
openFileOutputは第1引数に出力するファイル名を指定します。今回は"SaveData.dat"にしています。

第2引数には、下記の値を渡すことによって、それぞれのモードでファイルがオープンされます。
0、MODE_PRIVATE:アプリケーション専用モード
MODE_APPEND:追記モード
MODE_WORLD_READABLE:他のアプリケーションからも読み込みできるモード
MODE_WORLD_WRITEABLE:他のアプリケーションからも書き込みできるモード

openFileOutputの戻り値がjava標準クラスのFileOutputStreamになるため、fosで受け取っています。

例外処理としてFileNotFoundExceptionが有ります。
ファイルは存在せず作成もできない場合、またはなんらかの理由で開くことができない場合は、FileNotFoundException が投げられます。

ObjectOutputStream oos = new ObjectOutputStream(fos);

ObjectOutputStreamは、Serializableインターフェイスの実装クラスを出力する際に使用します。今回でたとえるとPersonクラスです。

oos.writeObject(data);

writeObjectで、「直列化可能」なクラスをバイトストリームに出力します。

oos.close();fos.close();

最後に closeで終了処理をします。

つぎは、選択アイテム長押しで、順番を最後尾に移動する処理を実装します。

	@Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2,
		long arg3) {
	// TODO 自動生成されたメソッド・スタブ
	switch(arg0.getId()) {
	case R.id.nameList:
		//選択アイテムを最後尾に移動
        ListView listView = (ListView) arg0;
        Person p = (Person)adapter.getItem(arg2);
        adapter.remove(p);
        Person ap = new Person();
        ap.setName(p.getName());
        ap.setOrder(p.getOrder());
        adapter.add(p.GetName());			
		break;
	}
	return false;
}			

ここでも大した処理はしていません、adapterに登録されている対象のデータをまずけして、
新しく追加しているだけです。
以上で完成です。

ファイルの操作は思ったよりも簡単にできました。
ただ、ファイルがどこに保存されて、アクセス権限がどうなっているのかを、もっと理解しないといけないかなぁ~
ちなみに今回のソフトにリスト削除機能がないので、どっかのタイミングで削除機能をつけます。

カテゴリーへ

選択色設定(標準)

リストビューで項目をクリックした際に、
わかりやすくするために現在選択している項目の行の背景色を変更してみようと思います。

カスタマイズしない標準のリストビューを使用する場合はそれほど難しくは有りません。
まずは標準のリストビューを使用するパターンです。

画面上にリストビューだけ配置します。


//main.xml
	<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical";>    
	<!-- リストビュー --;>
	<!-- divider 区切り線の色 --;>
	<!-- dividerHeight 区切り線の幅 --;>
	<ListView
	    android:id="@+id/main_list_listview"
	    android:layout_width="fill_parent"
		android:layout_height="wrap_content" 
		android:listSelector = "@color/red"
		android:choiceMode="singleChoice"
		android:divider="@color/black" 
		android:dividerHeight="1sp"		
		/;>
</LinearLayout;>

//MainActivity.java	
	ListView mainList = null;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
				
		String[] members = { "データ1", "データ2", "データ3", "データ4","データ5" };		
		//ArrayAdapterクラス作成		
		ArrayAdapter<String;> adapter = new ArrayAdapter<String;> 
		(this,android.R.layout.simple_expandable_list_item_1, members);		
		mainList = (ListView) findViewById(R.id.main_list_listview);		
		mainList.setAdapter(adapter);	
	}
}

android:listSelector = "@color/red"
上の属性を追加するだけでタッチしたときに色が変わるようになります。

ただこのままだと画面から指を離すと色が元に戻ってしまいます。

選択アイテムの背景色を変えるにはカスタムビューを使用しないといけません。

次はカスタムビューのパターンを見ていきたいともいます。

"@color/red"についてはこっちの記事を参照ください。


カテゴリーへ

選択色設定(カスタム)

リストビューで項目をクリックした際に、
わかりやすくするために現在選択している項目の行の背景色を変更してみようと思います。

まずはListViewを使用する際に使うクラスArrayAdapterをカスタマイズします。

ArrayAdapterは渡されたデータをTextにセットしてViewを返す処理を行っています。
Viewを返す処理をしているのがgetViewメソッドです。

よってArrayAdapterクラスを継承した新たなクラスを作成してgetViewメソッド
をオーバライドして、自分の好きなビューを返してやるようにします。

/*
 * ArrayAdapterカスタムクラス
 */
public class CustomArrayAdapter extends ArrayAdapter<String>{

	private Context myContext = null;
	
	/*
	 * コンストラクタ		
	 */
	public CustomArrayAdapter(Context context, int resource,
			int textViewResourceId, List<String> objects) {		
		super(context, resource, textViewResourceId, objects);		
		myContext = context;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		// TODO 自動生成されたメソッド・スタブ

	    View customItemView = null; 
	    if (convertView == null) {
	         LayoutInflater inflater = (LayoutInflater)myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
	         customItemView = inflater.inflate(R.layout.list_row, parent, false);
	    } else {
	         customItemView = convertView;
	    }

	    ListView listView = (ListView)parent;	    
	    if (listView.getCheckedItemPosition() == position) {
	    	customItemView.setBackgroundColor(Color.GREEN);
	    } else {
	    	customItemView.setBackgroundColor(Color.WHITE);
	    }
	    
	    return customItemView;
	}
}

コンストラクタとgetViewしかオーバーライドしてません。

コンストラクタではCustomArrayAdapterを生成した親(Context)を保持します。
次にgetViewですが初期表示ではconvertViewがNullのため下記のようにViewを作成します。
	
if (convertView == null) {
     LayoutInflater inflater = (LayoutInflater)myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
     customItemView = inflater.inflate(R.layout.list_row, parent, false);
} else {
     customItemView = convertView;
}
	
getViewメソッドの第2引数は、前回使用したViewオブジェクトが渡されるため
convertViewがNullじゃない場合は使い回しできます。

次はparentをListviewにキャストしてやります。
listView.getCheckedItemPosition()で現在選択中のItemが取得できます。

getViewメソッドの第1引数のpositionで現在のポジションが渡ってくるので、比較します。
同じなら選択色、違う場合は非選択色にしています。

これであとはレイアウトと紐つけるだけで選択色が反映されるリストを作成できるはずです。

/*
 * MainActivityクラス抜粋
 */
	@Override
	protected void onCreate(Bundle savedInstanceState) {
	    super.onCreate(savedInstanceState);
	    setContentView(R.layout.main);
	    ListView listView = (ListView)findViewById(R.id.main_list_listview);

	    items.add("Item 1");
	    items.add("Item 2");
	    items.add("Item 3");
	    items.add("Item 4");
	    items.add("Item 5");
	    items.add("Item 6");
	    items.add("Item 7");
	    items.add("Item 8");
	    
	    // アダプタの作成
	    adapter = new CustomArrayAdapter(this,
	        R.layout.list_row,
	        R.id.symbol_text,
	        items);
	      
	    listView.setAdapter(adapter);
	  
	}

出来上がってみれば、単純だったんですが、かなりはまりました...(;´∀`)
初めはselector.xmlを使ってゴニョゴニョしてたんですが、全く背景色が変わらず
次はListviewのsetOnItemClickListenerをつかってisSelectをゴニョゴニョしたり。。。
ほかにもっと簡単な方法はないんでしょうかねぇ…


カテゴリーへ

inserted by FC2 system