日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

实现京东商城地址选择效果(效果还挺一致的)

發布時間:2023/12/16 69 豆豆
生活随笔 收集整理的這篇文章主要介紹了 实现京东商城地址选择效果(效果还挺一致的) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言部分

最近新項目要中設計一個地址選擇的效果(效果和某東的商城一樣一樣的),雖然網上已經有現成的方案了,但是最近剛好時間還算充裕所以想了想還是準備自己來做一個,順便加深一下對自定義dialog的認識。

Demo中主要實現了京東的地址選擇的控件效果,開始本來計劃用dialog來實現的,但是網上似乎說推薦使用DialogFragment來封裝,剛好我還沒使用過DialogFragment來做一個,說是封裝其實只是定義了一個AddressSelectDialog對外提供了一些基礎的方法,如果需要使用可以自行修改。

放個效果圖鎮樓

內容部分

寫一個功能的基本流程:構思5分,代碼3分,完善2分。

因為以前我寫功能都是上來就開寫,一口氣寫個差不多完事,可是完成后你會發現寫的很混亂,因為寫之前沒有很好的構思項目,這樣看似效率很高,但是后來你回來改的時間會很多,這也就是為什么軟件開發一直都是強調架構的原因吧。

進入正題

其實這個地址選擇權很以前的三級聯動一樣不過是樣式上不同,個人覺得還是比較舒服的。

功能分析拆解一下,做起來更有條不紊。

  • 我們首先需要頭部三個tab,這三個tab也不是一個固定的可能發生增減。

  • 下方上一個地址的列表,省–市--區。

  • 省市區的列表是有關聯關系的,但是實際上同一時間只會有一個列表出現。

  • 具體的實現過程

  • 第一部分是頭部這里我使用了design包中的TabLayout來實現,用起來還是比較舒服,下面看一下布局和相關代碼:

    <android.support.design.widget.TabLayoutandroid:id="@+id/tb_head_indicator"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"app:tabIndicatorColor="@color/red"app:tabSelectedTextColor="@color/red" />

    上面的布局匯總很簡單,這里說明一下注意地方:

    • 其實你觀察源碼會發現TabLayout是繼承了HorizontalScrollView類,這也是可以滾動的原因所在。然后tabIndicatorColor是設置下面的指示標的顏色,tabSelectedTextColor設置選中文字的顏色。這里沒有什么特殊的樣式,其實TabLayout的功能還是很強大的,基本上你所需要的實現樣式都提供了。
  • 下面就是一個列表了啊,這個地方我們發現同時出現的只有一個列表,雖然是說省市區三個類表。這里的方案我想到三種:

    • 一個是分別弄三個RecyclerView(或者ListView)來實現,然后重疊在這個布局中,通過標記來設置顯示哪一個RecyclerView,這個方案的好處就是只需要初始化一次就可以了,并且選中的狀態也可以直接保留在列表中。

    • 一個是使用一個RecyclerView并給初始化三個不同的Adapter來實現,這個方案使得RecyclerView一只在界面中存在,通過給RecyclerView綁定不同的RecyclerView來實現切換。本Demo就是通過實現這個方案來做的。

    • 這種就是RecyclerView和RecyclerView用同一個通過切換tab來更換里面的數據來做,其實這個和上面的很像,上面的方案也很容易改成這樣。

      以上我覺得都還好吧,寫起來難以程度略不同,第2和第3 差不多,主要的邏輯都在通過標識位不斷的更新數據上,唯一的區別就是一個更新數據源,一個直接把適配器換掉了;第一個寫起來應該算是比較簡單,因為獨立出來三個不同的列表,只第一次把數據初始化進去就好了,后期只通過標識位來切換顯示就可以。

    下面貼出部分代碼片段:

    //初始化了三個adapter,先把第一個省的adapter綁定到RecyclerView上了。 private void initRecyclerView() {rvTabExample.setLayoutManager(new LinearLayoutManager(getContext()));rvTabExample.addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL));//省地址recyclerViewTabAdapter = new RecyclerViewTabAdapter(getContext());//市地址recyclerViewCityAdapter = new RecyclerViewCityAdapter(getContext());//區地址recyclerViewAreaAdapter = new RecyclerViewAreaAdapter(getContext());recyclerViewTabAdapter.setAddressList(cityBeanList);recyclerViewTabAdapter.setBaseItemClickListener(this);recyclerViewCityAdapter.setBaseItemClickListener(this);recyclerViewAreaAdapter.setBaseItemClickListener(this);rvTabExample.setAdapter(recyclerViewTabAdapter);}

    處理adapter更新的代碼部分,主要通過標記tabCurrentPosition當前顯示的tab來區分顯示,不同tab下adapter傳入的類型不同,這里如果使用同一個的話需要在adapter的內部來進行判斷了,或者在外面把數據做統一處理,傳入adapter的都統一一下。

    private void upDataArray() {if (tabCurrentPosition == oldTabCurrentPosition) {return;}//設置顏色LogUtil.i("upDataArray--更新列表啊:::" + tabCurrentPosition);switch (tabCurrentPosition) {case 0:recyclerViewTabAdapter.setCurrentSelect(currentSelectMap.get(tabCurrentPosition));recyclerViewTabAdapter.setAddressList(cityBeanList);rvTabExample.setAdapter(recyclerViewTabAdapter);break;case 1:cityIndex = currentSelectMap.get(0) == -1 ? initPosition : currentSelectMap.get(0);recyclerViewCityAdapter.setAddressList(cityBeanList.get(cityIndex).getCity());recyclerViewCityAdapter.setCurrentSelect(currentSelectMap.get(tabCurrentPosition));rvTabExample.setAdapter(recyclerViewCityAdapter);break;case 2:cityIndex = currentSelectMap.get(0) == -1 ? initPosition : currentSelectMap.get(0);int cityInnerIndex = currentSelectMap.get(1) == -1 ? initPosition : currentSelectMap.get(1);recyclerViewAreaAdapter.setAddressList(cityBeanList.get(cityIndex).getCity().get(cityInnerIndex).getArea());recyclerViewAreaAdapter.setCurrentSelect(currentSelectMap.get(tabCurrentPosition));rvTabExample.setAdapter(recyclerViewAreaAdapter);break;default:break;}oldTabCurrentPosition = tabCurrentPosition;}

    因為聯動的關系,所以每次點擊tab或者點擊item的時候都會出發更新的操作。

  • 這里是比較關鍵的部分,主要是處理了點擊事件,當點擊事件發生的時候要伴隨著tab的切換操作。

    這里我們有一個標記的當前tab的標識tabCurrentPosition,并且我會把每一個列表里選中的position存儲到map中,并且使用tabCurrentPosition當作key,這樣在切換tab回顯的時候就方便一些,這里以前我使用過List但是效果不好,因為不斷切換Tab的話還要去重制List。

    @Override public void onItemClick(View view, int position) { //設置一下tab上的文字switch (tabCurrentPosition) {case 0:mTabLayout.getTabAt(tabCurrentPosition).setText(recyclerViewTabAdapter.getAddressList().get(position).getName());break;case 1:mTabLayout.getTabAt(tabCurrentPosition).setText(recyclerViewCityAdapter.getAddressList().get(position).getName());break;case 2:mTabLayout.getTabAt(tabCurrentPosition).setText(recyclerViewAreaAdapter.getAddressList().get(position));break;default:break;}//相同tab下進行的position變化處理,這里要提醒一下,當滿足這個條件的時候,就是說明你下一個tab對應的數據需要重新初始化了。if (currentSelectMap.get(tabCurrentPosition) != position) {int removeTab = mTabLayout.getTabCount() - 1;while (removeTab > tabCurrentPosition) {if (mTabLayout.getTabAt(removeTab) != null) {mTabLayout.removeTabAt(removeTab);currentSelectMap.put(removeTab, -1);}removeTab--;}//防止越界啊,目前只寫了三級。其實是可以寫成很多。這里沒有擴展性if (tabCurrentPosition >= 2) {tabCurrentPosition = 2;} else {mTabLayout.addTab(mTabLayout.newTab().setText("請選擇"), false);currentSelectMap.put(tabCurrentPosition + 1, -1);}}//設置當前tab下的選中狀態currentSelectMap.put(tabCurrentPosition, position);//滾動到下一個tabtabCurrentPosition++;//越界的話處理為最后一個tabif (tabCurrentPosition >= mTabLayout.getTabCount()) {tabCurrentPosition = mTabLayout.getTabCount() - 1;if (selectAddressResultListener != null) {int[] result = {currentSelectMap.get(0), currentSelectMap.get(1), currentSelectMap.get(2)};selectAddressResultListener.selectAddressResult(result);dismiss();}} else {mTabLayout.setScrollPosition(tabCurrentPosition, 0f, true);}LogUtil.i("tabCurrentPosition--" + tabCurrentPosition + "tabCount" + mTabLayout.getTabCount());//如果在最后一個列表中切換的話這里單獨處理一下,因為upDataArray限制里更新的頻率。if (tabCurrentPosition == oldTabCurrentPosition) {switch (tabCurrentPosition) {case 0:recyclerViewTabAdapter.setCurrentSelect(currentSelectMap.get(tabCurrentPosition));recyclerViewTabAdapter.notifyDataSetChanged();break;case 1:recyclerViewCityAdapter.setCurrentSelect(currentSelectMap.get(tabCurrentPosition));recyclerViewCityAdapter.notifyDataSetChanged();break;case 2:recyclerViewAreaAdapter.setCurrentSelect(currentSelectMap.get(tabCurrentPosition));recyclerViewAreaAdapter.notifyDataSetChanged();break;default:break;}} else {upDataArray();}}

    其實上面基本就算主要步驟了,包含初始化—數據填充—點擊處理,完成的話基本上就實現了效果,下面我稍微完善一下這個控件。

  • 數據回顯,這是個比較常規的需求,所以也加了上來。如下使用了兩個方法,因為我發現如果show頁面后直接更新數據的話會報錯空指針,如果延遲一會就不出現問題,感覺是初始化界面的未完成就使用控件導致。所以稍微延遲一點來繞過這個問題。

    public void setSelectAddress(final int[] selectAddress) {new Handler().postDelayed(new Runnable() {@Overridepublic void run() {setSelectAddress(selectAddress, true);}}, 60);}private void setSelectAddress(int[] selectAddress, boolean isUpdata) {if (selectAddress != null && selectAddress.length != 0 && cityBeanList != null) {for (int i = 0; i < 3; i++) {//保存選擇currentSelectMap.put(i, selectAddress[i]);}CityBean cityBean = cityBeanList.get(currentSelectMap.get(0));CityBean.CityBeanInner cityBeanInner = cityBean.getCity().get(currentSelectMap.get(1));String name = cityBeanInner.getArea().get(currentSelectMap.get(2));mTabLayout.removeAllTabs();//初始化tabmTabLayout.addTab(mTabLayout.newTab().setText(cityBean.getName()), false);mTabLayout.addTab(mTabLayout.newTab().setText(cityBeanInner.getName()), false);mTabLayout.addTab(mTabLayout.newTab().setText(name), true);tabCurrentPosition = currentSelectMap.size() - 1;//選擇最后mTabLayout.setScrollPosition(tabCurrentPosition, 0f, true);//更新集合upDataArray();}}

    數據回顯的實現是通過傳入標識來完成,因為我在dialog內部維護了這個標志,外部只需要傳如標識并且更新一下界面就可以,界面的話需要更新三個tab和最后一個列表就可以了。由于初期就設計了三個列表所以這個標識我只是用了前三個長度(偷懶一下)。

  • 以上步驟就基本完成了這個功能了

    剩下一些零碎東西,如:數據源的設置,你需要參考一下我的CityBean實體;監聽設置,當點擊最后列表的條目時候就把完整的數據返回去取了。

    結束部分

    現在android開源的東西太多,我們似乎正在淪為代碼搬運工,但是我認為有些些東西還是要親自去做,能看懂和能寫出來中間差了很長一段路。再次共勉,共同進步。

    傳送到GitHub

    有問題歡迎糾正,謝謝啦

    如果對你有幫助就點個贊把,你的鼓勵是我寫作的動力。

    總結

    以上是生活随笔為你收集整理的实现京东商城地址选择效果(效果还挺一致的)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。