首页 > 嗟来之食 > 手把手教你实现慕课网导航效果(二)——编码实现
2016
05-18

手把手教你实现慕课网导航效果(二)——编码实现

手把手教你实现慕课网导航效果(二)——编码实现
前言
经过上一篇对慕课网导航效果的分析和验证,今天我们就来编码实现这一效果。还没有看过上一篇文章的同学,建议先看看手把手教你实现慕课网引导页效果(一)——分析验证。
通过本篇文章,我们可以学习到:

1.ViewPager+Fragment+FragmentPagerAdapter实现滑动导航页面
2.VideoView(播放视频)的基本使用
3.Activity转间动画

在编码之前,先回顾下慕课网的导航效果。

正文
1.首先,我们先实现显示Logo的Activity(简称MainActivity),这个比较简单。看上面的GIF图,MainActivity显示一会时间后向左滑动消失,GuideActivity从右边滑动出来。那就讲讲其中的Activity转间动画(Transition animation)。
一般使用下面的方式来实现:
public void overridePendingTransition (int enterAnim, int exitAnim)
//通常我们一般在startActivity(Intent)或finish()方法中调用此方法
//其中enterAnim表示新Activity的进入动画,exitAnim表示旧Activity的退出动画

//从Android4.1后,可以通过ActivityOptions将转间动画作为Bundle传入startActivity(Activity,Bundle)来实现

来看代码实现:
public class MainActivity extends AppCompatActivity {

private Handler mHandler = new Handler();
private Context mContext;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
//使用handler定时跳转到GuideActivity
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
Intent intent = new Intent(mContext,GuideActivity.class);
//设置跳转动画
//第一种方式实现
startActivity(new Intent(mContext,GuideActivity.class));
finish();
overridePendingTransition(R.anim.slide_in_right,R.anim.slide_out_left);

//第二种方式实现
// ActivityOptionsCompat optionsCompat =
// ActivityOptionsCompat.makeCustomAnimation(mContext,R.anim.slide_in_right,
// R.anim.slide_out_left);
// ActivityCompat.startActivity(MainActivity.this,intent,optionsCompat.toBundle());
// startActivity(new Intent(mContext,GuideActivity.class));
// finish();
}
}, 500);

}
}

运行效果:

2.接下来,实现滑动导航效果。相信现在讲这个的文章非常多,今天就当再复习一遍。呵呵,温故而知新。
我们使用ViewPager+Fragment+FragmentPagerAdapter来实现。
一般有三个步骤:

1.实现Fragment的子类
2.实现FragmentPagerAdapter适配器类
3.将第2步生成的Adapter设置为ViewPager的适配器,并使用addOnPageChangeListener方法对ViewPager的Page更改的事件进行监听来实现标识第几页的功能。

在这里,我们只需要创建一种Fragment即可。通过index参数来设置显示不同的图片和播放不同的视频。
下面是GuideFragment的代码:
/**
* Created by JohnTsai on 16/3/3.
*/
public class GuideFragment extends Fragment {
public static String TAG = GuideFragment.class.getSimpleName();
public static String KEY = "index";

private VideoView mVideoView;
private ImageView mImageView;

private int index;

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View guideView = inflater.inflate(R.layout.fragment_guide,container,false);

mVideoView = (VideoView) guideView.findViewById(R.id.videoView);
mImageView = (ImageView) guideView.findViewById(R.id.wordView);

switch (index){
case 0:
mImageView.setImageResource(R.mipmap.guide_1);
break;
case 1:
mImageView.setImageResource(R.mipmap.guide_2);
break;
case 2:
mImageView.setImageResource(R.mipmap.guide_3);
break;
}
Log.d(TAG,"onCreateView");
return guideView;
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

Bundle bundle = getArguments();
index = bundle.getInt(KEY);

Log.d(TAG,"onCreate");
}

public static GuideFragment newInstance(int index) {

Bundle args = new Bundle();
args.putInt(KEY, index);

GuideFragment fragment = new GuideFragment();
fragment.setArguments(args);
return fragment;
}
}

以及GuideActivity的代码
/**
* Created by JohnTsai on 16/3/3.
*/
public class GuideActivity extends AppCompatActivity{

private ImageView mDotOne,mDotTwo,mDotThree;
private LinearLayout mLayoutBtn;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_guide);

//初始化控件
ViewPager mViewPager = (ViewPager) findViewById(R.id.viewPager);
mDotOne = (ImageView) findViewById(R.id.guide_dot1);
mDotTwo = (ImageView) findViewById(R.id.guide_dot2);
mDotThree = (ImageView) findViewById(R.id.guide_dot3);
mLayoutBtn = (LinearLayout) findViewById(R.id.btn_layout);

GuideFragment guideFragment1 = GuideFragment.newInstance(0);
GuideFragment guideFragment2 = GuideFragment.newInstance(1);
GuideFragment guideFragment3 = GuideFragment.newInstance(2);

List<? extends Fragment> mFragmentList = Arrays.asList(guideFragment1, guideFragment2, guideFragment3);
GuideFragmentPagerAdapter mAdapter = new GuideFragmentPagerAdapter(getSupportFragmentManager(), mFragmentList);
mViewPager.setAdapter(mAdapter);

//设置小圆点
mDotOne.setImageResource(R.mipmap.guide_dot_checked);
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

}

@Override
public void onPageSelected(int position) {
mDotOne.setImageResource(R.mipmap.guide_dot_normal);
mDotTwo.setImageResource(R.mipmap.guide_dot_normal);
mDotThree.setImageResource(R.mipmap.guide_dot_normal);
switch (position) {
case 0:
mDotOne.setImageResource(R.mipmap.guide_dot_checked);
break;
case 1:
mDotTwo.setImageResource(R.mipmap.guide_dot_checked);
break;
case 2:
mDotThree.setImageResource(R.mipmap.guide_dot_checked);
break;
}
//设置当滑动到最后一页时,显示两个按钮
mLayoutBtn.setVisibility(position==2? View.VISIBLE:View.GONE);
}

@Override
public void onPageScrollStateChanged(int state) {

}
});
}

public static class GuideFragmentPagerAdapter extends FragmentPagerAdapter{

private List <? extends Fragment> fragments;

public GuideFragmentPagerAdapter(FragmentManager fm,List<? extends Fragment> fragments) {
super(fm);
this.fragments = fragments;
}

@Override
public Fragment getItem(int position) {
return fragments.get(position);
}

@Override
public int getCount() {
return fragments.size();
}
}
}

最后我们学习VideoView的基本使用。

参考资料:
VideoView官网文档
Android–使用VideoView播放视频

VideoView继承自SurfaceView,并实现了MediaPlayerControl接口。用于播放视频文件。
几个主要的方法:

void setVideoPath(String path):以文件路径的方式设置VideoView播放的视频源。
void setVideoURI(Uri uri):以Uri的方式设置VideoView播放的视频源,可以是网络Uri或本地Uri。
void start():开始播放。
void stopPlayback():停止播放。
setMediaController(MediaController controller):设置MediaController控制器。
setOnCompletionListener(MediaPlayer.onCompletionListener l):监听播放完成的事件。
setOnErrorListener(MediaPlayer.OnErrorListener l):监听播放发生错误时候的事件。
setOnPreparedListener(MediaPlayer.OnPreparedListener l)::监听视频装载完成的事件。

下面继续我们的慕课网视频引导效果的编码:
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View guideView = inflater.inflate(R.layout.fragment_guide, container, false);

mVideoView = (VideoView) guideView.findViewById(R.id.videoView);

//获取放置在raw文件夹得视频的Uri
Uri uri1 =Uri.parse("android.resource://" + getActivity().getPackageName() + "/" + R.raw.guide_1);
Uri uri2 =Uri.parse("android.resource://" + getActivity().getPackageName() + "/" + R.raw.guide_2);
Uri uri3 =Uri.parse("android.resource://" + getActivity().getPackageName() + "/" + R.raw.guide_3);

Log.d(TAG,"1:"+uri1
+"\n2:"+uri2
+"\n3:"+uri3);

mImageView = (ImageView) guideView.findViewById(R.id.wordView);

switch (index){
case 0:
mImageView.setImageResource(R.mipmap.guide_1);
mVideoView.setVideoURI(uri1);
break;
case 1:
mImageView.setImageResource(R.mipmap.guide_2);
mVideoView.setVideoURI(uri2);
break;
case 2:
mImageView.setImageResource(R.mipmap.guide_3);
mVideoView.setVideoURI(uri3);
break;
}
mVideoView.start();
//对VideoView的完成播放事件进行监听,完成后再次播放以达到循环播放的效果
mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mVideoView.start();
}
});
Log.d(TAG,"onCreateView");
return guideView;
}

运行效果:

看运行效果,发现一个问题,视频的比例和手机的比例不一致导致右边出现蓝色长条。
这里我们继承VideoView来自定义设置它的宽和高来解决这个问题:
代码如下:
/**
* Created by JohnTsai on 16/3/3.
*/
public class CustomWidthHeightVideoView extends VideoView{
private int mWidth = 0;
private int mHeight = 0;

public CustomWidthHeightVideoView(Context context) {
super(context);
}

public CustomWidthHeightVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
}

public CustomWidthHeightVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

public void setWidthHeight(int width,int height){
mWidth = width;
mHeight = height;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if(mWidth>0&&mHeight>0)
setMeasuredDimension(mWidth,mHeight);
else
super.onMeasure(widthMeasureSpec,heightMeasureSpec);
}
}

在onMeasure方法中,将我们设置的宽和高通过setMeasuredDimension来自定义VideoView的宽和高。
//设置全屏播放
DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
mVideoView.setWidthHeight(metrics.widthPixels,metrics.heightPixels);

运行效果:

好,慕课网引导效果的编码实现就到这。如果喜欢,请推荐一下。谢谢。
本文是由JohnTsai原创。著作权由本人保留。
如需转载,请在显著位置注明出处。
欢迎交流讨论。
联系邮箱JohnTsai.work@gmail.com

最后编辑:
作者:
这个作者貌似有点懒,什么都没有留下。

留下一个回复