最近在用原生的控件和布局绘制一些界面并使用,虽然这些都是Android基本知识,但是有的时候真的感觉力不从心,感觉有必要对Android常用的控件和布局做一个系统的了解。后续一个月甚至更多的时间都会围绕这个主题展开,毕竟这里面还是有不少高级控件的,我也会尽量结合应用深入的进行了解。
上一篇:RadioButton 下一篇:Spinner
今天,我们的主题是CheckedTextView,它是一种对TextView进行了扩展的控件,下面看一下官方文档的介绍:
* An extension to {@link TextView} that supports the {@link Checkable} * interface and displays. * <p> * This is useful when used in a {@link android.widget.ListView ListView} where * the {@link android.widget.ListView#setChoiceMode(int) setChoiceMode} has * been set to something other than * {@link android.widget.ListView#CHOICE_MODE_NONE CHOICE_MODE_NONE}.
可见,其通常配合ListView实现单选或者多选的操作,后面我们会结合ListView进行简单的演示。上面说到,这是一个继承至TextView且实现了Checkable接口的控件,下面看看其基本的使用和展示:
<CheckedTextView
android:id="@+id/checked_textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CheckedTextView"
android:textSize="25sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
和一个TextView没有任何区别,下面,我们给上面的控件添加一个属性android:checkMark:
<CheckedTextView
android:id="@+id/checked_textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="CheckedTextView"
android:textSize="25sp" />
<CheckedTextView
android:id="@+id/checked_textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checkMark="@drawable/checked_text_view_back"
android:text="CheckedTextView"
android:textSize="25sp"
/>
<CheckedTextView
android:id="@+id/checked_textView3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checkMark="@drawable/checked_text_view_back"
android:checked="true"
android:text="CheckedTextView"
android:textSize="25sp" />
可见,通过这个属性可以为CheckedTextView添加一个图标,至于TextView的设置文本相关的属性这里就不在演示了。此外,我们看到这个控件像是一个TextView与一个ImageView的组合,很像一个简单ListView的Item布局,当然这不是上面文档说其适合配合ListView的原因,之所以说其常常配合ListView使用是因为其实现了Checkable接口且ListView中有setItemCheck()这样的接口。下面是setItemCheck()的描述:
/** * Sets the checked state of the specified position. The is only valid if * the choice mode has been set to {@link #CHOICE_MODE_SINGLE} or * {@link #CHOICE_MODE_MULTIPLE}. * * @param position The item whose checked state is to be checked * @param value The new checked state for the item */
设置ListView对应position上的item的状态为checked,且只有在ListView设置为CHOICE_MODE_SINGLE和CHOICE_MODE_MULTIPLE下有效,这里这两个常参表示单选或者多选的意思。所以这也是常常使用ListView配合CheckedTextView实现单选或者多选的原因,此外,我们也可以通过上文关于RadioButton介绍中说的,使用RadioButtom配合RadioGroup实现,但是,后者只能针对定长的选项可以,对于选项数量可变的不好实现,而前者恰恰弥补了这一点。
下面就来通过ListView配合CheckedTextView实现一下多选的效果(不是通过上述方式),示例的运行结果如下:
主要的逻辑代码有我们的适配器MyAdaptor.java代码:
package aoto.com.commonwidgetandlayout.basic_widget.checkedTextView;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckedTextView;
import java.util.ArrayList;
import java.util.List;
import aoto.com.commonwidgetandlayout.R;
/**
* author:why
* created on: 2019/5/14 10:49
* description:
*/
public class MyAdaptor extends ArrayAdapter<String> {
private static final String TAG = "MyAdaptorWhy";
private int resourceID;
private Context context;
private ArrayList<String> resultList;
public MyAdaptor(@NonNull Context context, int resource, List<String> list) {
super(context, resource,list);
this.context = context;
this.resourceID = resource;
resultList=new ArrayList();
}
@NonNull
@Override
public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View view;
final ViewHolder holder;
if (convertView == null) {
view = LayoutInflater.from(getContext()).inflate(resourceID, parent, false);
holder=new ViewHolder();
holder.checkedTextView=view.findViewById(R.id.checked_textView);
view.setTag(holder);
} else {
//布局缓存处理
view = convertView;
holder = (ViewHolder) view.getTag();
}
String str = getItem(position);
holder.checkedTextView.setText(str);
holder.checkedTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
holder.checkedTextView.toggle();//切换选中与非选中状态
if(holder.checkedTextView.isChecked()){
resultList.add(holder.checkedTextView.getText().toString());
}
else {
if(resultList.contains(holder.checkedTextView.getText().toString())){
resultList.remove(holder.checkedTextView.getText().toString());
}
}
}
});
return view;
}
class ViewHolder {
CheckedTextView checkedTextView;
}
public ArrayList<String> getList(){
return resultList;
}
}
控制层代码CTextViewActivity.java代码:
package aoto.com.commonwidgetandlayout.basic_widget.checkedTextView;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.CheckedTextView;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
import aoto.com.commonwidgetandlayout.R;
/**
* @author why
* @date 2019-5-14 10:07:30
*/
public class CTextViewActivity extends AppCompatActivity {
private static final String TAG = "CTextViewActivityWhy";
CheckedTextView textView;
ListView listView;
TextView chooseResult;
MyAdaptor adaptor;
ArrayList<String> nameList=new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ctext_view);
chooseResult=findViewById(R.id.choose_result);
listView=findViewById(R.id.name_list_view);
nameList.add("苹果");
nameList.add("香蕉");
nameList.add("菠萝");
nameList.add("西瓜");
nameList.add("火龙果");
adaptor=new MyAdaptor(this,R.layout.list_item,nameList);
listView.setAdapter(adaptor);
}
public void confirm(View view){
if(adaptor.getList().size()==0){
chooseResult.setText("");
}
else {
chooseResult.setText(adaptor.getList().toString());
}
}
}
主布局以及ListView子布局很简单,这里就直接给出了
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="aoto.com.commonwidgetandlayout.basic_widget.checkedTextView.CTextViewActivity">
<TextView
android:layout_marginLeft="20dp"
android:layout_marginTop="10dp"
android:textSize="25sp"
android:text="请选择您喜欢的水果:"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:gravity="center_horizontal"
android:orientation="vertical"
android:layout_marginTop="10dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:background="@drawable/rectangle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ListView
android:layout_marginTop="10dp"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:layout_marginBottom="10dp"
android:id="@+id/name_list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
<Button
android:text="Sure"
android:onClick="confirm"
android:textAllCaps="false"
android:layout_marginBottom="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<TextView
android:gravity="center_horizontal"
android:textSize="20sp"
android:id="@+id/choose_result"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<CheckedTextView
android:textSize="25sp"
android:id="@+id/checked_textView"
android:checkMark="@drawable/checked_text_view_back"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="CheckedTextView" />
</LinearLayout>
这里很多都是关于ListView的知识,唯一用到的CheckedTextView的API就是toggle(),难得用到,我们就把它的源码拿出来看一下吧:
public void toggle() {
setChecked(!mChecked);
}
超级简单,就是实现这个控件的状态置反操作。关于这个示例的细节就不解释,毕竟还是很简单的。这里我们ListView的子条目布局是一个LinearLayout中放置了一个CheckedTextView实现的。这个时候我们对ListView设置:
listView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
在实际的操作中,我们是获取不到这个事件的,原因很简单,这个监听针对的是ListView子布局View实现了Checkable接口的。我们在上面实际上做了一个错误的示范,因为布局中就一个View,我们为什么不直接用CheckedTextView做ListView子项了,并且其还实现Chackable接口,配合ListView的API就可以实现单选或者多选的操作了。下面我们就按照这个思路来实现一下:
- 第一步,更换适配器代码
package aoto.com.commonwidgetandlayout.basic_widget.checkedTextView;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckedTextView;
import java.util.ArrayList;
import java.util.List;
import aoto.com.commonwidgetandlayout.R;
/**
* author:why
* created on: 2019/5/14 16:58
* description:
*/
public class MyAdaptorTest extends ArrayAdapter<String> {
private static final String TAG = "MyAdaptorWhy";
private Context context;
private ArrayList<String> resultList;
public MyAdaptorTest(@NonNull Context context, int resource, List<String> list) {
super(context, resource,list);
this.context = context;
resultList=new ArrayList();
}
@NonNull
@Override
public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View view;
final ViewHolder holder;
if (convertView == null) {
view = new CheckedTextView(context);
holder=new ViewHolder();
holder.checkedTextView= (CheckedTextView) view;
view.setTag(holder);
} else {
//布局缓存处理
view = convertView;
holder = (ViewHolder) view.getTag();
}
String str = getItem(position);
holder.checkedTextView.setText(str);
holder.checkedTextView.setCheckMarkDrawable(R.drawable.checked_text_view_back);
holder.checkedTextView.setTextSize(25);
return view;
}
class ViewHolder {
CheckedTextView checkedTextView;
}
public ArrayList<String> getList(){
return resultList;
}
}
- 第二步,更换控制层代码
package aoto.com.commonwidgetandlayout.basic_widget.checkedTextView;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.CheckedTextView;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import aoto.com.commonwidgetandlayout.R;
/**
* @author why
* @date 2019-5-14 15:05:23
*/
public class CTextViewTestActivity extends AppCompatActivity {
private static final String TAG = "CTextViewActivityWhy";
CheckedTextView textView;
ListView listView;
TextView chooseResult;
MyAdaptorTest adaptor;
List<String> record = new ArrayList();
ArrayList<String> nameList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.checked_text_view_test);
chooseResult = findViewById(R.id.choose_result);
listView = findViewById(R.id.name_list_view);
nameList.add("苹果");
nameList.add("香蕉");
nameList.add("菠萝");
nameList.add("西瓜");
nameList.add("火龙果");
adaptor = new MyAdaptorTest(this, 0, nameList);
listView.setAdapter(adaptor);
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
//listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
chooseResult.setText(nameList.get(position));//单选显示
//多选显示
// if (record.contains(nameList.get(position))) {
// record.remove(nameList.get(position));
// } else {
// record.add(nameList.get(position));
// }
//
// if (record.size() == 0) {
// chooseResult.setText("");
// } else {
// chooseResult.setText(record.toString());
// }
}
});
}
}
(1)我们首先在自定义适配器中的getView方法中直接返回一个CheckedTextView实例
(2)然后在调用ListView的setChoiceMode()设置选择模式
/** * Defines the choice behavior for the List. By default, Lists do not have any choice behavior * ({@link #CHOICE_MODE_NONE}). By setting the choiceMode to {@link #CHOICE_MODE_SINGLE}, the * List allows up to one item to be in a chosen state. By setting the choiceMode to * {@link #CHOICE_MODE_MULTIPLE}, the list allows any number of items to be chosen. * * @param choiceMode One of {@link #CHOICE_MODE_NONE}, {@link #CHOICE_MODE_SINGLE}, or * {@link #CHOICE_MODE_MULTIPLE} */
(3)设置AdapterView.OnItemClickListener实现子项选择监听事件获取数据
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
chooseResult.setText(nameList.get(position));//单选显示
}
});
单选和多选的运行结果如下所示:
可见,使用CheckedTextView配合ListView实现单选与多选的功能我们实现了。好了,到这里,关于CheckedTextView我们也就介绍完了。
上一篇:RadioButton 下一篇:Spinner
注:欢迎扫码关注