Android之实现百度云主界面框架

来源:互联网 发布:python os模块的作用 编辑:程序博客网 时间:2024/05/14 04:09

源码奉上:http://download.csdn.net/detail/weidi1989/6595979

新版的Android版百度云界面效果非常炫,给人焕然一新的感觉,如下图所示。

  

其实仔细研究,会发现也并不是那么复杂:

1.整个界面主容器是一个ViewPager,只是在左下角有一个切换的Button。

2.ViewPager有两个界面,由Fragment实现,并且加入了ViewPager切换动画。

3.ViewPager的两个Fragment都是Tab风格,点击底部Tab又会呈现不同的子Fragment。

其实,就是Fragment用得比较灵活,效果优化得比较好。

下面是本人模仿过的效果:

  


基本的效果是差不多的,只是那个“传输列表”的Fragment没有再加3个子Fragment了,但是原理是一样的,我这里就步赘述了。


下面来看看代码分析:

1.整个例子只有一个Activity,即MainActivity,注释算是比较多的了,有兴趣的可以看看:

/** * 仿百度云主界面框架 *  * 注意继承自FragmentActivity,才会有getSupportFragmentManager()函数 *  * @author way *  */public class MainActivity extends FragmentActivity implementsOnPageChangeListener {private static final int NUM_PAGES = 2;// 总页数,2个Fragmentpublic static final int PAGE_PERSONAL = 0;// 第一个界面IDpublic static final int PAGE_FILE_SYSTEM = 1;// 第二个界面IDprivate static final int ROTATE_ANIM_DURATION = 300;// 左下角切换动画的时间private int mCurPage = 0;// 当前页private ViewPager mViewPager;// 父容器由一个ViewPager实现private PagerAdapter mPagerAdapter;// ViewPager适配器private ImageButton mSwitchImageButton;// 左下角切换Paper按钮private ImageView mAnimView;// 动画Viewprivate Animation mRotateRightAnim;// 向右旋转动画private Animation mRotateLeftAnim;// 向左旋转动画@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();initAnim();}/** * 初始化Views */private void initView() {mAnimView = (ImageView) findViewById(R.id.anim_icon);mSwitchImageButton = (ImageButton) findViewById(R.id.switch_btn);mViewPager = (ViewPager) findViewById(R.id.vp_pager);mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());mViewPager.setAdapter(mPagerAdapter);mCurPage = PAGE_FILE_SYSTEM;mViewPager.setCurrentItem(mCurPage);mViewPager.setOnPageChangeListener(this);mViewPager.setPageTransformer(true, new DepthPageTransformer());}/** * 初始化动画 */private void initAnim() {mRotateRightAnim = new RotateAnimation(0.0f, 180.0f,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f);mRotateRightAnim.setDuration(ROTATE_ANIM_DURATION);mRotateRightAnim.setFillAfter(true);mRotateLeftAnim = new RotateAnimation(180.0f, 0.0f,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f);mRotateLeftAnim.setDuration(ROTATE_ANIM_DURATION);mRotateLeftAnim.setFillAfter(true);mRotateRightAnim.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationRepeat(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {mAnimView.clearAnimation();mAnimView.setVisibility(View.GONE);mSwitchImageButton.setVisibility(View.VISIBLE);mSwitchImageButton.setImageResource(R.drawable.ic_viewpager_switch_feedlist);}});mRotateLeftAnim.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationRepeat(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {mAnimView.clearAnimation();mAnimView.setVisibility(View.GONE);mSwitchImageButton.setVisibility(View.VISIBLE);mSwitchImageButton.setImageResource(R.drawable.ic_viewpager_switch_filesystem);}});}/** * 点击左下角切换按钮的事件处理 *  * 需要事先在布局中声明 android:onClick="switchPage" *  * @param view */public void switchPage(View view) {if (mCurPage == PAGE_FILE_SYSTEM) {mViewPager.setCurrentItem(PAGE_PERSONAL);} else if (mCurPage == PAGE_PERSONAL) {mViewPager.setCurrentItem(PAGE_FILE_SYSTEM);}}/** * 开始动画 *  * @param pager *            当前页 */private void startAmin(int pager) {if (pager == PAGE_FILE_SYSTEM) {mSwitchImageButton.setVisibility(View.INVISIBLE);mAnimView.setVisibility(View.VISIBLE);mAnimView.startAnimation(mRotateLeftAnim);} else if (pager == PAGE_PERSONAL) {mSwitchImageButton.setVisibility(View.INVISIBLE);mAnimView.setVisibility(View.VISIBLE);mAnimView.startAnimation(mRotateRightAnim);}mCurPage = pager;}/** * ViewPager的适配器,我这里只是一个例子,就作为内部类了。 *  * @author way *  */private class ScreenSlidePagerAdapter extends FragmentPagerAdapter {public ScreenSlidePagerAdapter(FragmentManager fm) {super(fm);}/** * 这里可以将Fragment缓存一下,减少加载次数,提高用户体验,我未作处理 */@Overridepublic Fragment getItem(int position) {switch (position) {case PAGE_PERSONAL:return new MainPersonalFragment();case PAGE_FILE_SYSTEM:return new MainFileSystemFragment();default:return null;}}@Overridepublic int getCount() {return NUM_PAGES;}}@Overridepublic void onPageScrollStateChanged(int arg0) {}@Overridepublic void onPageScrolled(int arg0, float arg1, int arg2) {}@Overridepublic void onPageSelected(int arg0) {startAmin(arg0);//手势滑动ViewPager时,也要播放一下动画}}


接下来是ViewPager的子Fragment,由于两个Fragment的原理是差不多的,我这里就只贴出一个MainFileSystemFragment的代码了,这里的重点是点击对应Tab按钮切换Fragment,没有过多的使用缓存,待优化:

/** * 文件系统的Fragment *  * 由于与另一个Fragment是对称的,我就只注释此类了,敬请谅解! *  * @author way *  */public class MainFileSystemFragment extends Fragment implementsOnCheckedChangeListener {private FragmentManager mFragmentManager;// Fragment管理类private FragmentTransaction mFragmentTransaction;private String mCurrentFragmentTag;// 当前显示的二级Fragment标签// 底部三个Tab的按钮RadioButton mFileListRadioButton;RadioButton mToolsRadioButton;RadioButton mTransFileRadioButton;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 初始化FragmentManager,再次提醒需要Activity继承FragmentActivitymFragmentManager = getActivity().getSupportFragmentManager();}@Overridepublic void onResume() {super.onResume();// 默认显示Tab为第一个,其实可以记住一下状态onSaveInstanceState,我为简洁未作处理onCheckedChanged(mFileListRadioButton, true);mFileListRadioButton.setChecked(true);mCurrentFragmentTag = getActivity().getResources().getString(R.string.tab_filelist);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {return inflater.inflate(R.layout.main_filesystem, container, false);}@Overridepublic void onViewCreated(View view, Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);// find views和setActionmFileListRadioButton = (RadioButton) view.findViewById(R.id.rb_filelist);mToolsRadioButton = (RadioButton) view.findViewById(R.id.rb_tools);mTransFileRadioButton = (RadioButton) view.findViewById(R.id.rb_transferlist_right);mFileListRadioButton.setOnCheckedChangeListener(this);mToolsRadioButton.setOnCheckedChangeListener(this);mTransFileRadioButton.setOnCheckedChangeListener(this);}/** * 初始化FragmentTransaction *  * @return FragmentTransaction实例 */protected FragmentTransaction ensureTransaction() {if (mFragmentTransaction == null) {mFragmentTransaction = mFragmentManager.beginTransaction();mFragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);}return mFragmentTransaction;}/** * 根据tag获取对应的Fragment *  * @param tag *            标签 * @return 对应tag的Fragment实例 */private Fragment getFragment(String tag) {Fragment f = mFragmentManager.findFragmentByTag(tag);if (f == null) {// 在这里判断tag,不同则实例化对应的fragment,f = SampleFragment.newInstance(tag, MainActivity.PAGE_FILE_SYSTEM);}return f;}/** * 将对应的fragment添加到容器中 *  * @param layout *            父容器 * @param f *            fragment实例 * @param tag *            标签 */protected void attachFragment(int layout, Fragment f, String tag) {if (f != null) {if (f.isDetached()) {// 如果当前fragment只是隐藏,则显示出来ensureTransaction();mFragmentTransaction.attach(f);} else if (!f.isAdded()) {// 如果当前fragment没有添加到容器中,则先要添加到容器中ensureTransaction();mFragmentTransaction.add(layout, f, tag);}}}/** * 将对应fragment隐藏 *  * @param f *            需要隐藏的fragment */protected void detachFragment(Fragment f) {if (f != null && !f.isDetached()) {ensureTransaction();mFragmentTransaction.detach(f);}}/** * 保存fragment状态,添加或隐藏fragment最后都需要调用此函数 */protected void commitTransactions() {if (mFragmentTransaction != null && !mFragmentTransaction.isEmpty()) {mFragmentTransaction.commit();mFragmentTransaction = null;}}/** * 点击不同的Tab切换fragment *  * @param tag */private void switchFragmen(String tag) {if (TextUtils.equals(mCurrentFragmentTag, tag))return;if (mCurrentFragmentTag != null)detachFragment(getFragment(mCurrentFragmentTag));attachFragment(R.id.sliding_layer_frame_right, getFragment(tag), tag);mCurrentFragmentTag = tag;commitTransactions();}@Overridepublic void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {if (!isChecked)return;Log.i("way", "mCurrentFragmentTag = " + mCurrentFragmentTag);switch (buttonView.getId()) {case R.id.rb_filelist:switchFragmen(getActivity().getString(R.string.tab_filelist));break;case R.id.rb_tools:switchFragmen(getActivity().getString(R.string.tab_tools));break;case R.id.rb_transferlist_right:switchFragmen(getActivity().getString(R.string.tab_transferlist));break;default:break;}}}

MainFileSystemFragment对应的布局,main_filesystem.xml,使用RadioGroup和RadioButton实现Tab。

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:background="@color/black" >    <RadioGroup        android:id="@+id/rg_tabs"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:layout_toRightOf="@android:id/icon"        android:background="@drawable/tabbar_background"        android:gravity="bottom"        android:orientation="horizontal"        android:paddingBottom="0.0dip"        android:paddingLeft="50.0dip"        android:paddingRight="0.0dip"        android:paddingTop="4.0dip" >        <RadioButton            android:id="@+id/rb_filelist"            style="@style/NetDisk.Unified.Smaller.Blue2TabBarGray"            android:layout_width="fill_parent"            android:layout_height="fill_parent"            android:layout_weight="1.0"            android:background="@android:color/transparent"            android:button="@null"            android:drawableTop="@drawable/tab_filelist"            android:gravity="center"            android:paddingTop="4.0dip"            android:text="@string/tab_filelist" />        <RadioButton            android:id="@+id/rb_tools"            style="@style/NetDisk.Unified.Smaller.Blue2TabBarGray"            android:layout_width="fill_parent"            android:layout_height="fill_parent"            android:layout_weight="1.0"            android:background="@android:color/transparent"            android:button="@null"            android:drawableTop="@drawable/tab_tools"            android:gravity="center"            android:paddingTop="4.0dip"            android:text="@string/tab_tools" />        <RadioButton            android:id="@+id/rb_transferlist_right"            style="@style/NetDisk.Unified.Smaller.Blue2TabBarGray"            android:layout_width="fill_parent"            android:layout_height="fill_parent"            android:layout_weight="1.0"            android:background="@android:color/transparent"            android:button="@null"            android:drawableTop="@drawable/tab_transferlist"            android:gravity="center"            android:paddingTop="4.0dip"            android:text="@string/tab_transferlist" />    </RadioGroup>    <FrameLayout        android:id="@+id/sliding_layer_frame_right"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_above="@id/rg_tabs"        android:background="@color/black" />    <ImageView        android:id="@+id/iv_guide"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:layout_marginBottom="169.0dip"        android:src="@drawable/ic_swipe_guide_right"        android:visibility="gone" /></RelativeLayout>

最后是每个Tab的Fragment了,由于我这里仅仅是一个例子,所以6个Tab对应的Fragment都是使用的此Fragment,只是在切换不同的Tab时,改变了标题栏名称和背景颜色而已:

/** * 每个Tab中的fragment *  * @author way *  */public class SampleFragment extends Fragment {private static final String ARG_TEXT = "text";private static final String ARG_PAGER = "pager";public static SampleFragment newInstance(String text, int pager) {SampleFragment f = new SampleFragment();Bundle args = new Bundle();args.putString(ARG_TEXT, text);args.putInt(ARG_PAGER, pager);f.setArguments(args);return f;}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {View v = inflater.inflate(R.layout.fragment_sample, container, false);((TextView) v.findViewById(R.id.text)).setText(getArguments().getString(ARG_TEXT));TextView title = (TextView) v.findViewById(R.id.title);title.setText(getArguments().getString(ARG_TEXT));int pager = getArguments().getInt(ARG_PAGER);if (pager == MainActivity.PAGE_FILE_SYSTEM)// 如果是文件系统的Fragmenttitle.setBackgroundColor(Color.parseColor("#ff3995e3"));// 蓝色标题栏elsetitle.setBackgroundColor(Color.parseColor("#ffde4125"));return v;}}

OK,谢谢你看到了文章末尾,由于在公司无法上传代码,回家后将源码奉上,请稍安勿燥!

急着下班,文章讲解不够,如果各位有啥问题,欢迎留言。Thanks!