您好,登錄后才能下訂單哦!
這篇文章主要介紹Android如何實(shí)現(xiàn)仿京東手機(jī)端類別頁(yè),文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
京東手機(jī)端的類別標(biāo)簽頁(yè), 是一個(gè)左側(cè)滑動(dòng)可選擇類別, 右側(cè)一個(gè)類別明細(xì)的列表聯(lián)動(dòng)頁(yè)面. 當(dāng)用戶選擇左側(cè)選項(xiàng), 可在右側(cè)顯示更多選項(xiàng)來(lái)選擇. 實(shí)現(xiàn)方式也不少. 最常見(jiàn)的當(dāng)然是左側(cè)和右側(cè)各一個(gè)Fragment, 左側(cè)Fragment放置ListView, 右側(cè)放顯示類別明細(xì)的Fragment. 如果覺(jué)得頁(yè)面包含的Fragment太多, 左側(cè)直接給一個(gè)ListView就可以了.不影響效果.
效果圖:
例子中值得注意的三點(diǎn):
左側(cè)列表點(diǎn)擊某個(gè)Item可以自動(dòng)上下滑動(dòng),使所點(diǎn)擊的item自動(dòng)移至列表中間
點(diǎn)擊item后保留背景色不變
右側(cè)布局
針對(duì)上面三個(gè)點(diǎn),這里采取如下的解決方法:
計(jì)算可見(jiàn)列表的可見(jiàn)首項(xiàng)或末項(xiàng)position值,使用smoothScrollToPosition()方法實(shí)現(xiàn)滑動(dòng)
自定義列表selector按下和松開(kāi)的背景色,在adapter去更新并控制item的背景色
右側(cè)布局,采用Fragment是最好的. 里面使用ScrollView裝載所有數(shù)據(jù),可以動(dòng)態(tài)的addView(),removeView(), 網(wǎng)格布局使用GridView. 由于Fragment, 所以更新數(shù)據(jù)和更新View都非常方便, 所以例子中直接用靜態(tài)頁(yè)面模擬數(shù)據(jù)了.
重在通過(guò)簡(jiǎn)單的例子解釋這種實(shí)現(xiàn)思路, 當(dāng)然實(shí)現(xiàn)不是唯一的.
然后,我們先來(lái)模擬右側(cè)的Fragment數(shù)據(jù),一看就懂的代碼:
public class JDFragment extends Fragment{ String TAG = "JDFragment"; private View rootView = null; private LinearLayout llayout_main = null; private TextView tv = null; private LinearLayout.LayoutParams lp_gd = null; private LinearLayout.LayoutParams lp_tv = null; private ArrayList<Category> itemList = null; private GDAdapter adapter = null; @Override public void onAttach(Activity activity) { Log.e(TAG, "onAttach..."); super.onAttach(activity); } @Override public void onCreate(Bundle savedInstanceState) { Log.e(TAG, "onCreate..."); super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Log.e(TAG, "onCreateView..."); rootView = inflater.inflate(R.layout.jd_frg_main, null); llayout_main = (LinearLayout) rootView.findViewById(R.id.llayout_jd_frg_main); tv = (TextView) rootView.findViewById(R.id.tv_jd_frg_main); updateTitle(); //模擬數(shù)據(jù) for(int i=0; i<2; i++) { setData(); } return rootView; } protected void updateTitle() { if(getArguments() != null) { updateTitle(getArguments().getString("name")); } } protected void updateTitle(String title) { if(tv != null) { tv.setText(title); } } private void setData() { if(itemList == null) { itemList = new ArrayList<Category>(); for(int i=1; i<11; i++) { itemList.add(new Category("選項(xiàng) " + i, ""+i)); } } //高度60dp+行距8dp = 68dp int heightUnit = (int)TypedValue .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 68, getResources().getDisplayMetrics()); int height; //計(jì)算Gridview總高度 if(itemList.size() % 3 == 0) { height = (itemList.size()/3 + 2)*heightUnit; } else{ height = (itemList.size()/3 + 1)*heightUnit; } if(lp_gd == null) lp_gd = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, height); if(lp_tv == null) lp_tv = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT , (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP , 30, getResources().getDisplayMetrics())); TextView tv_title = new TextView(getActivity()); tv_title.setLayoutParams(lp_tv); tv_title.setText("組一"); llayout_main.addView(tv_title); GridView gridView = new GridView(getActivity()); gridView.setNumColumns(3); gridView.setVerticalSpacing(8); gridView.setLayoutParams(lp_gd); adapter = new GDAdapter(getActivity(), itemList,R.drawable.cate); gridView.setAdapter(adapter); llayout_main.addView(gridView); } @Override public void onActivityCreated(Bundle savedInstanceState) { Log.e(TAG, "onActivityCreated..."); super.onActivityCreated(savedInstanceState); } @Override public void onStart() { Log.e(TAG, "onStart..."); super.onStart(); } @Override public void onResume() { Log.e(TAG, "onResume..."); super.onResume(); } @Override public void onPause() { Log.e(TAG, "onPause..."); super.onPause(); } @Override public void onStop() { Log.e(TAG, "onStop..."); super.onStop(); } @Override public void onDestroyView() { Log.e(TAG, "onDestroyView..."); super.onDestroyView(); } @Override public void onDestroy() { Log.e(TAG, "onDestroy..."); super.onDestroy(); } @Override public void onDetach() { Log.e(TAG, "onDetach..."); super.onDetach(); } static class GDAdapter extends BaseAdapter { Context context; List<Category> results; int imageId; ViewHolder holder = null; public GDAdapter(Context context, List<Category> results,int imageId) { this.context = context; this.results = results; this.imageId = imageId; } @Override public int getCount() { // TODO Auto-generated method stub return results.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return results.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { Category c = (Category)getItem(position); if(convertView == null) { holder = new ViewHolder(); convertView = LayoutInflater.from(context).inflate(R.layout.jd_item, null); holder.tv = (TextView) convertView.findViewById(R.id.tv_jd_item); holder.imv = (ImageView) convertView.findViewById(R.id.imv_jd_item); } else { holder = (ViewHolder) convertView.getTag(); } convertView.setTag(holder); holder.tv.setText(c.getName()); holder.imv.setImageResource(imageId); return convertView; } class ViewHolder { TextView tv; ImageView imv; } } }
JDFragment的布局文件, jd_frg_main.xml:
<?xml version="1.0" encoding="utf-8" ?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FFFFFF" > <TextView android:id="@+id/tv_jd_frg_main" android:layout_width="match_parent" android:layout_height="25dp" android:text="Fragment" android:textSize="16sp" android:background="#EEEEEE" /> <ScrollView android:id="@+id/scrlayout_jd_frg_main" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/tv_jd_frg_main" android:overScrollMode="never" > <LinearLayout android:id="@+id/llayout_jd_frg_main" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" /> </ScrollView> </RelativeLayout>
將所有數(shù)據(jù)放在ScrollView的線性布局中,使用Fragment作為容器, 可以根據(jù)需要ADD, Remove和Update數(shù)據(jù)和View. 到這里右側(cè)頁(yè)面的簡(jiǎn)單模擬實(shí)現(xiàn)就結(jié)束了,都是一目了然的代碼.
然后就是實(shí)現(xiàn)左側(cè)列表了,先是列表中簡(jiǎn)單的自定義Adapter, MyAdapter:
public class MyAdapter extends BaseAdapter { private Context context; private List<Category> results; private int imageId; private ViewHolder holder = null; private int selectedId; public MyAdapter(Context context, List<Category> results,int imageId) { this.context = context; this.results = results; this.imageId = imageId; } @Override public int getCount() { // TODO Auto-generated method stub return results.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return results.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } public void setSelected(int position) { this.selectedId = position; } @Override public View getView(int position, View convertView, ViewGroup parent) { Category c = (Category)getItem(position); if(convertView == null) { holder = new ViewHolder(); convertView = LayoutInflater.from(context).inflate(R.layout.jd_item, null); holder.tv = (TextView) convertView.findViewById(R.id.tv_jd_item); holder.imv = (ImageView) convertView.findViewById(R.id.imv_jd_item); } else { holder = (ViewHolder) convertView.getTag(); } if(position == selectedId) { convertView.setBackgroundResource(R.drawable.sele_true); } else { convertView.setBackgroundResource(R.drawable.sele_false); } holder.tv.setText(c.getName()); holder.imv.setImageResource(imageId); convertView.setTag(holder); return convertView; } class ViewHolder { TextView tv; ImageView imv; } }
然后是主Activity了, 在里面對(duì)可見(jiàn)ListView的item位置進(jìn)行計(jì)算, 并進(jìn)行滑動(dòng)處理. 當(dāng)用戶點(diǎn)擊偏上的item, 列表就往下滑動(dòng), 加載頂部更多的item; 當(dāng)用戶點(diǎn)擊偏下的item, 列表就往上滑動(dòng), 加載底部更多的item.
同時(shí)我們自定義按下和松開(kāi)時(shí)的背景文件放在drawable, 隨便一個(gè)shape就可以了. 然后點(diǎn)擊某個(gè)item的position時(shí), 在adapter中判斷是否目標(biāo)item, 是就設(shè)置按下背景色 - 白色, 否則就是正常的背景色 - 灰色.
/** * 仿京東類別頁(yè) * @author AlexTam */ public class JDActivity extends FragmentActivity{ private ListView lv_main = null; private EditText et_search = null; private ArrayList<Category> itemList = new ArrayList<Category>(); private MyAdapter adapter = null; //可見(jiàn)列表項(xiàng)的數(shù)量 private int visibleCount = 0; //上次點(diǎn)擊的位置 private int lastPosition = 0; private int ce = 0; //實(shí)際列表是否超出屏幕 private boolean isOut = true; private JDFragment fragment = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.jd_main); init(); } private void init() { lv_main = (ListView) findViewById(R.id.lv_main); et_search = (EditText) findViewById(R.id.et_search); for(int i=1; i<21; i++) { itemList.add(new Category("選項(xiàng) " + i, ""+i)); } adapter = new MyAdapter(this, itemList,R.drawable.ic_launcher); lv_main.setAdapter(adapter); lv_main.setOnItemClickListener(new MyOnItemOnClick()); lv_main.setSelector(R.color.pink); //模擬右側(cè)標(biāo)簽頁(yè) fragment = new JDFragment(); Bundle bundle = new Bundle(); bundle.putString("name", "c1"); fragment.setArguments(bundle); FragmentManager fm = getSupportFragmentManager(); FragmentTransaction ft = fm.beginTransaction(); ft.replace(R.id.flayout_main, fragment, "c0").commit(); adapter.setSelected(0); adapter.notifyDataSetChanged(); } private class MyOnItemOnClick implements OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //計(jì)算滑動(dòng) if(visibleCount == 0) { visibleCount = lv_main.getChildCount(); if(visibleCount == itemList.size()) isOut = false; else { ce = visibleCount/2; } } if(position <= (parent.getFirstVisiblePosition() + ce)) { //上移 lv_main.smoothScrollToPosition(position - ce); } else { //下移 if((parent.getLastVisiblePosition() + ce + 1) <= parent.getCount()) { lv_main.smoothScrollToPosition(position + ce); } else { lv_main.smoothScrollToPosition(parent.getCount()-1); } } lastPosition = position; adapter.setSelected(position); adapter.notifyDataSetChanged(); //更新右側(cè)標(biāo)簽頁(yè)的標(biāo)題 fragment.updateTitle("c" + (position+1)); } } /** * 選項(xiàng)對(duì)象 */ static class Category { private String name; private String id; Category(String name,String id) { this.name = name; this.id = id; } public String getName() { return this.name; } } }
OK, 到此效果就出來(lái)了. 好簡(jiǎn)單吧!
以上是“Android如何實(shí)現(xiàn)仿京東手機(jī)端類別頁(yè)”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。