Android Spinner识别ArrayList父级值并禁用/隐藏父项的实现方案
Android Spinner 隐藏/禁用层级结构中的父级项实现思路
我来帮你梳理下这个需求的实现思路,刚好之前做过类似的层级Spinner处理,分步骤来看:
一、核心:识别父级元素
首先得明确怎么判断一个元素是父级(存在子项):一个元素是父级,当且仅当列表中存在另一个元素以它为前缀,并且前缀后跟着.(比如1是父级,因为有1.1;4.1是父级,因为有4.1.1)。
高效识别父级的方法
为了避免重复遍历列表拖慢性能,推荐提前遍历一次所有元素,把所有父级元素缓存到一个Set中:
// 原始层级列表 List<String> originalLevelList = new ArrayList<>(Arrays.asList("1", "1.1", "1.2", ...)); Set<String> parentItemSet = new HashSet<>(); for (String item : originalLevelList) { String[] levelParts = item.split("\\."); // 只有层级大于1的元素才有父级 if (levelParts.length > 1) { StringBuilder parentBuilder = new StringBuilder(); // 逐级构建父级路径并加入Set for (int i = 0; i < levelParts.length - 1; i++) { if (i > 0) { parentBuilder.append("."); } parentBuilder.append(levelParts[i]); parentItemSet.add(parentBuilder.toString()); } } }
这样之后,判断任意元素是否是父级,只需要调用parentItemSet.contains(item)即可,非常高效。
二、两种处理Spinner的方案
根据你的需求,有两种常见的实现方式,你可以根据UI交互需求选择:
方案1:直接过滤父级,只显示叶子节点
如果不需要展示父级,只想让用户选择最终的子项,直接过滤出所有非父级元素,用过滤后的列表给Spinner设置适配器:
List<String> leafItems = new ArrayList<>(); for (String item : originalLevelList) { if (!parentItemSet.contains(item)) { leafItems.add(item); } } // 给Spinner设置普通适配器 ArrayAdapter<String> adapter = new ArrayAdapter<>( this, android.R.layout.simple_spinner_item, leafItems ); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); yourSpinner.setAdapter(adapter);
方案2:保留所有元素,但禁用父级项
如果需要展示父级(比如让用户看到层级结构)但禁止选择,需要自定义Spinner适配器,重写isEnabled()和getDropDownView()方法:
自定义适配器代码
public class LevelSpinnerAdapter extends ArrayAdapter<String> { private Set<String> parentItemSet; public LevelSpinnerAdapter(Context context, int resource, List<String> objects, Set<String> parentSet) { super(context, resource, objects); this.parentItemSet = parentSet; } // 核心:判断当前位置的项是否可点击 @Override public boolean isEnabled(int position) { String currentItem = getItem(position); return !parentItemSet.contains(currentItem); } // 给禁用的父级项设置不同的UI样式(比如灰色字体) @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { View view = super.getDropDownView(position, convertView, parent); TextView textView = (TextView) view; if (!isEnabled(position)) { // 设置禁用状态的字体颜色(需要在colors.xml中定义grey色值) textView.setTextColor(ContextCompat.getColor(getContext(), R.color.grey)); } else { textView.setTextColor(ContextCompat.getColor(getContext(), R.color.black)); } return view; } }
使用自定义适配器
LevelSpinnerAdapter adapter = new LevelSpinnerAdapter( this, android.R.layout.simple_spinner_item, originalLevelList, parentItemSet ); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); yourSpinner.setAdapter(adapter);
这样设置后,父级项会显示为灰色,并且无法被选中,完全符合你描述的效果。
内容的提问来源于stack exchange,提问作者Nicolas Parra Santamaria
相关产品推荐
相关产品推荐

