选择对话框:自定义组合控件+自定义对话框 实现
2014-11-12 23:57
363 查看
转:http://blog.csdn.net/billpig/article/details/6664053
由于项目的需要,需要用到选择对话框,虽然可以使用系统自带到控件就可以实现,但是从长远的角度上去看,还是不利于本项目的发展,于是自己做了一个自定义的控件,使用到了组合控件,顺便也学习了下组合控件的创建。
自定义控件有多种方式,具体就不提及了,本次俺只使用组合控件,先上个图,让大家对本次所实现的效果有个直观的认识:
如上图所示,我希望能在点击“浏览模式”的时候弹出选择对话框(注意:这个按钮有标题和当前选择项,右边还有一个图标以提示用户),而且这个对话框是可以使用自定义的对话框。针对这种实现,我想到的可能的几种方法:
使用ListPreference
难点1:使用PreferenceActivity的背景颜色不知道可以选择不? 个人觉得应该可以更改掉
难点2:Preference不是要保存数据么?如果不保存数据要如何去做? 经过查证,可以设置它的persistence属性,使其不保存数据
难点3:能够更改对话框的布局?应该可以,俺不确定,有待求证
使用Spinner
难点1:主页面(标题、当前选项、右边加一个图标)显示使用组合对话框应该可以解决,不过好像也蛮麻烦的
难点2:能够更改对话框的布局?应该可以,俺不确定,有待求证
完全自定义
难点1:控件的美观程度?应该可以用图片解决
难点2:弹出对话框后选择选项后改变相应的内容
难点3:自定义对话框布局
起初做的时候,可能查证的信息不够多,因此,头两种方式没有求尝试实现,当时就选择了最后的一种方式。
我们选择了自定义控件的方式,于是定义了一个类ListSelectView extends LinearLayout,有如下变量
[java] view
plaincopy
private TextView tvHeader; //Item 的标题
private TextView tvContent; //Item的选项
private CharSequence[] mEntries; //对话框的选项
private CharSequence[] mEntryValues; //选择对话框后的值
private int mClickedDialogEntryIndex; //对话框选项的index
定义了如下布局:
[html] view
plaincopy
<?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" android:paddingLeft="10dp" android:paddingRight="10dp" android:paddingTop="10dp" android:paddingBottom="4dp">
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:layout_weight="1">
<TextView android:id="@+id/tvListSelectLayoutTitle" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingBottom="0dp" />
<TextView android:id="@+id/tvListSelectLayoutContent" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="10dp" android:paddingTop="0dp" />
</LinearLayout>
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:scaleType="fitCenter" android:background="@drawable/ic_btn_round_more_normal"/>
</LinearLayout>
就大致了实现了这样的布局,然后在attrs.xml中定义了两个属性(可根据情况添加)
[html] view
plaincopy
<declare-styleable name="ListSelectView">
<attr name="entries" format="reference"/>
<attr name="entryValues" format="reference" />
</declare-styleable>
之后在在ListSelectView构造函数中初始化控件及状态
[java] view
plaincopy
public ListSelectView(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.list_select_layout, this, true);
TypedArray a = context.obtainStyledAttributes(attrs, org.lansir.R.styleable.ListSelectView, 0, 0);
mEntries = a.getTextArray(org.lansir.R.styleable.ListSelectView_entries); //从属性处初始化值
mEntryValues = a.getTextArray(org.lansir.R.styleable.ListSelectView_entryValues);
a.recycle();
tvHeader = (TextView) findViewById(R.id.tvListSelectLayoutTitle); //初始化控件
tvContent = (TextView) findViewById(R.id.tvListSelectLayoutContent);
tvHeader.setTextColor(Color.BLACK); //设置标题颜色
tvContent.setGravity(Gravity.TOP);
this.setOnClickListener(this); //设置点击事件
}
得到的效果如上,具体的美工在后期可通过贴图实现
这样,Item项就初始化完毕了
上节中,我们设置了点击事件,事件的内容如下:
[java] view
plaincopy
@Override
public final void onClick(View v) {
SingleSelectionDialog dialog = new SingleSelectionDialog.Builder(this.getContext()).setTitle(tvHeader.getText()).setSingleChoiceItems(mEntries,
mClickedDialogEntryIndex, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mClickedDialogEntryIndex = which;
tvContent.setText(mEntryValues[mClickedDialogEntryIndex]);
dialog.dismiss();
}
}).create();
dialog.show();
}
在这里自定义了一个对话框,SingleSelectionDialog是一个继承自Dialog的一个类,之所以不继承自AlertDialog,是因为AlertDialog要去自定义内容及Style比Dialog类还麻烦,要通过比较复杂的方式去实现。同时,这里setSingleChoiceItems是SingleSelectionDialog类自定义的一个封装方法,这里设置了对话框List选项的值及事件,在这个事件里,设置选项的Index,以便下次再次点击对话框时设置成已设置的值,同时,这里改变主页Item选项值t的内容及关闭对话框。
SingleSelectionDialog的代码实现如下:
[java] view
plaincopy
public class SingleSelectionDialog extends Dialog {
public SingleSelectionDialog(Context context, boolean cancelable,
OnCancelListener cancelListener) {
super(context, cancelable, cancelListener);
}
public SingleSelectionDialog(Context context, int theme) {
super(context, theme);
}
public SingleSelectionDialog(Context context) {
super(context);
}
public static class Builder {
private Context context;
private CharSequence title; //对话框标题
private CharSequence[] mListItem; //对话框选项值
private int mClickedDialogEntryIndex; //对话框选项Index
private DialogInterface.OnClickListener mOnClickListener; //对话框点击事件
public Builder(Context context) {
this.context = context;
}
public Builder setTitle(int title) {
this.title = (String) context.getText(title);
return this;
}
public Builder setTitle(CharSequence title) {
this.title = title;
return this;
}
public CharSequence[] getItems() {
return mListItem;
}
public Builder setItems(CharSequence[] mListItem) {
this.mListItem = mListItem;
return this;
}
//设置单选List选项及事件,这些属性在之后的create中用到,这里使用Android系统创建dialog的风格
public Builder setSingleChoiceItems(CharSequence[] items, int checkedItem, final OnClickListener listener) {
this.mListItem = items;
this.mOnClickListener = listener;
this.mClickedDialogEntryIndex = checkedItem;
return this;
}
public SingleSelectionDialog create() {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final SingleSelectionDialog dialog = new SingleSelectionDialog(
context, R.style.Theme_Dialog_ListSelect);
View layout = inflater.inflate(R.layout.single_selection_dialog,
null);
dialog.addContentView(layout, new LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
if(mListItem == null){
throw new RuntimeException("Entries should not be empty");
}
ListView lvListItem = (ListView) layout.findViewById(R.id.lvListItem);
// android.R.layout.simple_list_item_single_choice
//lvListItem.setAdapter(new ArrayAdapter(context, android.R.layout.simple_list_item_single_choice, android.R.id.text1, mListItem));
// SingleSelectionAdapter mSingleSelectionAdapter = new SingleSelectionAdapter(context, R.layout.single_list_item, R.id.ctvListItem, mListItem);
// lvListItem.setAdapter(mSingleSelectionAdapter);
lvListItem.setAdapter(new ArrayAdapter(context, R.layout.single_selection_list_item, R.id.ctvListItem, mListItem));
lvListItem.setOnItemClickListener(new OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
mOnClickListener.onClick(dialog, position);
}
});
lvListItem.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
lvListItem.setItemChecked(mClickedDialogEntryIndex, true);
lvListItem.setSelection(mClickedDialogEntryIndex);
TextView tvHeader = (TextView)layout.findViewById(R.id.title);
tvHeader.setText(title);
return dialog;
}
}
}
setSingleSelectItems设置了单选列表的Item以及事件,这些属性在create中用到。
最关键的就是create()方法,在这里初始化dialog的主题:
取消标题
取消边框
使用透明
style样式如下:
[java] view
plaincopy
<style name="Theme.Dialog.ListSelect" parent="android:style/Theme.Dialog">
<item name="android:windowIsFloating">true</item>
<item name="android:windowIsTranslucent">false</item><!--半透明-->
<item name="android:backgroundDimEnabled">false</item><!--模糊-->
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFrame">@null</item><!--边框-->
</style>
之后是使用setContent初始化内容,这里,使用自定义布局的方式去创建,xml布局文件如下:
[java] view
plaincopy
<?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:minWidth="280dip" android:layout_height="wrap_content">
//标题
<LinearLayout android:orientation="vertical"
android:background="@drawable/header" android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView style="@style/DialogText.Title" android:id="@+id/title"
android:paddingRight="8dip" android:paddingLeft="8dip"
android:background="@drawable/title" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:textColor="@color/black" />
</LinearLayout>
//内容
<LinearLayout android:id="@+id/content"
android:orientation="vertical" android:background="@drawable/center"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<ListView android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_marginTop="5px"
android:cacheColorHint="@null" android:divider="@android:drawable/divider_horizontal_bright"
android:scrollbars="vertical" android:id="@+id/lvListItem" />
</LinearLayout>//底部
<LinearLayout android:orientation="horizontal"
android:background="@drawable/footer" android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
整个布局分为:头部、内容、底部。头部用于显示标题, 内容用于显示单选List, 底部用于美化对话框用。
然后设置Adapter,使得adapter的layout使用我们自定义的layout,这个layout设置list选项的样式:
[java] view
plaincopy
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ctvListItem"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:textAppearance="?android:attr/textAppearanceLarge"
android:gravity="center_vertical"
android:checkMark="@drawable/radio_button_selector"
android:paddingLeft="6dip"
android:paddingRight="6dip"
android:textColor="@color/black"
/>
在做这个layout的时候,当初确实不知道如何去做,自己本想定义一个TextView 以及一个RadioButton解决,后来发现这种解决方式一直不理想,主要问题在如何设置单选按钮,实现它的单选功能?用我们自定义的Adapter必须检测是哪个item被选中,但由于ListView的缓存机制增加了这种做法的复杂程度,我们还得为之做个缓冲,保存单选的状态才能实现。而且查看了系统Dialog的源码,发现其本就使用了缓存选项状态的方式去实现,那我们干嘛要自己定义,自己实现,还那么复杂,为何不去使用它呢?于是便查看参考了android.R.layout.simple_list_item_single_choice布局文件的内容,发现它用到了CheckedTextView的控件,但是我们并不想要系统默认的单选样式。于是,自己自定义了一个CheckedTextView,改掉它的单选样式(即android:checkMark)。
于是创建布局完毕,开始最后一步整合,即设置单选列表,容易出问题的地方来了:
[java] view
plaincopy
ListView lvListItem = (ListView) layout.findViewById(R.id.lvListItem);
lvListItem.setAdapter(new ArrayAdapter(context, R.layout.single_selection_list_item, R.id.ctvListItem, mListItem));
lvListItem.setOnItemClickListener(new OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
mOnClickListener.onClick(dialog, position);
}
});
lvListItem.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
lvListItem.setItemChecked(mClickedDialogEntryIndex, true);
lvListItem.setSelection(mClickedDialogEntryIndex);
我们使用系统自定义的Adapter,发现它能为我们解决很多问题,如上述的缓存选项状态的问题。这里表明看起来没什么讲究,其实大有讲究:setChoiceMode必须在setItemChecked前调用,否则setChoiceMode会失效,这个也是我查看了Android的ListView的源码实现后才发现的。
这样,选择对话框:自定义组合控件+自定义对话框 完成,使用起来超级简单,完全不需要自己去做很多的设置,我的整个Activity如:
[java] view
plaincopy
public class SharePrefersActivity extends Activity {
private ListSelectView mListSelectView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mListSelectView = (ListSelectView)findViewById(R.id.lsvTest);
mListSelectView.setHeader("Hello");
mListSelectView.setContent("world");
}
便能实现如下的效果,来个截图纪念下:
这样,就大功告成了。
源代码下载
版权所有,转载请出明出处!
由于项目的需要,需要用到选择对话框,虽然可以使用系统自带到控件就可以实现,但是从长远的角度上去看,还是不利于本项目的发展,于是自己做了一个自定义的控件,使用到了组合控件,顺便也学习了下组合控件的创建。
自定义控件有多种方式,具体就不提及了,本次俺只使用组合控件,先上个图,让大家对本次所实现的效果有个直观的认识:
如上图所示,我希望能在点击“浏览模式”的时候弹出选择对话框(注意:这个按钮有标题和当前选择项,右边还有一个图标以提示用户),而且这个对话框是可以使用自定义的对话框。针对这种实现,我想到的可能的几种方法:
使用ListPreference
难点1:使用PreferenceActivity的背景颜色不知道可以选择不? 个人觉得应该可以更改掉
难点2:Preference不是要保存数据么?如果不保存数据要如何去做? 经过查证,可以设置它的persistence属性,使其不保存数据
难点3:能够更改对话框的布局?应该可以,俺不确定,有待求证
使用Spinner
难点1:主页面(标题、当前选项、右边加一个图标)显示使用组合对话框应该可以解决,不过好像也蛮麻烦的
难点2:能够更改对话框的布局?应该可以,俺不确定,有待求证
完全自定义
难点1:控件的美观程度?应该可以用图片解决
难点2:弹出对话框后选择选项后改变相应的内容
难点3:自定义对话框布局
起初做的时候,可能查证的信息不够多,因此,头两种方式没有求尝试实现,当时就选择了最后的一种方式。
我们选择了自定义控件的方式,于是定义了一个类ListSelectView extends LinearLayout,有如下变量
[java] view
plaincopy
private TextView tvHeader; //Item 的标题
private TextView tvContent; //Item的选项
private CharSequence[] mEntries; //对话框的选项
private CharSequence[] mEntryValues; //选择对话框后的值
private int mClickedDialogEntryIndex; //对话框选项的index
1、item项目实现
首先是主页的item项:定义了如下布局:
[html] view
plaincopy
<?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" android:paddingLeft="10dp" android:paddingRight="10dp" android:paddingTop="10dp" android:paddingBottom="4dp">
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:layout_weight="1">
<TextView android:id="@+id/tvListSelectLayoutTitle" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingBottom="0dp" />
<TextView android:id="@+id/tvListSelectLayoutContent" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="10dp" android:paddingTop="0dp" />
</LinearLayout>
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:scaleType="fitCenter" android:background="@drawable/ic_btn_round_more_normal"/>
</LinearLayout>
就大致了实现了这样的布局,然后在attrs.xml中定义了两个属性(可根据情况添加)
[html] view
plaincopy
<declare-styleable name="ListSelectView">
<attr name="entries" format="reference"/>
<attr name="entryValues" format="reference" />
</declare-styleable>
之后在在ListSelectView构造函数中初始化控件及状态
[java] view
plaincopy
public ListSelectView(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.list_select_layout, this, true);
TypedArray a = context.obtainStyledAttributes(attrs, org.lansir.R.styleable.ListSelectView, 0, 0);
mEntries = a.getTextArray(org.lansir.R.styleable.ListSelectView_entries); //从属性处初始化值
mEntryValues = a.getTextArray(org.lansir.R.styleable.ListSelectView_entryValues);
a.recycle();
tvHeader = (TextView) findViewById(R.id.tvListSelectLayoutTitle); //初始化控件
tvContent = (TextView) findViewById(R.id.tvListSelectLayoutContent);
tvHeader.setTextColor(Color.BLACK); //设置标题颜色
tvContent.setGravity(Gravity.TOP);
this.setOnClickListener(this); //设置点击事件
}
得到的效果如上,具体的美工在后期可通过贴图实现
这样,Item项就初始化完毕了
2、对话框实现
接下来是对话框的视图:上节中,我们设置了点击事件,事件的内容如下:
[java] view
plaincopy
@Override
public final void onClick(View v) {
SingleSelectionDialog dialog = new SingleSelectionDialog.Builder(this.getContext()).setTitle(tvHeader.getText()).setSingleChoiceItems(mEntries,
mClickedDialogEntryIndex, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mClickedDialogEntryIndex = which;
tvContent.setText(mEntryValues[mClickedDialogEntryIndex]);
dialog.dismiss();
}
}).create();
dialog.show();
}
在这里自定义了一个对话框,SingleSelectionDialog是一个继承自Dialog的一个类,之所以不继承自AlertDialog,是因为AlertDialog要去自定义内容及Style比Dialog类还麻烦,要通过比较复杂的方式去实现。同时,这里setSingleChoiceItems是SingleSelectionDialog类自定义的一个封装方法,这里设置了对话框List选项的值及事件,在这个事件里,设置选项的Index,以便下次再次点击对话框时设置成已设置的值,同时,这里改变主页Item选项值t的内容及关闭对话框。
SingleSelectionDialog的代码实现如下:
[java] view
plaincopy
public class SingleSelectionDialog extends Dialog {
public SingleSelectionDialog(Context context, boolean cancelable,
OnCancelListener cancelListener) {
super(context, cancelable, cancelListener);
}
public SingleSelectionDialog(Context context, int theme) {
super(context, theme);
}
public SingleSelectionDialog(Context context) {
super(context);
}
public static class Builder {
private Context context;
private CharSequence title; //对话框标题
private CharSequence[] mListItem; //对话框选项值
private int mClickedDialogEntryIndex; //对话框选项Index
private DialogInterface.OnClickListener mOnClickListener; //对话框点击事件
public Builder(Context context) {
this.context = context;
}
public Builder setTitle(int title) {
this.title = (String) context.getText(title);
return this;
}
public Builder setTitle(CharSequence title) {
this.title = title;
return this;
}
public CharSequence[] getItems() {
return mListItem;
}
public Builder setItems(CharSequence[] mListItem) {
this.mListItem = mListItem;
return this;
}
//设置单选List选项及事件,这些属性在之后的create中用到,这里使用Android系统创建dialog的风格
public Builder setSingleChoiceItems(CharSequence[] items, int checkedItem, final OnClickListener listener) {
this.mListItem = items;
this.mOnClickListener = listener;
this.mClickedDialogEntryIndex = checkedItem;
return this;
}
public SingleSelectionDialog create() {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final SingleSelectionDialog dialog = new SingleSelectionDialog(
context, R.style.Theme_Dialog_ListSelect);
View layout = inflater.inflate(R.layout.single_selection_dialog,
null);
dialog.addContentView(layout, new LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
if(mListItem == null){
throw new RuntimeException("Entries should not be empty");
}
ListView lvListItem = (ListView) layout.findViewById(R.id.lvListItem);
// android.R.layout.simple_list_item_single_choice
//lvListItem.setAdapter(new ArrayAdapter(context, android.R.layout.simple_list_item_single_choice, android.R.id.text1, mListItem));
// SingleSelectionAdapter mSingleSelectionAdapter = new SingleSelectionAdapter(context, R.layout.single_list_item, R.id.ctvListItem, mListItem);
// lvListItem.setAdapter(mSingleSelectionAdapter);
lvListItem.setAdapter(new ArrayAdapter(context, R.layout.single_selection_list_item, R.id.ctvListItem, mListItem));
lvListItem.setOnItemClickListener(new OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
mOnClickListener.onClick(dialog, position);
}
});
lvListItem.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
lvListItem.setItemChecked(mClickedDialogEntryIndex, true);
lvListItem.setSelection(mClickedDialogEntryIndex);
TextView tvHeader = (TextView)layout.findViewById(R.id.title);
tvHeader.setText(title);
return dialog;
}
}
}
setSingleSelectItems设置了单选列表的Item以及事件,这些属性在create中用到。
最关键的就是create()方法,在这里初始化dialog的主题:
取消标题
取消边框
使用透明
style样式如下:
[java] view
plaincopy
<style name="Theme.Dialog.ListSelect" parent="android:style/Theme.Dialog">
<item name="android:windowIsFloating">true</item>
<item name="android:windowIsTranslucent">false</item><!--半透明-->
<item name="android:backgroundDimEnabled">false</item><!--模糊-->
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFrame">@null</item><!--边框-->
</style>
之后是使用setContent初始化内容,这里,使用自定义布局的方式去创建,xml布局文件如下:
[java] view
plaincopy
<?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:minWidth="280dip" android:layout_height="wrap_content">
//标题
<LinearLayout android:orientation="vertical"
android:background="@drawable/header" android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView style="@style/DialogText.Title" android:id="@+id/title"
android:paddingRight="8dip" android:paddingLeft="8dip"
android:background="@drawable/title" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:textColor="@color/black" />
</LinearLayout>
//内容
<LinearLayout android:id="@+id/content"
android:orientation="vertical" android:background="@drawable/center"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<ListView android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_marginTop="5px"
android:cacheColorHint="@null" android:divider="@android:drawable/divider_horizontal_bright"
android:scrollbars="vertical" android:id="@+id/lvListItem" />
</LinearLayout>//底部
<LinearLayout android:orientation="horizontal"
android:background="@drawable/footer" android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
整个布局分为:头部、内容、底部。头部用于显示标题, 内容用于显示单选List, 底部用于美化对话框用。
然后设置Adapter,使得adapter的layout使用我们自定义的layout,这个layout设置list选项的样式:
[java] view
plaincopy
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ctvListItem"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:textAppearance="?android:attr/textAppearanceLarge"
android:gravity="center_vertical"
android:checkMark="@drawable/radio_button_selector"
android:paddingLeft="6dip"
android:paddingRight="6dip"
android:textColor="@color/black"
/>
在做这个layout的时候,当初确实不知道如何去做,自己本想定义一个TextView 以及一个RadioButton解决,后来发现这种解决方式一直不理想,主要问题在如何设置单选按钮,实现它的单选功能?用我们自定义的Adapter必须检测是哪个item被选中,但由于ListView的缓存机制增加了这种做法的复杂程度,我们还得为之做个缓冲,保存单选的状态才能实现。而且查看了系统Dialog的源码,发现其本就使用了缓存选项状态的方式去实现,那我们干嘛要自己定义,自己实现,还那么复杂,为何不去使用它呢?于是便查看参考了android.R.layout.simple_list_item_single_choice布局文件的内容,发现它用到了CheckedTextView的控件,但是我们并不想要系统默认的单选样式。于是,自己自定义了一个CheckedTextView,改掉它的单选样式(即android:checkMark)。
于是创建布局完毕,开始最后一步整合,即设置单选列表,容易出问题的地方来了:
[java] view
plaincopy
ListView lvListItem = (ListView) layout.findViewById(R.id.lvListItem);
lvListItem.setAdapter(new ArrayAdapter(context, R.layout.single_selection_list_item, R.id.ctvListItem, mListItem));
lvListItem.setOnItemClickListener(new OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
mOnClickListener.onClick(dialog, position);
}
});
lvListItem.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
lvListItem.setItemChecked(mClickedDialogEntryIndex, true);
lvListItem.setSelection(mClickedDialogEntryIndex);
我们使用系统自定义的Adapter,发现它能为我们解决很多问题,如上述的缓存选项状态的问题。这里表明看起来没什么讲究,其实大有讲究:setChoiceMode必须在setItemChecked前调用,否则setChoiceMode会失效,这个也是我查看了Android的ListView的源码实现后才发现的。
这样,选择对话框:自定义组合控件+自定义对话框 完成,使用起来超级简单,完全不需要自己去做很多的设置,我的整个Activity如:
[java] view
plaincopy
public class SharePrefersActivity extends Activity {
private ListSelectView mListSelectView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mListSelectView = (ListSelectView)findViewById(R.id.lsvTest);
mListSelectView.setHeader("Hello");
mListSelectView.setContent("world");
}
便能实现如下的效果,来个截图纪念下:
这样,就大功告成了。
3、注意选项
在做这个DEMO的时候,我想设置主页Item的select,于是便在构造函数里使用this.setBackground()去设置,发现这样设置后,在xml里对ListSelectView设置paddingLeft, layout_margin等属性时都会便无效,这里记住这个错误的方式,以提醒后来人!源代码下载
版权所有,转载请出明出处!
相关文章推荐
- 选择对话框:自定义组合控件+自定义对话框 实现
- 安卓_手机卫士_第二天(GridView,自定义组合控件实现设置页项,自定义对话框)
- maximo 自定义高级数据选择对话框(非表域实现)
- 创建一个如下的窗体,并在窗体上放置colorDialog控件。实现功能:1)程序运行时,单击打开颜色对话框按钮,可选择颜色,并以所选颜色作为窗体背景色
- Android自定义View 简单实现多图片选择控件
- Android进阶——自定义View之组合系统控件实现水珠形状的ItemView
- Android自定义组合控件实现动态轮播图
- DatePicker(日期选择自定义服务器控件)的实现
- (转)ASP.NET弹出式日历选择控件的实现-可用于模块对话框
- 自定义组合控件之省市区三级联动选择
- Android自定义View之组合控件实现类似电商app顶部栏
- 自定义组合控件:下拉选择框
- 实现自定义消息对话框控件MsgBox简介
- android自定义日期和时间选择对话框得实现
- 自定义组合控件属性,自定义对话框,md5加密,自定义按钮背景,
- Android自定义View 简单实现多图片选择控件
- 在窗体上放置一个标签、一个按钮、一个fontDialog控件。标签内容改为“烟台大学”。实现功能:1)程序运行时,单击打开字体对话框按钮,可选择字体,并以所选字体作为标签字体。
- 安卓自定义组合控件实现标题栏
- 套用DatePickerDialog源码实现自定义样式的日期选择对话框
- Android进阶——自定义View之重写ViewGroup组合系统控件实现自定义ToolBar模板