现在很多APP的首页都类似于淘宝的首页,普遍是上面一个标题,下面三至六个点击的按钮,中间再放上一个FragmentManager,当然也有可能中间放一个ViewPager的,因为最近在学习这个,所以我就来介绍一下,怎样开发出类似淘宝的简单的一个框架结构。
1、首先,当然是创建一个新工程,这里就不赘述了。我们的MainActivity对应的xml文件的布局,也就是activity_main由两个部分组成,在一个垂直方向排列的线性布局中放入一个FrameLayout和一个水平排列的LinearLayout,其中LinearLayout中放入几个Button,具体根据需要来定,我这里依照淘宝放入五个Button。
代码如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <FrameLayout android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" /> <LinearLayout android:id="@+id/ll_main_tab" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:background="@android:color/transparent" android:layout_alignParentBottom="true"> <Button android:id="@+id/btn_home" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:background="@android:color/transparent" android:drawableTop="@drawable/home" android:text="首页" android:textSize="@dimen/text_home_bottom" android:textColor="@color/color_home_bottom_text" /> <Button android:id="@+id/btn_small_tao" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:background="@android:color/transparent" android:drawableTop="@drawable/home" android:text="微淘" android:textColor="@color/color_home_bottom_text"/> <Button android:id="@+id/btn_find" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:background="@android:color/transparent" android:drawableTop="@drawable/home" android:text="发现" android:textColor="@color/color_home_bottom_text"/> <Button android:id="@+id/btn_shoppingcart" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:background="@android:color/transparent" android:drawableTop="@drawable/home" android:text="购物车" android:textColor="@color/color_home_bottom_text"/> <Button android:id="@+id/btn_my_taobao" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:background="@android:color/transparent" android:drawableTop="@drawable/home" android:text="我的淘宝" android:textColor="@color/color_home_bottom_text"/> </LinearLayout> </LinearLayout>
2、写完首页布局文件之后,我们就要来写MainActivity了。因为我们MainActivity里面放置了五个Fragment,因此我这里让他继承FragmentActivity而不是Activity,因为我要用FragmentActivity的一些特定的方法。又因为有多个Fragment需要进行管理,所以先要获得FragmentManager的实例,FragmentManager是一个可以对fragment进行管理的类:
private FragmentManager mFragmentManager;
mFragmentManager = getSupportFragmentManager();
通常默认一进入MainActivity就显示首页,也就是HomeFragment,那么其他的Fragment就要隐藏,而在隐藏的同时,我们需要获得当前的Fragment以及创建Fragment。
/** * 隐藏其它Fragment * * @param index */ private void hideOtherFragment(int index) { Fragment fragment = getFragment(index); FragmentTransaction ft = mFragmentManager.beginTransaction(); try { if (fragment == null) { fragment = creatFragment(index); ft.add(R.id.fragment_container, fragment); } else { ft.show(fragment); } ft.commit(); } catch (Exception e) { Log.e(TAG, index + "隐藏其它Fragment"); } }
/** * 获得fragment * @param index * @return 相应的fragment */ private Fragment getFragment(int index) { switch (index) { default: case 0: return mHomeFragment; case 1: return mSmallTaoFragment; case 2: return mShoppingcartFragment; case 3: return mFindFragment; case 4: return mMineFragment; } } private Fragment creatFragment(int index) { switch (index) { default: case 0: mHomeFragment = new HomeFragment(); return mHomeFragment; case 1: mSmallTaoFragment = new SmallTaoFragment(); return mSmallTaoFragment; case 2: mShoppingcartFragment = new ShoppingcartFragment(); return mShoppingcartFragment; case 3: mFindFragment = new FindFragment(); return mFindFragment; case 4: mMineFragment = new MyTaobaoFragment(); return mMineFragment; } }
从上面的代码,可以获知这三个方法的用处所在,要说明一下的是FragmentTransaction是一个可以对fragment进行添加、替换、移除、显示、隐藏以及执行其他动作的一个雷,具体可以看源码,源码的讲解很清晰。3、做完这些之后,我们就可以通过findViewById获得我们的控件,也就是Button,同时为他们设置监听,这个很简单,我就不细说了。点击按钮之后,我们的界面就要进行切换。因为切换的方法其实是一样的,所以把v.getId作为参数,写了如下的方法:
/** * 底部按钮点击时调用 * @param checkedId */ public void onItemClick(int checkedId) { for (int i = 0; i < mTab.getChildCount(); i++) { if (mTab.getChildAt(i).getId() == checkedId) { if (mCurrentTab == i) { break; } else { changeToIndexTab(i); } break; } } }
如上面的方法所示,fromfragment是要跳出的那个fragment,tofragment是要跳进去的那个fragment,mHasAnima是一个Boolean类型的变量,为了保证Fragment切换的流畅性,以及因为FragmentTransaction每执行一个动作就要执行commit()方法,所以设置mHasAnim来进行判断,从而执行一些方法。 R.anim.xxx就是一些动画效果,之前的博客有介绍,这里就不多说了。底部和中间区域的面积解决之后,就是标题的实现了。标题不在MainActivity里面设置,而是在Fragment里面。这里以HomeFragment为例,首先我写了个简单的标题布局,也就是一个相对布局的中间区域放上一个TextView就OK了,这里就不贴代码了,对了,命名为“title”。/** * * @param index */ private void changeCheck(int index) { if (index != mCurrentTab) { mToTabl = index; Fragment tofragment = getFragment(index); Fragment fromfragment = getFragment(mCurrentTab); FragmentTransaction ft = obtainFragmentTransaction(index); if (fromfragment != null) { ft.hide(fromfragment); } if (tofragment != null) { ft.show(tofragment); } else { tofragment = creatFragment(index); ft.add(R.id.fragment_container, tofragment); } try { if (mHasAnima) { ft.commit(); } else { ft.commitAllowingStateLoss(); } } catch (Exception e) { Log.e(TAG, index + "," + e.getMessage()); } mHasAnima = false; mCurrentTab = index; } }
/** * 切换 * * @param index * @return */ private FragmentTransaction obtainFragmentTransaction(int index) { FragmentTransaction ft = mFragmentManager.beginTransaction(); if (mHasAnima) { if (index > mCurrentTab) { ft.setCustomAnimations(R.anim.push_left_in, R.anim.push_left_out); } else { ft.setCustomAnimations(R.anim.push_right_in, R.anim.push_right_out); } } return ft; }
接着把title放进HomeFragment的对应布局home_layout中,示例如下:
<include layout="@layout/title" />最后,把下面这段代码加入HomeFragment中:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { view = inflater.inflate(R.layout.home_layout, container, false); setTitle(view); return view; } private void setTitle(View view) { TextView tvHomeTitle = (TextView) view.findViewById(R.id.tv_title); tvHomeTitle.setText(getResources().getText(R.string.home)); }
在这里,MainActivity就算告一段落了,首页的框架也基本实现了。后续我还会继续这个类淘宝实现的开发。