You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android KitKat下Activity间视频纹理淡入淡出过渡异常解决方案咨询

解决KitKat系统中TextureView视频淡入淡出过渡出现白色空白的问题

你遇到的这个问题确实是Android 4.4(KitKat)系统的一个已知bug:当使用overridePendingTransition进行Activity跳转时,旧Activity退出后会短暂显示窗口背景(默认白色),而新Activity的TextureView需要等待MediaPlayer加载并准备好视频才能显示内容,这就导致了过渡期间的白色空白。

下面是针对KitKat系统的几种可行解决方案,按推荐程度排序:

方案一:在同一个Activity中管理多个TextureView(最推荐)

放弃Activity跳转,将两个视频的TextureView放在同一个布局中叠层显示,通过直接控制它们的Alpha动画实现淡入淡出,完全避免窗口切换的间隙。

步骤1:编写布局文件(activity_main.xml)

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 第一个视频的TextureView,初始显示 -->
    <TextureView
        android:id="@+id/texture_video1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:alpha="1.0"/>

    <!-- 第二个视频的TextureView,初始隐藏 -->
    <TextureView
        android:id="@+id/texture_video2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:alpha="0.0"/>

</FrameLayout>

步骤2:Activity中的实现代码

public class VideoSwitchActivity extends AppCompatActivity implements SurfaceTextureListener {
    private TextureView textureVideo1, textureVideo2;
    private MediaPlayer player1, player2;
    private boolean isShowingVideo1 = true;

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

        textureVideo1 = findViewById(R.id.texture_video1);
        textureVideo2 = findViewById(R.id.texture_video2);

        // 设置SurfaceTexture监听器,准备视频播放
        textureVideo1.setSurfaceTextureListener(this);
        textureVideo2.setSurfaceTextureListener(this);

        // 点击布局任意位置切换视频
        findViewById(R.id.root_layout).setOnClickListener(v -> switchVideo());
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        // 根据SurfaceTexture对应的TextureView初始化对应的MediaPlayer
        if (surface == textureVideo1.getSurfaceTexture()) {
            initPlayer(player1, R.raw.test1, surface);
        } else if (surface == textureVideo2.getSurfaceTexture()) {
            initPlayer(player2, R.raw.test2, surface);
        }
    }

    // 初始化MediaPlayer的工具方法
    private void initPlayer(MediaPlayer player, int videoResId, SurfaceTexture surface) {
        player = MediaPlayer.create(this, videoResId);
        player.setLooping(true);
        player.setSurface(new Surface(surface));
        player.start();
    }

    // 切换视频的核心方法,执行淡入淡出动画
    private void switchVideo() {
        Animation fadeOutAnim = AnimationUtils.loadAnimation(this, R.anim.fade_out);
        Animation fadeInAnim = AnimationUtils.loadAnimation(this, R.anim.fade_in);

        if (isShowingVideo1) {
            // 当前显示视频1,切换到视频2
            textureVideo1.startAnimation(fadeOutAnim);
            textureVideo2.startAnimation(fadeInAnim);
            textureVideo1.setAlpha(0.0f);
            textureVideo2.setAlpha(1.0f);
        } else {
            // 当前显示视频2,切换到视频1
            textureVideo2.startAnimation(fadeOutAnim);
            textureVideo1.startAnimation(fadeInAnim);
            textureVideo2.setAlpha(0.0f);
            textureVideo1.setAlpha(1.0f);
        }
        isShowingVideo1 = !isShowingVideo1;
    }

    // SurfaceTextureListener的其他空实现
    @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}
    @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { return false; }
    @Override public void onSurfaceTextureUpdated(SurfaceTexture surface) {}

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 释放MediaPlayer资源
        if (player1 != null) player1.release();
        if (player2 != null) player2.release();
    }
}

这个方案的优势是完全在同一个窗口内操作,没有Activity切换的空白,过渡效果流畅,完美适配KitKat系统。

方案二:使用Fragment切换代替Activity跳转

如果业务逻辑需要拆分页面,可以将每个视频放在独立的Fragment中,通过FragmentTransaction的自定义动画实现过渡,同样避免Activity窗口切换的问题。

核心切换代码

// 在宿主Activity中切换Fragment
getSupportFragmentManager().beginTransaction()
    .setCustomAnimations(R.anim.fade_in, R.anim.fade_out) // 设置淡入淡出动画
    .replace(R.id.fragment_container, new NextVideoFragment())
    .commit();

每个Fragment内部的TextureView和MediaPlayer初始化逻辑和你之前的Activity代码一致即可。

方案三:修改Activity窗口为透明(妥协方案)

如果必须保留Activity跳转,可以尝试将两个Activity的窗口背景设为透明,减少空白的视觉冲击,但在KitKat上可能仍有短暂的空白(取决于视频加载速度)。

步骤1:定义透明主题(styles.xml)

<style name="TransparentVideoActivity" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowAnimationStyle">@null</item>
</style>

步骤2:在Manifest中为Activity应用该主题

<activity
    android:name=".MainActivity"
    android:theme="@style/TransparentVideoActivity"/>
<activity
    android:name=".FirstVideoActivity"
    android:theme="@style/TransparentVideoActivity"/>

同时要确保新Activity的MediaPlayer尽可能早地初始化(比如在onCreate中立即开始准备),缩短空白时间。


内容的提问来源于stack exchange,提问作者acroscene

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:48:23