2011年11月30日水曜日

[Android][TextView]TextViewに取り消し線をいれる

なかなか情報が見つからなかったのでメモ。以下のスレッドを参考にしました。

bitwise operators - Remove a Paint Flag in Android - Stack Overflow
TextViewに取り消し線をいれるには、TextPaintクラスを使用します。TextViewのインスタンスからTextPaintオブジェクトを取得し、TextPaintオブジェクトに対し、Paint#STRIKE_THRU_TEXTのフラグを付けてやります。

[java]
TextPaint paint = textView.getPaint();
paint.setFlags(textView.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
paint.setAntiAlias(true);
[/java]

3行目はアンチエイリアスをオンにしています。オンにしないとテキストがギザギザになって見栄えが悪くなってしまいます。

サンプルコードの全文は続きからどうぞ。


サンプルの説明


サンプルでは、カスタムレイアウトのListViewを定義し、ListViewの中にTextViewを1つ配置しています。ListViewのアイテムをタップする事で取り消し線を付けたり消したりできます。



サンプルコード


まずはレイアウトファイルから



main.xml


[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_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="1"></ListView>

</LinearLayout>
[/xml]

ListViewが置いてあるだけです。



list_row.xml


[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="wrap_content"
android:padding="10dip">
<TextView android:id="@+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textStyle="bold">
</TextView>
</LinearLayout>
[/xml]

ListViewのレイアウト。TextViewが1つ配置してあるだけです。


続いてJavaのコード。



Item.java


[java]
package jp.inara.sample.LineThrough;

public class Item {
private String text;
private boolean lineThroughFlag;

public Item(String text, boolean lineThroughFlag) {
this.text = text;
this.lineThroughFlag = lineThroughFlag;
}

public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public boolean isLineThrough() {
return lineThroughFlag;
}
public void setLineThroughFlag(boolean lineThroughFlag) {
this.lineThroughFlag = lineThroughFlag;
}

}
[/java]

ListViewのアイテムに取り消し線が付いてるかどうかの判定がしたかったので、Itemというクラスを作成して、表示用のテキストと取り消し線が付いてるかのフラグをメンバに持たせました。



MyListAdapter.java


[java]
package jp.inara.sample.LineThrough;

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

import android.content.Context;
import android.graphics.Paint;
import android.text.TextPaint;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class MyListAdapter extends ArrayAdapter<Item> {

private ArrayList<Item> mItems;
private LayoutInflater mInflater;

public MyListAdapter(Context context, int textViewResourceId, List<Item> list) {
super(context, textViewResourceId, list);
this.mItems = (ArrayList<Item>) list;
this.mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if(view == null) {
view = mInflater.inflate(R.layout.list_row, null);
}
Item item = mItems.get(position);
if (item != null) {
TextView textView = (TextView)view.findViewById(R.id.text);
textView.setText(item.getText().toString());

// 取り消し線を引くために TextPaintを取得
TextPaint paint = textView.getPaint();

if (item.isLineThrough()) {
// 取り消し線を引く
paint.setFlags(textView.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
// アンチエイリアスをオンにする
paint.setAntiAlias(true);
} else {
// 取り消し線を消す
paint.setFlags(textView.getPaintFlags() & (~ Paint.STRIKE_THRU_TEXT_FLAG));
}

}
return view;
}

}
[/java]

ListViewのAdapterです。getView()の中で、タップされたitemの取り消し線フラグを確認し、Trueなら取り消し線を付け、Falseなら取り消し線を外しています。取り消し線を外すときはsetFlags()で現在のフラグからPaint#STRIKE_THRU_TEXT_FLAGだけを除外します。



MainActivity.java


[java]
package jp.inara.sample.LineThrough;

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

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;

public class MainActivity extends Activity {
private Context mContext;
private List<Item> mList;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

mContext = this;
mList = new ArrayList<Item>();

final MyListAdapter adapter = new MyListAdapter(mContext, R.layout.list_row, mList);
ListView listView = (ListView) findViewById(R.id.listView1);
listView.setAdapter(adapter);

Item item1 = new Item("AAA", false);
Item item2 = new Item("BBB", false);
Item item3 = new Item("CCC", false);

mList.add(item1);
mList.add(item2);
mList.add(item3);

// リストビュークリック時のコールバックリスナー
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Item item = adapter.getItem(position);
item.setLineThroughFlag(!item.isLineThrough());

// ListViewを更新
adapter.notifyDataSetChanged();

}
});
}
}
[/java]

メインのアクティビティになります。タップしたアイテムの取り消し線フラグを反転させています。


以上になります。

自分は取り消し線を外すやり方がうまくわからず、なぜかどのアイテムを選んでもかならず1番上のアイテムに取り消し線が入るという、謎挙動をするようになったりしてしまいました。たぶん、論理演算の指定がおかしかったからだと思います。

ちなみに実行結果はこんな感じ。
20111130003610

実際かなり取り消し線が見づらいですね・・・。
自分は作成中のアプリに入れたくて実装したのですが、結局取り消し線が入ったことが分かりづらいので文字の色も合わせて変更しています。paint#setStrokeWidth()とか試したんですけどだめだったんですよねー。どうやったらラインを太くできるのやら。

0 件のコメント:

コメントを投稿