AI智能
改变未来

android视频启动页效果(splash)


1.基础原理:

编码解码: 视频压缩成文件还原成帧图像 h.264
封装格式:mp4,avi等
硬解与软解:cpu,gpu
关键帧:视频压缩中比较重要的图像帧数据

1.程序主入口

AndroidMenifest.xml

intent-filter意图过滤器

<activity android:name=\".MainActivity\" android:theme=\"@style/FullScreen\"><intent-filter><action android:name=\"android.intent.action.MAIN\" /><category android:name=\"android.intent.category.LAUNCHER\" /></intent-filter></activity>

theme只对当前activity有作用
theme在application的话,对所有activity均有作用
以最小为准

2.Activity生命周期

3.视图相关

1.xml

ConstraintLayout 继承自ViewGroup
ViewGroup继承自View

public abstract class ViewGroup extends View implements ViewParent, ViewManager

View和ViewGroup是组合设计模式,23种设计模式之一。
match_parent:子view大小等于父view的大小

2.VideoView

VideoView :
对MediaPlayer的一层封装,只支持3gp和mp4格式的播放。
继承自SufarceView

videoview的全屏问题:
videoview会根据视频文件的大小来改变自身的大小,所以要自定义view。

##6. Bundle
与Map类型数据相似,以key-value的形式存储数据
界面被销毁后,是否能还原之前的状态

3.setContentView方法

把自定义layout加入id为content的ViewGroup中

4.activity中设置播放的视频路径

mVideoView.setVideoURI(Uri.parse(\"android.resource://\"+getPackageName()+ File.separator+R.raw.splash));

播放器的状态:闲置,准备,播放

mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {@Overridepublic void onPrepared(MediaPlayer mp) {mp.start();}});
mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {@Overridepublic void onCompletion(MediaPlayer mp) {mp.start();}});

观察者设计模式:
观察者是界面,被观察者是播放器。

5.自定义theme

全屏

<item name=\"android:windowFullscreen\">true</item>

无标题栏

<style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.NoActionBar\">

6.自定义View的几种方式

1.继承自View类。

核心步骤为尺寸测量与绘制,对应函数为onMeasure、onDraw。
VideoView中只有onMeasure方法,没有onDraw方法

2、继承现有控件实现特定效果
3、继承ViewGroup实现布局类
主要用于自定义子视图的排列方式时,比如下拉刷新、上拉加载等。ViewGroup为什么具有容器的作用?因为实现了两个接口 ViewParent和ViewManager,其中后者定义了addView及removeView等对子视图操作的方法,

重点实现onLayout方法,主要是用于子视图的排版。
public class FullScreenVideoView extends VideoView {public FullScreenVideoView(Context context) {super(context);}用于在Activity中直接new出来的对象public FullScreenVideoView(Context context, AttributeSet attrs) {super(context, attrs);}用于xml文件中定义的布局的new。支持自定义属性。public FullScreenVideoView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}也是用于xml文件中,也支持自定义属性,同时支持style样式
为了全屏重写测量方法系统的onMeasure方法会根据兼容性更改大小@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int width = getDefaultSize(0,widthMeasureSpec);int height = getDefaultSize(0,heightMeasureSpec);setMeasuredDimension(width,height);// super.onMeasure(widthMeasureSpec, heightMeasureSpec);}

7.测量模式

EXACTLY模式
该模式为精确模式。什么时候用到的是这种模式呢?当我们将layout_width or layout_height 设置为具体数值的时候,如100dp 或者是match_parent 的时候。这时系统就是调用的精确模式

AT_MOST
该模式为最大值模式。当我们将layout_width or layout_height设置为wrap_content 的时候,系统调用的就是该模式。此时控件大小是随着子控件或者内容的变化而变化的,只要不超出父控件允许的最大范围即可

UNSPECIFIED
这个模式一般只有在我们自定义控件的时候才会用到,它代表没有具体的测量模式,view自己想多大就多大。

8.xml中的部分属性

<color name=\"colorPrimary\">#6200EE</color>

颜色色值:
#ffffffff由#加八位数字或字母组成,前两个ff为透明度(十六进制),后面六位ffffff为颜色代码,采用RGB配色(十六进制),
透明度参照表;
00%=FF(不透明) 5%=F2 10%=E5 15%=D8 20%=CC 25%=BF 30%=B2 35%=A5 40%=99 45%=8c 50%=7F
55%=72 60%=66 65%=59 70%=4c 75%=3F 80%=33 85%=21 90%=19 95%=0c 100%=00(全透明)

dp px sp 之间的概念:
px:像素单位,dp:安卓距离单位,sp:安卓字体大小单位

当屏幕为mdpi时,1dp = 1px,换算单位为 dp = (dpi/160)px。
1dp永远都等于1sp。

dp不随手机字体大小变化而变化
sp跟随系统

控件位置
相对父控件
android:layout_marginTop=“50dp”

9.自定义shape

弧度

<corners android:radius=\"20dp\"/>

背景

<solid android:color=\"@color/colorBlack\"/>

边框

<stroke android:width=\"1dp\" android:color=\"@color/colorffffff\"/>

4.倒计时类的实现

1.需要实现哪些功能?

1、实时回调,倒计时至几秒
2、支持动态传入倒计时的总时间
3、每过一秒总秒数减一
4、总时间倒计时为0时要回调完成的状态

2.用到观察者设计模式。

//具体实现@Overridepublic void run() {if (isRun){if(CountDownHandler!=null){CountDownHandler.onTicker(countdowntime);}if(countdowntime == 0) {cancel();if (CountDownHandler != null) {CountDownHandler.onFinish();}}else{countdowntime = time--;handler.postDelayed(this,1000);}}}
//开始倒计时public void start(){isRun = true;handler.post(this);}
//跳出循环,终止public void cancel(){isRun = false;handler.removeCallbacks(this);}
//观察者回调借口  (IOC 数据回调)public interface IcountDownHandler{//倒计时回调void onTicker(int time);//完成时回调void onFinish();}}

3.用Handler的消息机制做数据的减法操作

5. Handler

1.原理图

2.MessageQueen和 Looper

Looper

Handler 源码中,

mLooper = Looper.myLooper();

在进入到Looper的源码中

/*** Return the Looper object associated with the current thread.  Returns* null if the calling thread is not associated with a Looper.*/public static @Nullable Looper myLooper() {return sThreadLocal.get();}
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

ThreadLocal相当线程同步的池子,取出放回

MessageQueue

在looper的构造方法中,创建了MessageQueue

final MessageQueue queue = me.mQueue;
private Looper(boolean quitAllowed) {mQueue = new MessageQueue(quitAllowed);mThread = Thread.currentThread();}

3.ActivityThread源码中的Handler

main方法中

Looper.prepareMainLooper();
Looper.loop();

Looper.loop()

final MessageQueue queue = me.mQueue;
for (;;) {Message msg = queue.next(); // might blockif (msg == null) {// No message indicates that the message queue is quitting.return;}

在此处遍历的是Message类型的数据

而postDelayed的是Runnable类型的数据
进入到postDelayed的源码

public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {return sendMessageDelayed(getPostMessage(r), delayMillis);}

将Runnable封装成Message

查看getPostMessage,放进callback成员变量里面

private static Message getPostMessage(Runnable r) {Message m = Message.obtain();m.callback = r;return m;}

app启动时创建looper不断去循环MessageQueen

H类

class H extends Handler

处理handler消息

public void handleMessage(Message msg) {

Activity生命周期是通过ActivityThread类,发送一些消息,处理不同的消息类型,调用Activity的生命周期。

6 Activity的跳转

在AndroidManifest中,隐式启动

<intent-filter><action android:name=\"android.intent.action.MAIN\" /><category android:name=\"android.intent.category.LAUNCHER\" /></intent-filter>

将Action放进intent里面,
匹配字符串\”android.intent.action.MAIN\”

在项目当中,可以用显式启动

startActivity(new Intent(SplashActivity.this,MainActivity.class));


SplashActivity 继承自AppCompatActivity
AppCompatActivity的继承可以深入到contex类

5 项目存在一些问题。

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » android视频启动页效果(splash)