We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
几乎没有platform都有自己的下拉框,安卓翻一下官网教程,看上去应该用的是Spinner
<Spinner android:id="@+id/spinnerTest" android:layout_marginTop="300dp" android:layout_width="150dp" android:layout_height="80dp" />
SpinnerAdapter是接口,我们使用的他的一个具体实现类ArrayAdapter
private static final String[] buildings ={"宝石大楼","25号楼"}; Spinner spinner = view.findViewById(R.id.spinnerTest); ArrayAdapter<String> adapter = new ArrayAdapter<>(this.getContext(), android.R.layout.simple_spinner_item, buildings); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter);
其中比较陌生的是两个Resource的定义
<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" style="?android:attr/spinnerItemStyle" android:singleLine="true" android:layout_width="match_parent" android:layout_height="wrap_content" android:ellipsize="marquee" android:textAlignment="inherit"/>
通过ide找过去发现就一个文本显示,表示展开的单项的UI
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" style="?android:attr/spinnerDropDownItemStyle" android:singleLine="true" android:layout_width="match_parent" android:layout_height="?android:attr/dropdownListPreferredItemHeight" android:ellipsize="marquee"/>
这个应该是未展开时候的UI主体
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { String building = (String) parent.getItemAtPosition(position); MessageHelper.ShowToast( view.getContext(), String.format("%s building selected",building) ); } @Override public void onNothingSelected(AdapterView<?> parent) { } });
可以监听选中获取未选的情况
就是现在的代码我只能写在View层,并不能和我的业务数据好好的结合 我要解决以下问题
从ViewModel层绑定数据源
选中项需要能持有
监听选中事件到ViewModel的Method
public class SpinnerBindingAdapters { @BindingAdapter(value = {"itemsSource","onItemSelected","selectedIndex"},requireAll = false) public static <T> void setSpinnerItems(Spinner spinner , List<T> itemsSource,final OnMyItemSelectedListener listener , int index){ SimpleArrayAdapter<T> adapter; @SuppressWarnings("unchecked") SimpleArrayAdapter<T> oldAdapter = (SimpleArrayAdapter<T>)spinner.getAdapter(); boolean createNew = oldAdapter != null && oldAdapter.list == itemsSource; if( createNew ){ adapter = oldAdapter; adapter.notifyDataSetChanged(); } else { adapter = new SimpleArrayAdapter<>(spinner.getContext(), android.R.layout.simple_spinner_item, itemsSource); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @SuppressWarnings("OptionalUsedAsFieldOrParameterType") private Optional<Integer> lastPosition= Optional.empty(); @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { //String itemValue = (String) parent.getItemAtPosition(position); if( lastPosition.isPresent() && lastPosition.get() == position ){ return; } lastPosition = Optional.of(position); listener.onItemSelected(position); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); } spinner.setAdapter(adapter); if( spinner.getSelectedItemPosition() != index ) { spinner.setSelection(index); } } public static class SimpleArrayAdapter<T> extends ArrayAdapter<T>{ private final List<T> list; public SimpleArrayAdapter(Context context, @LayoutRes int resource, List<T> objects){ super(context,resource,objects); this.list = objects; } } }
略过中间过程了(很多坑),直接上“成果”了
还是靠我们神奇的BindingAdapter来实现 @BindingAdapter标记的函数解析
itemsSource:用来绑定来自ViewModel的数据集
onItemSelected:用来绑定下拉框切换的事件绑定
selectedIndex:用来绑定已选中的下标值,能让整个页面“记住”
为什么要扩展ArrayAdapter写个自定义类? 是为了能持有绑定的list对象,如果对象的引用一致则不需要初始化Adapter
为啥有个Optional lastPosition? 因为有个小bug,设置selection后会触发Listener两次,一时解决不了,只能加一个判断过滤一下
<FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".fragments.SpaceFragment"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:textSize="32sp" android:text="@string/space" /> <Spinner android:id="@+id/spinnerTest" app:itemsSource="@{dataContext.buildings}" app:selectedIndex="@{dataContext.buildingIndex}" app:onItemSelected="@{(item)->dataContext.onSelected(item)}" android:layout_marginTop="300dp" android:layout_width="150dp" android:layout_height="80dp" /> </FrameLayout>
View部分的定义,不解释了,很清楚了
@HiltViewModel public class SpaceViewModel extends ObservableViewModel { private final List<String> buildings = Arrays.asList( "宝石大楼","25号楼" ); private int buildingIndex; @Inject public SpaceViewModel( @NonNull Application application ) { super(application); } @Bindable public List<String> getBuildings() { return buildings; } @Bindable public int getBuildingIndex() { return buildingIndex; } public void onSelected(int position ){ Logger.i("SpaceViewModel get select:%s",position); if( buildingIndex != position ){ buildingIndex = position; } } }
ViewModel部分源码
这次基本完成了Spinner的简版 MVVM实现。 当然未来还可以拓展
还有一些教训
参考
The text was updated successfully, but these errors were encountered:
No branches or pull requests
引言
几乎没有platform都有自己的下拉框,安卓翻一下官网教程,看上去应该用的是Spinner
标准用法
SpinnerAdapter是接口,我们使用的他的一个具体实现类ArrayAdapter
其中比较陌生的是两个Resource的定义
通过ide找过去发现就一个文本显示,表示展开的单项的UI
这个应该是未展开时候的UI主体
可以监听选中获取未选的情况
好像少了点什么不开心
就是现在的代码我只能写在View层,并不能和我的业务数据好好的结合
我要解决以下问题
从ViewModel层绑定数据源
选中项需要能持有
监听选中事件到ViewModel的Method
将MVVM进行到底!
略过中间过程了(很多坑),直接上“成果”了
还是靠我们神奇的BindingAdapter来实现
@BindingAdapter标记的函数解析
itemsSource:用来绑定来自ViewModel的数据集
onItemSelected:用来绑定下拉框切换的事件绑定
selectedIndex:用来绑定已选中的下标值,能让整个页面“记住”
为什么要扩展ArrayAdapter写个自定义类?
是为了能持有绑定的list对象,如果对象的引用一致则不需要初始化Adapter
为啥有个Optional lastPosition?
因为有个小bug,设置selection后会触发Listener两次,一时解决不了,只能加一个判断过滤一下
View部分的定义,不解释了,很清楚了
ViewModel部分源码
总结
这次基本完成了Spinner的简版 MVVM实现。
当然未来还可以拓展
基本上是RecyclerView兄弟,Adapter用法有神似的地方,比RecyclerView用起来简单。
还有一些教训
参考
The text was updated successfully, but these errors were encountered: