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

源码奉上: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 implements
		OnPageChangeListener {
	private static final int NUM_PAGES = 2;// 总页数,2个Fragment
	public static final int PAGE_PERSONAL = 0;// 第一个界面ID
	public static final int PAGE_FILE_SYSTEM = 1;// 第二个界面ID
	private 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;// 动画View
	private Animation mRotateRightAnim;// 向右旋转动画
	private Animation mRotateLeftAnim;// 向左旋转动画

	@Override
	protected 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() {

			@Override
			public void onAnimationStart(Animation animation) {
			}

			@Override
			public void onAnimationRepeat(Animation animation) {
			}

			@Override
			public 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() {

			@Override
			public void onAnimationStart(Animation animation) {
			}

			@Override
			public void onAnimationRepeat(Animation animation) {
			}

			@Override
			public 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缓存一下,减少加载次数,提高用户体验,我未作处理
		 */
		@Override
		public Fragment getItem(int position) {
			switch (position) {
			case PAGE_PERSONAL:
				return new MainPersonalFragment();
			case PAGE_FILE_SYSTEM:
				return new MainFileSystemFragment();
			default:
				return null;
			}
		}

		@Override
		public int getCount() {
			return NUM_PAGES;
		}

	}

	@Override
	public void onPageScrollStateChanged(int arg0) {
	}

	@Override
	public void onPageScrolled(int arg0, float arg1, int arg2) {
	}

	@Override
	public void onPageSelected(int arg0) {
		startAmin(arg0);//手势滑动ViewPager时,也要播放一下动画
	}
}


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

/**
 * 文件系统的Fragment
 * 
 * 由于与另一个Fragment是对称的,我就只注释此类了,敬请谅解!
 * 
 * @author way
 * 
 */
public class MainFileSystemFragment extends Fragment implements
		OnCheckedChangeListener {
	private FragmentManager mFragmentManager;// Fragment管理类
	private FragmentTransaction mFragmentTransaction;
	private String mCurrentFragmentTag;// 当前显示的二级Fragment标签
	// 底部三个Tab的按钮
	RadioButton mFileListRadioButton;
	RadioButton mToolsRadioButton;
	RadioButton mTransFileRadioButton;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// 初始化FragmentManager,再次提醒需要Activity继承FragmentActivity
		mFragmentManager = getActivity().getSupportFragmentManager();
	}

	@Override
	public void onResume() {
		super.onResume();
		// 默认显示Tab为第一个,其实可以记住一下状态onSaveInstanceState,我为简洁未作处理
		onCheckedChanged(mFileListRadioButton, true);
		mFileListRadioButton.setChecked(true);
		mCurrentFragmentTag = getActivity().getResources().getString(
				R.string.tab_filelist);
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		return inflater.inflate(R.layout.main_filesystem, container, false);
	}

	@Override
	public void onViewCreated(View view, Bundle savedInstanceState) {
		super.onViewCreated(view, savedInstanceState);
		// find views和setAction
		mFileListRadioButton = (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();
	}

	@Override
	public 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;
	}

	@Override
	public 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)// 如果是文件系统的Fragment
			title.setBackgroundColor(Color.parseColor("#ff3995e3"));// 蓝色标题栏
		else
			title.setBackgroundColor(Color.parseColor("#ffde4125"));
		return v;
	}
}

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

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




  • 13
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 21
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值