Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android 輕松實現仿淘寶地區選擇

Android 輕松實現仿淘寶地區選擇

編輯:Android開發實例

  介紹

  最近用淘寶客戶端的時候,編輯地址的時候有個地區選擇的功能。看上面的效果覺得挺酷,滾動的時候,是最後一個從下面飛上來挨著前一個。就自己鼓搗一個出來玩玩。

  說了效果可能不太直觀,下面上兩張圖看看效果

  淘寶地區選擇效果

Android 輕松實現仿淘寶地區選擇

  再來一張自己的效果

Android 輕松實現仿淘寶地區選擇

  gif的效果可能不太好,大家自己用Android手機打開淘寶看看

  實現分析

  展示很簡單,ListView就可以了。對於動畫效果,只需要在getView的時候獲取到要展示的View,通過屬性動畫修改translationY就ok啦。由於地區選擇是一個界面,所以這裡還用到了Fragment的 addToBackStack知識

  1、用來展示的Fragment

  用一個Fragment來接受parentCode參數來獲取父地區的所有子地區,然後進行顯示。這裡用Fragment來做是因為用Activity的話,這樣的連續點擊都是同一類的界面不太適合。

Java代碼
  1. public class AreaFragment extends Fragment implements AdapterView.OnItemClickListener {  
  2.   
  3.     private static final String ARG_PARAM1 = "parentCode";  
  4.     @Bind(R.id.refresh_list_view)  
  5.     ListView mRefreshListView;  
  6.     @Bind(R.id.loadingBar)  
  7.     ProgressBar mLoadingBar;  
  8.   
  9.     private String mParam1;//parentCode參數  
  10.   
  11.     OkHttpClient mOkHttpClient = new OkHttpClient();  
  12.   
  13.     private OnFragmentInteractionListener mListener;  
  14.   
  15.     private AreaAdapter adapter;//地區adapter  
  16.   
  17.     public AreaFragment() {  
  18.     }  
  19.   
  20.     /** 
  21.      * Use this factory method to create a new instance of 
  22.      * this fragment using the provided parameters. 
  23.      * 
  24.      * @param param1 Parameter 1. 
  25.      * @return A new instance of fragment AreaFragment. 
  26.      */  
  27.     public static AreaFragment newInstance(String param1) {  
  28.         AreaFragment fragment = new AreaFragment();  
  29.         Bundle args = new Bundle();  
  30.         args.putString(ARG_PARAM1, param1);  
  31.         fragment.setArguments(args);  
  32.         return fragment;  
  33.     }  
  34.   
  35.     @Override  
  36.     public void onCreate(Bundle savedInstanceState) {  
  37.         super.onCreate(savedInstanceState);  
  38.         if (getArguments() != null) {  
  39.             //獲取父地區的code,用來查詢子地區  
  40.             mParam1 = getArguments().getString(ARG_PARAM1);  
  41.               
  42.         }  
  43.     }  
  44.   
  45.     @Override  
  46.     public View onCreateView(LayoutInflater inflater, ViewGroup container,  
  47.                              Bundle savedInstanceState) {  
  48.         // Inflate the layout for this fragment  
  49.         View view = inflater.inflate(R.layout.fragment_area, container, false);  
  50.         ButterKnife.bind(this, view);  
  51.         mRefreshListView.setOnItemClickListener(this);  
  52.   
  53.         FormEncodingBuilder builder = new FormEncodingBuilder();  
  54.         builder.add(ARG_PARAM1,mParam1);  
  55.   
  56.         //通過parentCode來請求地區,如果parentCode不存在就是第一級  
  57.         final Request request = new Request.Builder()  
  58.                 .url("http://123.184.16.19:8008/area/list")  
  59.                 .post(builder.build())  
  60.                 .build();  
  61.         mOkHttpClient.newCall(request).enqueue(new Callback(){  
  62.             @Override  
  63.             public void onFailure(Request request, IOException e) {  
  64.   
  65.             }  
  66.   
  67.             @Override  
  68.             public void onResponse(Response response) throws IOException {  
  69.                 final String res = response.body().string();  
  70.                 if (res!=null){  
  71.                     Gson gson = new Gson();  
  72.                     JsonResult jsonResult =  gson.fromJson(res, JsonResult.class);  
  73.                     if (jsonResult.isSuccess()){  
  74.                         List list = (List) jsonResult.getResult();  
  75.   
  76.                         List newList = new ArrayList();  
  77.                         Iterator iterator = list.iterator();  
  78.                         while (iterator.hasNext()){  
  79.                             Map map = (Map) iterator.next();  
  80.                             AreaInfo areaInfo = gson.fromJson(gson.toJson(map),AreaInfo.class);  
  81.                             newList.add(areaInfo);  
  82.                         }  
  83.                         adapter = new AreaAdapter(getContext(),newList);  
  84.                         getActivity().runOnUiThread(new Runnable() {  
  85.                             @Override  
  86.                             public void run() {  
  87.                       //拿到數據進行展示           
  88.                        mRefreshListView.setAdapter(adapter);  
  89.                             }  
  90.                         });  
  91.                     }  
  92.                 }  
  93.             }  
  94.         });  
  95.   
  96.         return view;  
  97.     }  
  98.   
  99.     @Override  
  100.     public void onAttach(Context context) {  
  101.         super.onAttach(context);  
  102.         if (context instanceof OnFragmentInteractionListener) {  
  103.             mListener = (OnFragmentInteractionListener) context;  
  104.         } else {  
  105.             throw new RuntimeException(context.toString()  
  106.                     + " must implement OnFragmentInteractionListener");  
  107.         }  
  108.     }  
  109.   
  110.     @Override  
  111.     public void onDetach() {  
  112.         super.onDetach();  
  113.         mListener = null;  
  114.     }  
  115.   
  116.     @Override  
  117.     public void onDestroyView() {  
  118.         super.onDestroyView();  
  119.         ButterKnife.unbind(this);  
  120.     }  
  121.   
  122.   
  123.   
  124.     @Override  
  125.     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {  
  126.         //單擊的時候需要處理地區點擊事件,統一交給Activity處理  
  127.         AreaInfo areaInfo = (AreaInfo) parent.getAdapter().getItem(position);  
  128.         if (areaInfo==null) return;  
  129.         if (mListener!=null){  
  130.             mListener.onFragmentInteraction(areaInfo);  
  131.         }  
  132.     }  
  133.   
  134.   
  135.     //用來和Activity交互的回調接口  
  136.     public interface OnFragmentInteractionListener {  
  137.         void onFragmentInteraction(AreaInfo areaInfo);  
  138.     }  

  我們用了一個Fragment來接受parentCode,用於請求下一級的地區,獲取成功之後進行了展示。並且提供了一個OnFragmentInteractionListener用來在onItemClick時與Activity交互。

  接下來看adapter,最開始我們提到了要實現淘寶的效果我們只需要拿到即將顯示的View,設置動畫就可以了。

  2、處理顯示效果的adapter

Java代碼
  1. class AreaAdapter extends BaseAdapter {  
  2.   
  3.         private List list;  
  4.   
  5.         private int lastPosition;  
  6.   
  7.         public AreaAdapter(Context context, List<AreaInfo> list) {  
  8.             this.list = list;  
  9.         }  
  10.   
  11.   
  12.         @Override  
  13.         public int getCount() {  
  14.             return list.size();  
  15.         }  
  16.   
  17.         @Override  
  18.         public Object getItem(int position) {  
  19.             return list.get(position);  
  20.         }  
  21.   
  22.         @Override  
  23.         public long getItemId(int position) {  
  24.             return 0;  
  25.         }  
  26.   
  27.         @Override  
  28.         public View getView(int position, View convertView, ViewGroup parent) {  
  29.             ViewHolder viewHolder = null;  
  30.             if (convertView==null){  
  31.                convertView =  LayoutInflater.from(getContext()).inflate(R.layout.area_list_item,parent,false);  
  32.                 viewHolder = new ViewHolder();  
  33.                 viewHolder.textView = (TextView) convertView.findViewById(android.R.id.text1);  
  34.                 convertView.setTag(viewHolder);  
  35.             }  
  36.             viewHolder = (ViewHolder) convertView.getTag();  
  37.             AreaInfo item = (AreaInfo) list.get(position);  
  38.             viewHolder.textView.setText(item.getAreaName());  
  39.             if (lastPosition<position&&lastPosition!=0){  
  40.                 ObjectAnimator.ofFloat(convertView,"translationY",convertView.getHeight()*2,0).setDuration(500).start();  
  41.   
  42.             }  
  43.             lastPosition = position;  
  44.             return convertView;  
  45.         }  
  46.   
  47.         class ViewHolder{  
  48.             TextView textView;  
  49.         }  
  50.     }  

  很常見的一個Adapter寫法,只是在getView當中獲取到了要顯示的view,通過

  ObjectAnimator.ofFloat(convertView,"translationY",convertView.getHeight()*2,0).setDuration(500).start()為veiw設置了動畫,

  這裡還用了個變量position來區別只有在向上滾動的時候才會有動畫。不過我覺得不加position區別的效果也不錯,大家可以試試。

  其實這樣已經實現了效果,接下來順便提一下Activity對Framgnet中onItemClick的處理。

  3、Activity和fragment的交互處理

Java代碼
  1. public class AreaSelectActivity extends AppCompatActivity implements AreaFragment.OnFragmentInteractionListener{  
  2.   
  3.     private Fragment oneFragment;  
  4.     private Fragment twoFragment;  
  5.   
  6.   
  7.     private Map map = new HashMap();  
  8.     @Override  
  9.     protected void onCreate(Bundle savedInstanceState) {  
  10.         super.onCreate(savedInstanceState);  
  11.         setContentView(R.layout.activity_area_select);  
  12.         ButterKnife.bind(this);  
  13.         //新建第一級地區,parentCode參數為null  
  14.         oneFragment = AreaFragment.newInstance("");  
  15.         FragmentManager fragmentManager = getSupportFragmentManager();  
  16.         fragmentManager.beginTransaction().replace(R.id.content,oneFragment).commit();  
  17.     }  
  18.   
  19.   
  20.     @Override  
  21.     public boolean onOptionsItemSelected(MenuItem item) {  
  22.         switch (item.getItemId()){  
  23.             case android.R.id.home:  
  24.                 FragmentManager fragmentManager = getSupportFragmentManager();  
  25.                 if (fragmentManager.getBackStackEntryCount()>0){  
  26.                     fragmentManager.popBackStack();  
  27.                 }else{  
  28.                     finish();  
  29.                 }  
  30.                 break;  
  31.         }  
  32.         return true;  
  33.     }  
  34.   
  35.   
  36.       
  37.      /** 
  38.      * 處理交互,hide前一個fragment,並且調用addToBackStack讓Fragment可以點擊back的時候顯示前一個fragment 
  39.      * 如果是第三級地區則直接返回地區選擇數據給上個Activity 
  40.      * @param areaInfo 被點擊的地區信息 
  41.      */  
  42.     @Override  
  43.     public void onFragmentInteraction(AreaInfo areaInfo) {  
  44.         if (areaInfo==null){  
  45.             return;  
  46.         }  
  47.         FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();  
  48.         int level = areaInfo.getLevel();  
  49.         switch (level){  
  50.             case 1:  
  51.                 map.put("provId",areaInfo.getId());  
  52.                 map.put("provName",areaInfo.getAreaName());  
  53.                 if (areaInfo.isLeaf()){  
  54.                     Intent intent = new Intent();  
  55.                     intent.putExtra("addressInfo", (Serializable) map);  
  56.                     setResult(RESULT_OK,intent);  
  57.                     finish();  
  58.                 }else{  
  59.                     transaction.hide(oneFragment);  
  60.                     transaction.add(R.id.content,twoFragment=AreaFragment.newInstance(areaInfo.getAreaCode()+"")).addToBackStack(null).commit();  
  61.                 }  
  62.                 break;  
  63.             case 2:  
  64.                 map.put("cityId",areaInfo.getId());  
  65.                 map.put("cityName",areaInfo.getAreaName());  
  66.                 if (areaInfo.isLeaf()){  
  67.                     Intent intent = new Intent();  
  68.                     intent.putExtra("addressInfo", (Serializable) map);  
  69.                     setResult(RESULT_OK,intent);  
  70.                     finish();  
  71.                 }else {  
  72.                     transaction.hide(twoFragment);  
  73.                     transaction.add (R.id.content, AreaFragment.newInstance(areaInfo.getAreaCode()+"")).addToBackStack(null).commit();  
  74.                 }  
  75.                 break;  
  76.             case 3:  
  77.                 map.put("districtId",areaInfo.getId());  
  78.                 map.put("districtName",areaInfo.getAreaName());  
  79.                 Intent intent = new Intent();  
  80.                 intent.putExtra("addressInfo", (Serializable) map);  
  81.                 setResult(RESULT_OK,intent);  
  82.                 finish();  
  83.                 break;  
  84.         }  
  85.   
  86.     }  
  87. }  

  這樣仿淘寶地區選擇就實現啦!

  結語

  大家可以自己寫測試接口,也可以直接調用我寫好的接口:

  http://123.184.16.19:8008/area/list

  源碼提供給大家參考:

  Android仿淘寶地區選擇

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved