目录
- 介绍
- 项目结构
- 前端代码
- activity_main.xml
- item_spin_guns.xml
- 后端代码
- GunBean.java
- GenericAdapter.java
- MainActivity.java
介绍
Spinner是一种点一下后供用户可以上下选择用的组件。
我们直接来看一个例子说明这个组件是做什么用的。
我们放大点看
我们这次的课程目标就是实现这样的一种点一下然后弹出选择框的样式。
项目结构
随着前几章对Adapter知识的牢固掌握,我们可以看到,这个例子依旧使用的是Adapter设计模式。
- 我们在项目里放置5个图片用来显示“枪”;
- 我们做一个ViewBean-GunBean;
- 我们做一个用于被Adapter渲染用的细节布局item_spin_guns.xml,它的使用是点击下部那个选择你的爱枪这个spinner被点击时,弹出的那个可纵向选择用的视图;
来看代码吧。
前端代码
activity_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" | |
android:padding="dp" | |
tools:context=".MainActivity"> | |
<TextView | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:text="选择武器等级" | |
android:textColor="#BDED" | |
android:textSize="sp" /> | |
<Spinner | |
android:id="@+id/spinLevel" | |
android:layout_width="dp" | |
android:layout_height="dp" | |
android:entries="@array/data" | |
android:prompt="@string/title" | |
android:spinnerMode="dialog" /> | |
<TextView | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_marginTop="dp" | |
android:text="选择你的爱枪" | |
android:textColor="#FA" | |
android:textSize="sp" /> | |
<Spinner | |
android:id="@+id/spinGuns" | |
android:layout_width="wrap_content" | |
android:layout_height="dp" /> | |
</LinearLayout> |
item_spin_guns.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:orientation="horizontal" | |
android:padding="dp"> | |
<ImageView | |
android:id="@+id/gunIcon" | |
android:layout_width="dp" | |
android:layout_height="dp" | |
android:src="@drawable/golden_qiang" /> | |
<TextView | |
android:id="@+id/gunName" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_marginLeft="dp" | |
android:layout_marginTop="dp" | |
android:text="机枪-大链锯" | |
android:textSize="sp" /> | |
</LinearLayout> |
后端代码
GunBean.java
package org.mk.android.demospinneradapter; | |
import java.io.Serializable; | |
public class GunBean implements Serializable { | |
private static final long serialVersionUID =L; | |
private int gunIcon; | |
private String gunName=""; | |
public GunBean(){ | |
} | |
public GunBean(String gunName,int gunIcon){ | |
this.gunName=gunName; | |
this.gunIcon=gunIcon; | |
} | |
public int getGunIcon() { | |
return gunIcon; | |
} | |
public void setGunIcon(int gunIcon) { | |
this.gunIcon = gunIcon; | |
} | |
public String getGunName() { | |
return gunName; | |
} | |
public void setGunName(String gunName) { | |
this.gunName = gunName; | |
} | |
} |
GenericAdapter.java
我们依旧延用我们上一篇在自定义Adapter中制作的那个可接受泛型的Adapter。
package org.mk.android.demospinneradapter; | |
import android.content.Context; | |
import android.util.Log; | |
import android.util.SparseArray; | |
import android.view.LayoutInflater; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.widget.BaseAdapter; | |
import android.widget.ImageView; | |
import android.widget.TextView; | |
import java.util.ArrayList; | |
import java.util.List; | |
public abstract class GenericAdapter<T> extends BaseAdapter { | |
private List<T> data; | |
private int layoutRes; | |
public GenericAdapter() { | |
} | |
public GenericAdapter(List<T> data, int layoutRes) { | |
this.data = data; | |
this.layoutRes = layoutRes; | |
} | |
public int getCount() { | |
Log.i("app",">>>>>>data.size: "+data.size()); | |
if(data!=null) { | |
return data.size(); | |
} | |
return; | |
} | |
public T getItem(int position) { | |
return data.get(position); | |
} | |
public long getItemId(int position) { | |
return position; | |
} | |
public View getView(int position, View convertView, ViewGroup parent) { | |
Log.i("app",">>>>>>into getView"); | |
ViewHolder holder = ViewHolder.bind(parent.getContext(), convertView, parent, layoutRes | |
, position); | |
bindView(holder, getItem(position)); | |
return holder.getItemView(); | |
} | |
//添加一个元素 | |
public void add(T item) { | |
if (data == null) { | |
data = new ArrayList<>(); | |
} | |
data.add(item); | |
notifyDataSetChanged(); | |
} | |
//往特定位置,添加一个元素 | |
public void add(int position,T item){ | |
if (data == null) { | |
data = new ArrayList<>(); | |
} | |
data.add(position, item); | |
notifyDataSetChanged(); | |
} | |
public void remove(T item) { | |
if(data != null) { | |
data.remove(item); | |
} | |
notifyDataSetChanged(); | |
} | |
public void remove(int position) { | |
if(data != null) { | |
data.remove(position); | |
} | |
notifyDataSetChanged(); | |
} | |
public void clear() { | |
if(data != null) { | |
data.clear(); | |
} | |
notifyDataSetChanged(); | |
} | |
public abstract void bindView(ViewHolder holder, T obj); | |
public static class ViewHolder { | |
private SparseArray<View> mViews; //存储ListView 的 item中的View | |
private View item; //存放convertView | |
private int position; //游标 | |
private Context context; //Context上下文 | |
//构造方法,完成相关初始化 | |
private ViewHolder(Context context, ViewGroup parent, int layoutRes) { | |
mViews = new SparseArray<>(); | |
this.context = context; | |
View convertView = LayoutInflater.from(context).inflate(layoutRes, parent,false); | |
convertView.setTag(this); | |
item = convertView; | |
} | |
public static ViewHolder bind(Context context, View convertView, ViewGroup parent, | |
int layoutRes, int position) { | |
ViewHolder holder; | |
if(convertView == null) { | |
holder = new ViewHolder(context, parent, layoutRes); | |
} else { | |
holder = (ViewHolder) convertView.getTag(); | |
holder.item = convertView; | |
} | |
holder.position = position; | |
return holder; | |
} | |
public <T extends View> T getView(int id) { | |
T t = (T) mViews.get(id); | |
if(t == null) { | |
t = (T) item.findViewById(id); | |
mViews.put(id, t); | |
} | |
return t; | |
} | |
/** | |
* 获取当前条目 | |
*/ | |
public View getItemView() { | |
return item; | |
} | |
/** | |
* 获取条目位置 | |
*/ | |
public int getItemPosition() { | |
return position; | |
} | |
/** | |
* 设置文字 | |
*/ | |
public ViewHolder setText(int id, CharSequence text) { | |
View view = getView(id); | |
if(view instanceof TextView) { | |
((TextView) view).setText(text); | |
} | |
return this; | |
} | |
/** | |
* 设置图片 | |
*/ | |
public ViewHolder setImageResource(int id, int drawableRes) { | |
View view = getView(id); | |
if(view instanceof ImageView) { | |
((ImageView) view).setImageResource(drawableRes); | |
} else { | |
view.setBackgroundResource(drawableRes); | |
} | |
return this; | |
} | |
/** | |
* 设置标签 | |
*/ | |
public ViewHolder setTag(int id, Object obj) { | |
getView(id).setTag(obj); | |
return this; | |
} | |
public ImageView iconImg; | |
public TextView iconText; | |
} | |
} |
MainActivity.java
package org.mk.android.demospinneradapter; | |
import androidx.appcompat.app.AppCompatActivity; | |
import android.content.Context; | |
import android.os.Bundle; | |
import android.util.Log; | |
import android.view.View; | |
import android.widget.AdapterView; | |
import android.widget.BaseAdapter; | |
import android.widget.Spinner; | |
import android.widget.TextView; | |
import com.google.android.material.navigation.NavigationBarView; | |
import java.util.ArrayList; | |
import java.util.List; | |
public class MainActivity extends AppCompatActivity { | |
private Spinner spin_one; | |
private Spinner spin_two; | |
private Context mContext; | |
//判断是否为刚进去时触发onItemSelected的标志 | |
private boolean one_selected = false; | |
private boolean two_selected = false; | |
private List<GunBean> mData = null; | |
private BaseAdapter myAdadpter = null; | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
mData = new ArrayList<GunBean>(); | |
bindViews(); | |
} | |
private void bindViews() { | |
spin_one = (Spinner) findViewById(R.id.spinLevel); | |
spin_two = (Spinner) findViewById(R.id.spinGuns); | |
mData.add(new GunBean("ak",R.drawable.golden_qiang1)); | |
mData.add(new GunBean("大狙",R.drawable.golden_qiang)); | |
mData.add(new GunBean("AK",R.drawable.golden_qiang3)); | |
mData.add(new GunBean("不认识",R.drawable.normal_qiang)); | |
mData.add(new GunBean("突击步枪",R.drawable.normal_qiang)); | |
myAdadpter = new GenericAdapter<GunBean>(mData, | |
R.layout.item_spin_guns) { | |
public void bindView(ViewHolder holder, GunBean obj) { | |
holder.setImageResource(R.id.gunIcon, obj.getGunIcon()); | |
holder.setText(R.id.gunName, obj.getGunName()); | |
} | |
}; | |
spin_two.setAdapter(myAdadpter); | |
spin_one.setOnItemSelectedListener(new OnItemSelectedListener()); | |
spin_two.setOnItemSelectedListener(new OnItemSelectedListener()); | |
} | |
private class OnItemSelectedListener implements AdapterView.OnItemSelectedListener{ | |
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { | |
switch (parent.getId()){ | |
case R.id.spinLevel: | |
if(one_selected){ | |
Log.i("app", | |
">>>>>>您选的级别为:"+parent.getItemAtPosition(position).toString()); | |
}else one_selected = true; | |
break; | |
case R.id.spinGuns: | |
if(two_selected){ | |
TextView gunName = | |
(TextView) view.findViewById(R.id.gunName); | |
Log.i("app", | |
">>>>>>您选的枪为:"+gunName.getText().toString()); | |
}else two_selected = true; | |
break; | |
} | |
} | |
public void onNothingSelected(AdapterView<?> parent) { | |
} | |
} | |
} |
请自己动手运行一下,试试看效果吧。