域名解析后怎么做网站,网站编程软件有哪些,婚纱摄影的网站模板,安阳网络教研平台登录目录
效果图为什么需要搜索功能如何设计搜索本地的功能#xff0c;如何维护呢#xff1f;总结
一、效果图 二、为什么需要搜索功能
找一个选项#xff0c;需要花非常多的时间#xff0c;并且每次都需要指导客户在哪里#xff0c;现在只要让他们搜索一下就可以。这也是模…目录
效果图为什么需要搜索功能如何设计搜索本地的功能如何维护呢总结
一、效果图 二、为什么需要搜索功能
找一个选项需要花非常多的时间并且每次都需要指导客户在哪里现在只要让他们搜索一下就可以。这也是模仿手机里面的设置功能来进行开发的。这些选项我是存储在本地的。参数太多暂时还没考虑做到后台当然即使后面做到后台也只是替换数据而已。 三、如何设计搜索本地的功能如何维护呢
我们可以看到效果图
有开关类的、有输入类的。有分类系统设置、串口设置、功能开启等等。有默认值如123456默认是关的等等。…
so我们需要设计数据模型。
3.1 设计数据模型
大家可以思考一下为什么数据模型要这样设计有默认值有key有nameId
/*** nameId:显示名称,这里存储的是rid,方便后续国际化* nameS:名称* category分类* drfault默认值* type类型 1 多选项值 2 开关 3 输入类* mmkvName保存key*/
enum class OtherEnum(var nameId:Int,var nameS:String,var category:String,var drfault:Any,var type:Int,var mmkvName: String) {MDB(R.string.base_two_code,通讯协议,串口设置,MDB, 2,MMKVName.MDB),CHANGE(R.string.base_nayax,找零功能,找零设置,false, 1,MMKVName.CHANGE),CONTACT_NUMBER(R.string.leak_canary_test_class_name,联系方式,系统设置,123456, 2,MMKVName.CONTACT_NUMBER),
}3.2 Repo类
这里只是增加了一个要展示的数据后面如果把数据放在了后端也就只是替换这一部分就可以。
class OtherFragmentRepo Inject constructor() : BaseRepository() {var arrayList: MutableListOtherEnum Arrays.asList(//用于列表展示OtherEnum.MDB,OtherEnum.CHANGE,OtherEnum.CONTACT_NUMBER,)}如果有新增的数据只需要在这里增加就可以了。这样也非常好维护所以需要数据模型设置好来。
3.3 VM主要是提供搜索的功能
search方法其实就是遍历所有的集合元素找到匹配的内容存放到一个list里面进行展示通过_readAllDataSuccess进行数据通知界面刷新。因为数据量较小不到100个左右所以这里使用的for循环遍历。
class OtherFragmentVM Inject constructor(private val mRepo: OtherFragmentRepo) : BaseViewModel() {//搜索功能【通信设置、系统设置、功能开启等等】//1. 首先我们需要先添加我们的所有设置。【通过一个bean来存储一个list来存储所有的】//bean名称分类类型【开关类、输入类、多值类、音量调节】value//举例优惠券、功能开启、开关、false//2. 首先把所有的功能项拿到进行遍历//3. 具体的数据展示:如何展示呢navigationfragment【搜索的时候展示另外一个fragment而不搜索的时候展示其中一个。】//1.拿到所有的通讯设置var list :ArrayListOtherEnum ArrayList()private var _readAllDataSuccess MutableLiveDataInt()//是否读取所有数据成功val readAllDataSuccess: LiveDataInt get() _readAllDataSuccess//2.搜索功能fun search(searchText: CharSequence) {list.clear()val arrayList mRepo.arrayListfor (otherEnum in arrayList) {val stringRes UiUtil.getStringRes(otherEnum.nameId).uppercase()if (stringRes.contains(searchText.toString().uppercase())) {list.add(otherEnum)}}_readAllDataSuccess.value list.size}}3.4 Fragment
搜索功能先判断是否输入内容为空如果为空就提示用户。符合条件就调用search进行模糊匹配搜索。搜索到以后就将默认显示的navigation进行GONE将搜索结果进行VISIBLE
class OtherFragment : BaseFragmentBackstageFragmentOtherBinding, OtherFragmentVM() {private val TAG OtherFragmentoverride val mViewModel: OtherFragmentVM by viewModels()override fun createVB() BackstageFragmentOtherBinding.inflate(layoutInflater)private var otherAdapter: OtherAdapter? nulloverride fun BackstageFragmentOtherBinding.initView() {Log.d(TAG, OtherFragment initView: )ivSearch.setOnClickListener {val searchText etSearch.text.trim()Log.d(TAG, searchText: searchText)if(searchText){ToastUtil.switchToastStyleToWarn(请输入内容后搜索)returnsetOnClickListener}//进行数据的搜索mViewModel.search(searchText)}with(rvOtherSearch){//设置布局排列方式默认垂直排列val gridLayoutManager: GridLayoutManager GridLayoutManager(thisOtherFragment.context, 2, androidx.recyclerview.widget.GridLayoutManager.VERTICAL, false)layoutManager gridLayoutManagermViewModel.list.add(OtherEnum.CHANGE)otherAdapter OtherAdapter(mViewModel.list)otherAdapter!!.setItemListener(object : AdapterClickListener {override fun onClickListener(view: View?, position: Int, data: String?) {}})adapter otherAdapter}}override fun initObserve() {observeLiveData(mViewModel.readAllDataSuccess,::searchResult)}fun searchResult(i: Int) {if (i0) {ToastUtil.switchToastStyleToWarn(搜索结果为空)mBinding.rvOtherSearch.visibility View.GONEmBinding.fcvOther.visibility View.VISIBLEreturn}mBinding.rvOtherSearch.visibility View.VISIBLEmBinding.fcvOther.visibility View.GONELog.d(TAG, searchResult: mViewModel.list)otherAdapter?.setData(mViewModel.list)otherAdapter?.notifyDataSetChanged()}override fun initRequestData() {}}3.5 xmlUI应该如何编写呢
UI方面 1最简单的一个输入框一个搜索按钮一个recycleview展示搜索结果一个navigationFragmentContainerView展示默认的内容也就是不搜索的时候全部展示。 2扩展1. 搜索历史热门搜索输入的时候补全提示。后面可以增加。我们先实现最简单的。
?xml version1.0 encodingutf-8?
androidx.constraintlayout.widget.ConstraintLayout xmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:apphttp://schemas.android.com/apk/res-autoxmlns:toolshttp://schemas.android.com/toolsandroid:layout_widthmatch_parentandroid:backgrounddrawable/no_nav_bgandroid:layout_heightmatch_parentnet.lucode.hackware.magicindicator.MagicIndicatorandroid:idid/magic_otherandroid:layout_widthmatch_parentandroid:layout_height88dpandroid:backgrounddrawable/backstage_shape_product_navandroid:paddingLeft20dpapp:layout_constraintEnd_toEndOfparentapp:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toTopOfparent /EditTextandroid:idid/et_searchandroid:layout_width1000dpandroid:layout_height80dpandroid:backgrounddrawable/home_other_rectangle_backgroundandroid:paddingLeft20dpandroid:maxLines1android:inputTypetextandroid:layout_marginVertical10dpandroid:hintstring/backstage_search_hintandroid:textColor#2E80DDandroid:textSize32spandroid:textStyleboldapp:layout_constraintEnd_toEndOfparentapp:layout_constraintHorizontal_bias0.51app:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toBottomOfid/magic_other /ImageViewandroid:idid/iv_searchandroid:layout_width90dpandroid:layout_height90dpandroid:padding10dpandroid:layout_marginLeft10dpandroid:srcdrawable/searchapp:layout_constraintBottom_toBottomOfid/et_searchapp:layout_constraintStart_toEndOfid/et_searchapp:layout_constraintTop_toTopOfid/et_search /androidx.fragment.app.FragmentContainerViewandroid:idid/fcv_otherandroid:nameandroidx.navigation.fragment.NavHostFragmentandroid:layout_widthmatch_parentandroid:layout_height0dpapp:layout_constraintBottom_toBottomOfparentapp:layout_constraintEnd_toEndOfparentapp:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toBottomOfid/et_searchapp:navGraphnavigation/backstage_other_nav /androidx.recyclerview.widget.RecyclerViewandroid:idid/rv_other_searchandroid:layout_widthmatch_parentandroid:layout_height0dpandroid:visibilitygoneapp:layout_constraintBottom_toBottomOfparentapp:layout_constraintEnd_toEndOfparentapp:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toBottomOfid/et_search //androidx.constraintlayout.widget.ConstraintLayout3.6 Adapter这里我们需要思考子项不一样应该如何设计保存也数据逻辑也不一样!
子项不一样我们应该如何处理呢我们可以看到otherEnum里面有一个type属性就是用于定义不同的布局的如下那么开关类的保存输入类的保存有应该如何呢只需要使用不同的布局进行不同的逻辑进行处理就可以。如下 class OtherAdapter(var productList: MutableListOtherEnum) :RecyclerView.AdapterRecyclerView.ViewHolder() {private val TAG HomeProductAdaptervar SWITCH_TYPE 1var INPUT_TYPE 2fun setItemListener(itemListener: AdapterClickListener?) {this.itemListener itemListener}private var itemListener: AdapterClickListener? nullprivate var generalParamData: MutableListString? null//开关类布局inner class MyViewHolder(binding: BackstageItemSystemSettingsBinding) :ViewHolder(binding.root) {private val mBinding bindingfun bind(otherEnum: OtherEnum) {mBinding.run {Log.d(TAG, MyViewHolder bind: otherEnum)tvName.text UiUtil.getStringRes(productList[layoutPosition].nameId)//开关类的数据保存rgSwitch.setOnCheckedChangeListener { group, checkedId -when (checkedId) {R.id.rb_close - {SpUtils.putBoolean(otherEnum.mmkvName,false)}R.id.rb_open - {SpUtils.putBoolean(otherEnum.mmkvName,true)}else - {}}}var flag SpUtils.getBoolean(otherEnum.mmkvName,otherEnum.drfault as Boolean)if(flag true){rbOpen.isChecked true}else{rbClose.isChecked true}}}}//输入类的布局inner class InputViewHolder(binding: BackstageItemInputBinding) : ViewHolder(binding.root) {private val mBinding bindingfun bind(otherEnum: OtherEnum) {mBinding.run {Log.d(TAG, InputViewHolder bind: otherEnum.mmkvName: SpUtils.contains(otherEnum.mmkvName))tvName.text UiUtil.getStringRes(productList[layoutPosition].nameId)var defaultValue SpUtils.getString(otherEnum.mmkvName,otherEnum.drfault as String)etValue.setText(defaultValue)//输入类的数据保存btnUpdate.setOnClickListener {val value etValue.text.trim().toString()if(value){ToastUtil.switchToastStyleToWarn(输入为空)returnsetOnClickListener}SpUtils.putString(otherEnum.mmkvName,value)ToastUtil.switchToastStyleToSuccess(更新成功:otherEnum.mmkvName)}}}}override fun getItemViewType(position: Int): Int {//不同的类型使用不同的布局return productList[position].type}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {when (viewType) {SWITCH_TYPE - {return MyViewHolder(BackstageItemSystemSettingsBinding.inflate(LayoutInflater.from(parent.context),parent,false))}INPUT_TYPE - {Log.d(TAG, onCreateViewHolder: InputViewHolder:viewType)return InputViewHolder(BackstageItemInputBinding.inflate(LayoutInflater.from(parent.context),parent,false))}else - {}}return MyViewHolder(BackstageItemSystemSettingsBinding.inflate(LayoutInflater.from(parent.context),parent,false))}override fun getItemCount(): Int {return productList.size}override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {if (holder is MyViewHolder) {holder.bind(productList.get(position))} else if (holder is InputViewHolder) {holder.bind(productList.get(position))}itemListener?.onClickListener(holder.itemView, position, null)}fun setData(productList: MutableListOtherEnum) {this.productList productList}
}
四、总结
其实搜索功能的重点在于数据模型的设计还有apdater布局的设置。以前都是一个一个控件的增加数据也可以直接就增加所以维护很模仿现在换成了recycleview所以我们需要思考每一个item他的数据应该如何展示默认值是如何在哪个分类如何保存数据。