您的位置:首页 > 移动开发 > Android开发

手把手教你炫酷慕课网视频启动导航的完美实现

2016-09-27 13:22 316 查看
看了慕课网的视频启动导航真心感觉不错,然后呢试着去做了个一模一样的效果,个人感觉效果还是不错的。 
先来看效果:







整体感觉效果还是非常不错的吧。


实现思路

看上面那个GIF图,分析可知。首先是一个显示慕课网LOGO的Activity,然后跳转到了今天我们要讲的引导效果的Activity
根据它滑动的效果,可猜测是由ViewPager实现的。
ViewPager中有三个播放着动画或者视频的Fragment。
底部有标识滑动到哪一页的小圆点。
当滑动到第三页时,出现登录、注册按钮。


实现的技术分析:

打开慕课网App的引导页面,以为是用gif图片做的,后来发现每个引导页面都是加载的一段视频。 既然我们知道每个页面都是视频的话,那么就很好做了有木有,既然是几个引导页我就想到了轮播图那就使用viewPager来实现是比较轻松的,每个视频用Fragment这样的话复用率比较高,所以就选择用FragmentPagerAdapter,然后播放视频呢本来想用Vitamio然后呢发现videoView来实现比较简单,所以果断使用,然后还加上登录注册和首页,这里为了简单直观直接使用webView加载的效果是不是特别的炫,如果是第一次也会去慕课网那样的提示页,是不是感觉非常棒。


Android三种播放视频的方式

Android中,我们有三种方式来实现视频的播放:

1、使用其自带的播放器。指定Action为ACTION_VIEW,Data为Uri,Type为其MIME类型。

2、使用VideoView来播放。在布局文件中使用VideoView结合MediaController来实现对其控制。

3、使用MediaPlayer类和SurfaceView来实现,这种方式很灵活。


videoView的使用

Android支持播放网络上的视频。在播放网络上的视频时,牵涉到视频流的传输,往往有两种协议,

一种是HTTP,一种是RTSP。这 

两种协议最大的不同是,HTTP协议,不支持实时流媒体的播放,而RTSP协议就支持。 

Android中自带的播放器,以及VideoView等都支持上述两种协议,因此,可以直接播放网络上的视频,唯一不同的就是URI。


VideoView播放视频的步骤:


1、在界面布局文件中定义VideoView组件,或在程序中创建VideoView组件 

2、调用VideoView的如下两个方法来加载指定的视频 

setVidePath(String path):加载path文件代表的视频 

setVideoURI(Uri uri):加载uri所对应的视频 

3、调用VideoView的start()、stop()、psuse()方法来控制视频的播放

VideoView使用注意:


1.先把要播放的视频放到res/raw目录下,注明我这里要播放的是Android项目中的资源文件,而不是访问SD卡播放视频。 

2.视频格式必须是Android支持的格式(3gp,mp4,wmv),据说swf不支持,暂未试过。并且视频文件命名不能有大写字母,必须是小写字母、数字或下划线。 

3.布局文件中添加VideoView组件 

4.创建个String类型对象保存uri 

5.调用VideoView的setVideoURI方法设置URI,参数为上面的uri 

6.调用start()方法播放。


准备工作


1 .准备3个mp4格式的启动页视频 

2.准备2个图片(白点) 

3.准备几个webView需要加载的URL


代码解说

不多说看代码: 

先来布局:(导航页)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
tools:showIn="@layout/activity_main" tools:context=".MainActivity">
<android.support.v4.view.ViewPager
android:id="@+id/id_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<LinearLayout
android:id="@+id/button_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="50dp"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:visibility="gone">

<TextView
android:id="@+id/login"
android:layout_width="140dp"
android:layout_height="48dp"
android:background="@drawable/guide_login_btn_bg"
android:gravity="center"
android:text="登录/注册"
android:textColor="@color/black_000000"
android:textSize="18dp" />

<TextView
android:id="@+id/enter"
android:layout_width="140dp"
android:layout_height="48dp"
android:layout_marginLeft="20dp"
android:background="@drawable/guide_enter_btn_bg"
android:gravity="center"
android:text="立即体验"
android:textColor="@color/white_66FFFFFF"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/dot_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:layout_marginBottom="10dp"
android:orientation="horizontal" />
</RelativeLayout>
然后ViewPager里面使用的是Fragment里面使用的是VideoView来播放视频。所以自定义videoView便于视频的播放管理,看代码:
package com.richerpay.videoview.moocguide.view;

import android.annotation.TargetApi;
import android.content.Context;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.VideoView;
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class MCVideoView extends VideoView {
public MCVideoView(Context context) {
super(context,null);
}
public MCVideoView(Context context, AttributeSet attrs) {
super(context, attrs,0);
}
public MCVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr, 0);
}
public MCVideoView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
}
public void playVideo(Context context, Uri paramUri)
{
if (paramUri == null)
throw new IllegalArgumentException("Uri can not be null");
setVideoURI(paramUri);
start();
setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.setLooping(true);
}
});
setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
return true;
}
});
}
}

其实不封装也是差不多的,代码很简单我们来看下Fragment的布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.richerpay.videoview.moocguide.view.MCVideoView
android:id="@+id/videoview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<View
android:id="@+id/guide_bg"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>

接下来我们来看Fragment里面的代码,也是很简单:
package com.richerpay.videoview.moocguide.fragmnet;

import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.richerpay.videoview.moocguide.R;
import com.richerpay.videoview.moocguide.view.MCVideoView;
public class GuideFragment extends Fragment {

private View mBgView;
private Context mContext;
private MCVideoView mVideoView;

@Override
public void onAttach(Context context) {
super.onAttach(context);
this.mContext=context;
}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View localView = inflater.inflate(R.layout.guide_item_layout, null);
initView(localView);
return localView;
}

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initData();
}

private void initView(View localView) {
mVideoView = ((MCVideoView)localView.findViewById(R.id.videoview));
mBgView = localView.findViewById(R.id.guide_bg);
}

private void initData() {
Bundle localBundle = getArguments();
int i = 0;
int j = 0;
int k = 0;
if ((localBundle != null) && (localBundle.containsKey("index")))
i = localBundle.getInt("index");
try
{
String str = "guide_" + i;
j = R.raw.class.getDeclaredField(str).getInt(this);
int l = R.mipmap.class.getDeclaredField(str).getInt(this);
k = l;
if (j != 0)
this.mVideoView.playVideo(mContext, Uri.parse("android.resource://" + this.mContext.getPackageName() + "/" + j));
if (k != 0)
this.mBgView.setBackgroundResource(k);
return;
}
catch (Exception localException)
{
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (this.mVideoView == null)
return;
this.mVideoView.stopPlayback();
}
}

上面这段代码无非就是为了公用一个Fragment所以无非就是播放Raw文件下的不同视频而已。好了我们来看下导航的代码:
package com.richerpay.videoview.moocguide;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.richerpay.videoview.moocguide.fragmnet.GuideFragment;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

private ViewPager viewpager;
private FragmentPagerAdapter mAdapter;
private List<Fragment> mFragments;
private ImageView[] images;
private GuideFragment mTab01;
private GuideFragment mTab02;
private GuideFragment mTab03;
private TextView login, enter;
private LinearLayout button_layout, dot_layout;
private ObjectAnimator mAnim;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//   requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initView();

setSelect(0);
initDot(0);
}

private void initEvent() {
login.setOnClickListener(this);
enter.setOnClickListener(this);
}

private void initView() {
login = (TextView) findViewById(R.id.login);
enter = (TextView) findViewById(R.id.enter);
button_layout = (LinearLayout) findViewById(R.id.button_layout);
dot_layout = (LinearLayout) findViewById(R.id.dot_layout);
viewpager = (ViewPager) findViewById(R.id.id_viewpager);
mFragments = new ArrayList<Fragment>();
Bundle bundel = new Bundle();
mTab01 = new GuideFragment();
bundel.putInt("index", 1);
mTab01.setArguments(bundel);
mTab02 = new GuideFragment();
Bundle bunde2 = new Bundle();
bunde2.putInt("index", 2);
mTab02.setArguments(bunde2);
mTab03 = new GuideFragment();
Bundle bunde3 = new Bundle();
bunde3.putInt("index", 3);
mTab03.setArguments(bunde3);
mFragments.add(mTab01);
mFragments.add(mTab02);
mFragments.add(mTab03);

mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {

@Override
public int getCount() {
// TODO Auto-generated method stub
return mFragments.size();
}

@Override
public Fragment getItem(int arg0) {
// TODO Auto-generated method stub
return mFragments.get(arg0);
}
};

viewpager.setAdapter(mAdapter);

viewpager.setOnPageChangeListener(new android.support.v4.view.ViewPager.OnPageChangeListener() {

@Override
public void onPageSelected(int pos) {
int currentItem = viewpager.getCurrentItem();
setTab(currentItem);
initDot(pos);
images[pos].setEnabled(true);
}

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

}

@Override
public void onPageScrollStateChanged(int arg0) {

}
});
}
private void setSelect(int i) {
setTab(i);
viewpager.setCurrentItem(i);
}
private void setTab(int i) {
switch (i) {
case 0:
button_layout.setVisibility(View.GONE);
fadeInAnim(button_layout);
break;
case 1:
button_layout.setVisibility(View.GONE);
fadeInAnim(button_layout);
break;
case 2:
button_layout.setVisibility(View.VISIBLE);
initEvent();
break;
default:
break;
}
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.login) {
goLoginActivity();
}
if (v.getId() == R.id.enter) {
if (Constant.isFrist)
goIndexActivity();
else
goInitActivity();
}
}
private void goInitActivity() {
startActivity(new Intent(this, InitActivity.class));
finish();
}
private void goIndexActivity() {
startActivity(new Intent(this, IndexActivity.class));
finish();
}

private void goLoginActivity() {
startActivity(new Intent(this, LoginActivity.class));
finish();
}

private void fadeInAnim(View paramView) {
if (Build.VERSION.SDK_INT < 11)
return;
float[] arrayOfFloat = new float[2];
arrayOfFloat[0] = 0.0F;
arrayOfFloat[1] = 1.0F;
mAnim = ObjectAnimator.ofFloat(paramView, "alpha", arrayOfFloat).setDuration(1000L);
AnimatorSet localAnimatorSet = new AnimatorSet();
localAnimatorSet.play(mAnim);
localAnimatorSet.start();
}
/**
*初始化下面的点
*/
private void initDot(int select) {
//设置点的个数为fragment的数量
images = new ImageView[mFragments.size()];
//先移除所有的点
dot_layout.removeAllViews();
for (int i = 0; i < mFragments.size(); i++) {
ImageView localImageView = new ImageView(this);
LinearLayout.LayoutParams localLayoutParams = new LinearLayout.LayoutParams(-2, -2);
//左边距为30
localLayoutParams.leftMargin = 30;
localImageView.setLayoutParams(localLayoutParams);
localImageView.setImageResource(R.drawable.dot_bg);
if (i == select)  //如果选中则图片变为白点
localImageView.setEnabled(true);
else    //否者就为暗一点的白点
localImageView.setEnabled(false);
images[i] = localImageView;
dot_layout.addView(localImageView);
}
}
}


上面这代码无非就是把fragment适配到viewPager里面,并且根据选择到第几页来控制下面的白点,当到第三页时让登录注册按钮显示,和点击按钮执行相关的操作。

为了让效果更加好点,点击登录注册用的web
package com.richerpay.videoview.moocguide.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.view.KeyEvent;
import android.webkit.WebSettings;
import android.webkit.WebSettings.RenderPriority;
import android.webkit.WebSettings.ZoomDensity;
import android.webkit.WebView;
import android.webkit.WebViewClient;
/**
* 自定义WebView,长按图片获取图片url
*
*/
public class CustomWebView extends WebView{
private Context context;

public CustomWebView(Context context) {
super(context);
this.context = context;
initSettings();
}

private void initSettings() {
// 初始化设置
WebSettings mSettings = this.getSettings();
mSettings.setJavaScriptEnabled(true);//开启javascript
mSettings.setDomStorageEnabled(true);//开启DOM
mSettings.setDefaultTextEncodingName("utf-8");//设置字符编码
//设置web页面
mSettings.setAllowFileAccess(true);//设置支持文件流
mSettings.setSupportZoom(true);// 支持缩放
mSettings.setBuiltInZoomControls(true);// 支持缩放
mSettings.setUseWideViewPort(true);// 调整到适合webview大小
mSettings.setLoadWithOverviewMode(true);// 调整到适合webview大小
mSettings.setDefaultZoom(ZoomDensity.FAR);// 屏幕自适应网页,如果没有这个,在低分辨率的手机上显示可能会异常
mSettings.setRenderPriority(RenderPriority.HIGH);
//提高网页加载速度,暂时阻塞图片加载,然后网页加载好了,在进行加载图片
mSettings.setBlockNetworkImage(true);
mSettings.setAppCacheEnabled(true);//开启缓存机制

setWebViewClient(new MyWebViewClient());

}

private class MyWebViewClient extends WebViewClient {
/**
* 加载过程中 拦截加载的地址url
* @param view
* @param url  被拦截的url
* @return
*/
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return super.shouldOverrideUrlLoading(view, url);
}
/**
* 页面加载过程中,加载资源回调的方法
* @param view
* @param url
*/
@Override
public void onLoadResource(WebView view, String url) {
super.onLoadResource(view, url);
}
/**
* 页面加载完成回调的方法
* @param view
* @param url
*/
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
// 关闭图片加载阻塞
view.getSettings().setBlockNetworkImage(false);
}
/**
* 页面开始加载调用的方法
* @param view
* @param url
* @param favicon
*/
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
@Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
}
@Override
public void onScaleChanged(WebView view, float oldScale, float newScale) {
super.onScaleChanged(view, oldScale, newScale);
CustomWebView.this.requestFocus();
CustomWebView.this.requestFocusFromTouch();
}
}
@Override
// 设置回退
// 覆盖Activity类的onKeyDown(int keyCoder,KeyEvent event)方法
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && this.canGoBack()) {
this.goBack(); // goBack()表示返回WebView的上一页面
return true;
}
return super.onKeyDown(keyCode,event);
}
}


View加载,顺便对webView进行了简单的封装。

ok,案例到此结束,大家有疑问可以留言~~

越努力,越幸运!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息