修复::手机无法正常开播
This commit is contained in:
parent
18719d752b
commit
1be8f14f07
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -45,3 +45,7 @@ archive/
|
|||
Thumbs.db
|
||||
**/.idea/
|
||||
**/.vscode/
|
||||
android-app/gradle/wrapper/gradle-wrapper.properties
|
||||
android-app/gradle/wrapper/gradle-wrapper.properties
|
||||
android-app/gradle/wrapper/gradle-wrapper.properties
|
||||
android-app/gradle/wrapper/gradle-wrapper.properties
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import android.os.Handler;
|
|||
import android.os.Looper;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Size;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
|
@ -28,9 +27,11 @@ import com.example.livestreaming.net.AuthStore;
|
|||
import com.example.livestreaming.net.CreateRoomRequest;
|
||||
import com.example.livestreaming.net.Room;
|
||||
import com.pedro.encoder.input.video.CameraHelper;
|
||||
import com.pedro.encoder.input.video.CameraOpenException;
|
||||
import com.pedro.rtmp.utils.ConnectCheckerRtmp;
|
||||
import com.pedro.rtplibrary.rtmp.RtmpCamera1;
|
||||
import com.pedro.rtplibrary.rtmp.RtmpCamera2;
|
||||
import com.pedro.rtplibrary.view.OpenGlView;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
|
@ -42,7 +43,7 @@ import retrofit2.Response;
|
|||
/**
|
||||
* 手机开播界面
|
||||
* 使用 RootEncoder 进行 RTMP 推流
|
||||
* 优先使用 Camera2 API (RtmpCamera2),兼容性更好
|
||||
* 使用 OpenGlView 确保视频编码正常工作
|
||||
*/
|
||||
public class BroadcastActivity extends AppCompatActivity implements ConnectCheckerRtmp, SurfaceHolder.Callback {
|
||||
|
||||
|
|
@ -68,11 +69,11 @@ public class BroadcastActivity extends AppCompatActivity implements ConnectCheck
|
|||
private boolean streamerVerified = false;
|
||||
private boolean cameraInitialized = false;
|
||||
|
||||
// 推流参数 - 平衡画质和流畅度
|
||||
private static final int VIDEO_WIDTH = 720;
|
||||
private static final int VIDEO_HEIGHT = 480;
|
||||
private static final int VIDEO_FPS = 24;
|
||||
private static final int VIDEO_BITRATE = 1200 * 1024; // 1.2Mbps
|
||||
// 推流参数 - 使用标准16:9分辨率,兼容性更好
|
||||
private static final int VIDEO_WIDTH = 640;
|
||||
private static final int VIDEO_HEIGHT = 360; // 标准16:9比例
|
||||
private static final int VIDEO_FPS = 25; // 标准帧率
|
||||
private static final int VIDEO_BITRATE = 800 * 1024; // 800kbps,更流畅
|
||||
private static final int AUDIO_BITRATE = 64 * 1024;
|
||||
private static final int AUDIO_SAMPLE_RATE = 44100;
|
||||
|
||||
|
|
@ -239,7 +240,8 @@ public class BroadcastActivity extends AppCompatActivity implements ConnectCheck
|
|||
}
|
||||
|
||||
private void setupSurface() {
|
||||
binding.surfaceView.getHolder().addCallback(this);
|
||||
// OpenGlView 使用 SurfaceHolder.Callback
|
||||
binding.openGlView.getHolder().addCallback(this);
|
||||
}
|
||||
|
||||
private void checkPermissions() {
|
||||
|
|
@ -285,7 +287,7 @@ public class BroadcastActivity extends AppCompatActivity implements ConnectCheck
|
|||
}
|
||||
|
||||
if (cameraInitialized) {
|
||||
Log.d(TAG, "摄像头已初始化");
|
||||
Log.d(TAG, "摄像头已初始化,跳过");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -296,6 +298,8 @@ public class BroadcastActivity extends AppCompatActivity implements ConnectCheck
|
|||
return;
|
||||
}
|
||||
|
||||
// 立即设置标志,防止重复初始化
|
||||
cameraInitialized = true;
|
||||
Log.d(TAG, "开始初始化摄像头...");
|
||||
|
||||
// 延迟初始化,确保 Surface 完全准备好
|
||||
|
|
@ -304,6 +308,7 @@ public class BroadcastActivity extends AppCompatActivity implements ConnectCheck
|
|||
initCameraInternal();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "摄像头初始化异常: " + e.getMessage(), e);
|
||||
cameraInitialized = false; // 失败时重置标志
|
||||
Toast.makeText(this, "摄像头初始化失败", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}, 500);
|
||||
|
|
@ -313,16 +318,40 @@ public class BroadcastActivity extends AppCompatActivity implements ConnectCheck
|
|||
// 优先尝试 Camera2 API (Android 5.0+)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
try {
|
||||
Log.d(TAG, "尝试使用 Camera2 API...");
|
||||
rtmpCamera2 = new RtmpCamera2(binding.surfaceView, this);
|
||||
Log.d(TAG, "尝试使用 Camera2 API + OpenGlView...");
|
||||
// 【关键】使用 OpenGlView 构造 RtmpCamera2,确保视频编码正常
|
||||
rtmpCamera2 = new RtmpCamera2(binding.openGlView, this);
|
||||
|
||||
// 先开始预览,再准备编码器(推流时再准备)
|
||||
String cameraId = isFrontCamera ? "1" : "0";
|
||||
rtmpCamera2.startPreview(cameraId);
|
||||
useCamera2 = true;
|
||||
cameraInitialized = true;
|
||||
Log.d(TAG, "Camera2 预览已开始");
|
||||
return;
|
||||
// 【关键】正确顺序:先准备编码器,再开始预览
|
||||
// 准备音频编码器
|
||||
boolean audioReady = rtmpCamera2.prepareAudio(AUDIO_BITRATE, AUDIO_SAMPLE_RATE, false);
|
||||
Log.d(TAG, "Camera2 音频编码器准备: " + audioReady);
|
||||
|
||||
// 准备视频编码器 - 尝试多种分辨率
|
||||
boolean videoReady = rtmpCamera2.prepareVideo(VIDEO_WIDTH, VIDEO_HEIGHT, VIDEO_FPS, VIDEO_BITRATE, 2);
|
||||
Log.d(TAG, "Camera2 视频编码器准备 (640x360): " + videoReady);
|
||||
|
||||
if (!videoReady) {
|
||||
videoReady = rtmpCamera2.prepareVideo(480, 270, 20, 500 * 1024, 2);
|
||||
Log.d(TAG, "Camera2 视频编码器准备 (480x270): " + videoReady);
|
||||
}
|
||||
|
||||
if (!videoReady) {
|
||||
videoReady = rtmpCamera2.prepareVideo(320, 240, 15, 300 * 1024, 2);
|
||||
Log.d(TAG, "Camera2 视频编码器准备 (320x240): " + videoReady);
|
||||
}
|
||||
|
||||
if (!audioReady || !videoReady) {
|
||||
Log.e(TAG, "Camera2 编码器准备失败,尝试 Camera1");
|
||||
rtmpCamera2 = null;
|
||||
} else {
|
||||
// 编码器准备好后,开始预览
|
||||
String cameraId = isFrontCamera ? "1" : "0";
|
||||
rtmpCamera2.startPreview(cameraId);
|
||||
useCamera2 = true;
|
||||
Log.d(TAG, "Camera2 + OpenGlView 初始化完成,预览已开始");
|
||||
return;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Camera2 初始化失败: " + e.getMessage(), e);
|
||||
if (rtmpCamera2 != null) {
|
||||
|
|
@ -334,14 +363,33 @@ public class BroadcastActivity extends AppCompatActivity implements ConnectCheck
|
|||
|
||||
// 回退到 Camera1 API
|
||||
try {
|
||||
Log.d(TAG, "尝试使用 Camera1 API...");
|
||||
rtmpCamera1 = new RtmpCamera1(binding.surfaceView, this);
|
||||
Log.d(TAG, "尝试使用 Camera1 API + OpenGlView...");
|
||||
// 【关键】使用 OpenGlView 构造 RtmpCamera1
|
||||
rtmpCamera1 = new RtmpCamera1(binding.openGlView, this);
|
||||
|
||||
// 【关键】正确顺序:先准备编码器,再开始预览
|
||||
boolean audioReady = rtmpCamera1.prepareAudio(AUDIO_BITRATE, AUDIO_SAMPLE_RATE, false, false, false);
|
||||
Log.d(TAG, "Camera1 音频编码器准备: " + audioReady);
|
||||
|
||||
boolean videoReady = rtmpCamera1.prepareVideo(VIDEO_WIDTH, VIDEO_HEIGHT, VIDEO_FPS, VIDEO_BITRATE, 2);
|
||||
Log.d(TAG, "Camera1 视频编码器准备 (640x360): " + videoReady);
|
||||
|
||||
if (!videoReady) {
|
||||
videoReady = rtmpCamera1.prepareVideo(480, 270, 20, 500 * 1024, 2);
|
||||
Log.d(TAG, "Camera1 视频编码器准备 (480x270): " + videoReady);
|
||||
}
|
||||
|
||||
if (!audioReady || !videoReady) {
|
||||
Log.e(TAG, "Camera1 编码器也准备失败");
|
||||
cameraInitialized = false; // 重置标志
|
||||
Toast.makeText(this, "编码器初始化失败", Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
CameraHelper.Facing facing = isFrontCamera ? CameraHelper.Facing.FRONT : CameraHelper.Facing.BACK;
|
||||
rtmpCamera1.startPreview(facing);
|
||||
useCamera2 = false;
|
||||
cameraInitialized = true;
|
||||
Log.d(TAG, "Camera1 预览已开始");
|
||||
Log.d(TAG, "Camera1 + OpenGlView 初始化完成,预览已开始");
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Camera1 初始化也失败: " + e.getMessage(), e);
|
||||
|
|
@ -351,6 +399,7 @@ public class BroadcastActivity extends AppCompatActivity implements ConnectCheck
|
|||
rtmpCamera1 = null;
|
||||
}
|
||||
|
||||
cameraInitialized = false; // 重置标志
|
||||
Toast.makeText(this, "摄像头初始化失败,请检查权限或重启应用", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
|
|
@ -484,53 +533,23 @@ public class BroadcastActivity extends AppCompatActivity implements ConnectCheck
|
|||
Log.d(TAG, "开始推流到: " + rtmpUrl);
|
||||
|
||||
try {
|
||||
// 编码器已在 initCameraInternal 中准备好,直接开始推流
|
||||
if (useCamera2 && rtmpCamera2 != null) {
|
||||
Log.d(TAG, "使用 Camera2 API 推流");
|
||||
|
||||
// 推流前准备编码器 - 使用优化后的低码率参数
|
||||
boolean audioReady = rtmpCamera2.prepareAudio(AUDIO_BITRATE, AUDIO_SAMPLE_RATE, false);
|
||||
// 使用 640x360 低分辨率,更流畅
|
||||
boolean videoReady = rtmpCamera2.prepareVideo(VIDEO_WIDTH, VIDEO_HEIGHT, VIDEO_FPS, VIDEO_BITRATE, 0);
|
||||
|
||||
Log.d(TAG, "编码器准备: audio=" + audioReady + ", video=" + videoReady);
|
||||
|
||||
if (!videoReady) {
|
||||
// 尝试更低的分辨率
|
||||
Log.w(TAG, "640x360 失败,尝试 480x270");
|
||||
videoReady = rtmpCamera2.prepareVideo(480, 270, VIDEO_FPS, VIDEO_BITRATE, 0);
|
||||
}
|
||||
|
||||
if (!videoReady) {
|
||||
Log.e(TAG, "视频编码器准备失败");
|
||||
binding.progressBar.setVisibility(View.GONE);
|
||||
binding.btnStartLive.setEnabled(true);
|
||||
Toast.makeText(this, "视频编码器初始化失败", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rtmpCamera2.isStreaming()) {
|
||||
rtmpCamera2.startStream(rtmpUrl);
|
||||
Log.d(TAG, "Camera2 推流已启动");
|
||||
}
|
||||
|
||||
} else if (rtmpCamera1 != null) {
|
||||
Log.d(TAG, "使用 Camera1 API 推流");
|
||||
|
||||
// 推流前准备编码器 - 使用优化参数
|
||||
boolean audioReady = rtmpCamera1.prepareAudio(AUDIO_BITRATE, AUDIO_SAMPLE_RATE, false, false, false);
|
||||
boolean videoReady = rtmpCamera1.prepareVideo(VIDEO_WIDTH, VIDEO_HEIGHT, VIDEO_FPS, VIDEO_BITRATE, 0);
|
||||
|
||||
Log.d(TAG, "编码器准备: audio=" + audioReady + ", video=" + videoReady);
|
||||
|
||||
if (!videoReady) {
|
||||
Log.e(TAG, "视频编码器准备失败");
|
||||
binding.progressBar.setVisibility(View.GONE);
|
||||
binding.btnStartLive.setEnabled(true);
|
||||
Toast.makeText(this, "视频编码器初始化失败", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rtmpCamera1.isStreaming()) {
|
||||
rtmpCamera1.startStream(rtmpUrl);
|
||||
Log.d(TAG, "Camera1 推流已启动");
|
||||
}
|
||||
|
||||
} else {
|
||||
Log.e(TAG, "没有可用的摄像头推流器");
|
||||
binding.progressBar.setVisibility(View.GONE);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.example.livestreaming;
|
|||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
|
@ -185,6 +186,9 @@ public class RoomDetailActivity extends AppCompatActivity implements SurfaceHold
|
|||
getSupportActionBar().hide();
|
||||
}
|
||||
|
||||
// 设置沉浸式全屏模式
|
||||
setupImmersiveMode();
|
||||
|
||||
android.util.Log.d("RoomDetail", "开始inflate布局");
|
||||
binding = ActivityRoomDetailNewBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
|
|
@ -242,6 +246,28 @@ public class RoomDetailActivity extends AppCompatActivity implements SurfaceHold
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置沉浸式全屏模式
|
||||
*/
|
||||
private void setupImmersiveMode() {
|
||||
// 设置全屏沉浸式体验
|
||||
getWindow().setFlags(
|
||||
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
|
||||
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
|
||||
);
|
||||
|
||||
// 设置状态栏透明
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
getWindow().setStatusBarColor(android.graphics.Color.TRANSPARENT);
|
||||
}
|
||||
|
||||
// 隐藏导航栏(可选)
|
||||
View decorView = getWindow().getDecorView();
|
||||
int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
|
||||
decorView.setSystemUiVisibility(uiOptions);
|
||||
}
|
||||
|
||||
private void setupUI() {
|
||||
// 返回按钮
|
||||
binding.backButton.setOnClickListener(v -> finish());
|
||||
|
|
@ -954,13 +980,15 @@ public class RoomDetailActivity extends AppCompatActivity implements SurfaceHold
|
|||
// 横屏时隐藏其他UI元素,只显示播放器
|
||||
binding.topBar.setVisibility(View.GONE);
|
||||
binding.roomInfoLayout.setVisibility(View.GONE);
|
||||
binding.chatLayout.setVisibility(View.GONE);
|
||||
binding.exitFullscreenButton.setVisibility(View.GONE);
|
||||
binding.chatInputLayout.setVisibility(View.GONE);
|
||||
binding.chatRecyclerView.setVisibility(View.GONE);
|
||||
binding.exitFullscreenButton.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
// 竖屏时显示所有UI元素
|
||||
binding.topBar.setVisibility(View.VISIBLE);
|
||||
binding.roomInfoLayout.setVisibility(View.VISIBLE);
|
||||
binding.chatLayout.setVisibility(View.VISIBLE);
|
||||
binding.chatInputLayout.setVisibility(View.VISIBLE);
|
||||
binding.chatRecyclerView.setVisibility(View.VISIBLE);
|
||||
binding.exitFullscreenButton.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -784,4 +784,102 @@ public interface ApiService {
|
|||
*/
|
||||
@GET("api/front/fan-group/all")
|
||||
Call<ApiResponse<List<Map<String, Object>>>> getAllMyFanGroups();
|
||||
|
||||
// ==================== 用户活动记录 ====================
|
||||
|
||||
/**
|
||||
* 获取观看历史
|
||||
*/
|
||||
@GET("api/front/activity/view-history")
|
||||
Call<ApiResponse<PageResponse<Map<String, Object>>>> getViewHistory(
|
||||
@Query("type") String type,
|
||||
@Query("page") int page,
|
||||
@Query("pageSize") int pageSize);
|
||||
|
||||
/**
|
||||
* 清除观看历史
|
||||
*/
|
||||
@DELETE("api/front/activity/view-history")
|
||||
Call<ApiResponse<String>> clearViewHistory(@Query("type") String type);
|
||||
|
||||
/**
|
||||
* 获取点赞记录
|
||||
*/
|
||||
@GET("api/front/activity/like-records")
|
||||
Call<ApiResponse<PageResponse<Map<String, Object>>>> getLikeRecords(
|
||||
@Query("type") String type,
|
||||
@Query("page") int page,
|
||||
@Query("pageSize") int pageSize);
|
||||
|
||||
/**
|
||||
* 获取收藏的作品
|
||||
*/
|
||||
@GET("api/front/activity/collected-works")
|
||||
Call<ApiResponse<PageResponse<Map<String, Object>>>> getCollectedWorks(
|
||||
@Query("page") int page,
|
||||
@Query("pageSize") int pageSize);
|
||||
|
||||
/**
|
||||
* 获取关注记录
|
||||
*/
|
||||
@GET("api/front/activity/follow-records")
|
||||
Call<ApiResponse<PageResponse<Map<String, Object>>>> getFollowRecords(
|
||||
@Query("page") int page,
|
||||
@Query("pageSize") int pageSize);
|
||||
|
||||
/**
|
||||
* 获取消费记录
|
||||
*/
|
||||
@GET("api/front/activity/consume-records")
|
||||
Call<ApiResponse<List<Map<String, Object>>>> getConsumeRecords(
|
||||
@Query("page") int page,
|
||||
@Query("pageSize") int pageSize);
|
||||
|
||||
/**
|
||||
* 记录观看历史(新版)
|
||||
*/
|
||||
@POST("api/front/activity/record-view")
|
||||
Call<ApiResponse<Map<String, Object>>> recordViewHistoryNew(@Body Map<String, Object> body);
|
||||
|
||||
/**
|
||||
* 调试Token
|
||||
*/
|
||||
@GET("api/front/activity/debug-token")
|
||||
Call<ApiResponse<Map<String, Object>>> debugToken();
|
||||
|
||||
// ==================== 黑名单接口 ====================
|
||||
|
||||
/**
|
||||
* 获取我的黑名单
|
||||
*/
|
||||
@GET("api/front/blacklist/list")
|
||||
Call<ApiResponse<PageResponse<Map<String, Object>>>> getMyBlacklist(
|
||||
@Query("page") int page,
|
||||
@Query("pageSize") int pageSize);
|
||||
|
||||
/**
|
||||
* 添加到黑名单
|
||||
*/
|
||||
@POST("api/front/blacklist/add")
|
||||
Call<ApiResponse<String>> addToBlacklist(@Body Map<String, Object> body);
|
||||
|
||||
/**
|
||||
* 从黑名单移除
|
||||
*/
|
||||
@POST("api/front/blacklist/remove")
|
||||
Call<ApiResponse<Map<String, Object>>> removeFromBlacklist(@Body Map<String, Object> body);
|
||||
|
||||
/**
|
||||
* 检查是否在黑名单中
|
||||
*/
|
||||
@GET("api/front/blacklist/check/{userId}")
|
||||
Call<ApiResponse<Map<String, Object>>> checkBlacklist(@Path("userId") int userId);
|
||||
|
||||
// ==================== 直播分类 ====================
|
||||
|
||||
/**
|
||||
* 获取直播分类列表
|
||||
*/
|
||||
@GET("api/front/live/types")
|
||||
Call<ApiResponse<List<LiveTypeResponse>>> getLiveTypes();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#40000000" />
|
||||
<corners android:radius="20dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#40FFFFFF" />
|
||||
</shape>
|
||||
|
|
@ -5,15 +5,17 @@
|
|||
android:layout_height="match_parent"
|
||||
android:background="#000000">
|
||||
|
||||
<!-- 使用 SurfaceView 作为摄像头预览,支持 RootEncoder RTMP 推流 -->
|
||||
<SurfaceView
|
||||
android:id="@+id/surfaceView"
|
||||
<!-- 使用 OpenGlView 作为摄像头预览,支持 RootEncoder RTMP 推流和视频编码 -->
|
||||
<com.pedro.rtplibrary.view.OpenGlView
|
||||
android:id="@+id/openGlView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:keepAspectRatio="true"
|
||||
app:aspectRatioMode="adjust" />
|
||||
|
||||
<!-- 顶部工具栏 -->
|
||||
<LinearLayout
|
||||
|
|
|
|||
|
|
@ -1,149 +1,50 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#000000"
|
||||
android:fitsSystemWindows="true">
|
||||
android:background="#000000">
|
||||
|
||||
<!-- 顶部标题栏 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/topBar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="#1A1A1A"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="4dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/backButton"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="返回"
|
||||
android:src="@drawable/ic_arrow_back_24"
|
||||
app:tint="@android:color/white" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/topTitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="直播间"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<!-- 直播状态标签 -->
|
||||
<TextView
|
||||
android:id="@+id/liveTag"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="@drawable/live_badge_background"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:paddingVertical="3dp"
|
||||
android:text="● 直播中"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="11sp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- 观看人数 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/topViewerLayout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="14dp"
|
||||
android:layout_height="14dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:src="@drawable/ic_people_24"
|
||||
app:tint="#AAAAAA" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/topViewerCount"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="0"
|
||||
android:textColor="#AAAAAA"
|
||||
android:textSize="12sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 播放器容器 -->
|
||||
<!-- 全屏播放器容器 - 底层,视频填充整个屏幕 -->
|
||||
<FrameLayout
|
||||
android:id="@+id/playerContainer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="#000000"
|
||||
app:layout_constraintDimensionRatio="16:9"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/topBar">
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#000000">
|
||||
|
||||
<SurfaceView
|
||||
android:id="@+id/flvSurfaceView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextureView
|
||||
android:id="@+id/flvTextureView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- ExoPlayer 播放器 - 填充模式 -->
|
||||
<androidx.media3.ui.PlayerView
|
||||
android:id="@+id/playerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
app:resize_mode="fill"
|
||||
app:use_controller="false"
|
||||
app:show_buffering="when_playing" />
|
||||
app:show_buffering="when_playing"
|
||||
app:surface_type="texture_view" />
|
||||
|
||||
<!-- GSYVideoPlayer 播放器视图 -->
|
||||
<!-- GSYVideoPlayer 播放器视图 - 填充模式 -->
|
||||
<com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
|
||||
android:id="@+id/gsyPlayer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/exitFullscreenButton"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:layout_gravity="top|start"
|
||||
android:layout_margin="12dp"
|
||||
android:background="@drawable/bg_circle_white_60"
|
||||
android:contentDescription="退出全屏"
|
||||
android:src="@drawable/ic_arrow_back_24"
|
||||
android:tint="@android:color/white"
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- 横屏按钮 -->
|
||||
<ImageButton
|
||||
android:id="@+id/fullscreenButton"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="12dp"
|
||||
android:background="@drawable/bg_circle_white_60"
|
||||
android:contentDescription="全屏"
|
||||
android:src="@drawable/ic_fullscreen_24"
|
||||
android:tint="@android:color/white" />
|
||||
|
||||
<!-- 离线提示 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/offlineLayout"
|
||||
|
|
@ -180,158 +81,219 @@
|
|||
|
||||
</FrameLayout>
|
||||
|
||||
<!-- 直播信息区域 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/roomInfoLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/white"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:paddingVertical="10dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/playerContainer">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:background="@drawable/bg_avatar_circle"
|
||||
android:src="@drawable/ic_person_24"
|
||||
android:tint="@android:color/white" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/roomTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="直播间标题"
|
||||
android:textColor="#333333"
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/streamerName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:text="主播名称"
|
||||
android:textColor="#999999"
|
||||
android:textSize="12sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/shareButton"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="分享"
|
||||
android:src="@drawable/ic_share_24"
|
||||
android:tint="#666666" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/followButton"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="92dp"
|
||||
android:layout_height="40dp"
|
||||
android:paddingHorizontal="14dp"
|
||||
android:text="关注"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="12sp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:textAllCaps="false"
|
||||
app:backgroundTint="#FF2FD3C7"
|
||||
app:icon="@drawable/ic_heart_24"
|
||||
app:iconSize="14dp"
|
||||
app:iconTint="@android:color/white" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 粉丝团加入横幅 -->
|
||||
<include
|
||||
android:id="@+id/fanGroupBannerInclude"
|
||||
layout="@layout/banner_join_fan_group"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/roomInfoLayout" />
|
||||
|
||||
<!-- 弹幕区域 -->
|
||||
<!-- UI覆盖层 - 悬浮在视频上方,透明背景 -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/chatLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@android:color/white"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/fanGroupBannerInclude">
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/transparent">
|
||||
|
||||
<!-- 弹幕列表 -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/chatRecyclerView"
|
||||
<!-- 顶部渐变遮罩 - 半透明 -->
|
||||
<View
|
||||
android:id="@+id/topGradient"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingTop="8dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/chatInputLayout"
|
||||
android:layout_height="100dp"
|
||||
android:background="@drawable/bg_gradient_top"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<!-- 弹幕输入区域 -->
|
||||
<!-- 顶部工具栏 - 悬浮 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/chatInputLayout"
|
||||
android:id="@+id/topBar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#F5F5F5"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="12dp"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:paddingTop="36dp"
|
||||
android:paddingBottom="8dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/backButton"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:background="@drawable/bg_circle_semi_transparent"
|
||||
android:contentDescription="返回"
|
||||
android:src="@drawable/ic_arrow_back_24"
|
||||
app:tint="@android:color/white" />
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<!-- 直播状态标签 -->
|
||||
<TextView
|
||||
android:id="@+id/liveTag"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="@drawable/live_badge_background"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:paddingVertical="3dp"
|
||||
android:text="● 直播中"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="11sp"
|
||||
android:visibility="visible" />
|
||||
|
||||
<!-- 观看人数 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/topViewerLayout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_rounded_semi_transparent"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:paddingVertical="4dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="14dp"
|
||||
android:layout_height="14dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:src="@drawable/ic_people_24"
|
||||
app:tint="@android:color/white" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/topViewerCount"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="0"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="12sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 隐藏的标题(用于代码引用) -->
|
||||
<TextView
|
||||
android:id="@+id/topTitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<!-- 主播信息卡片 - 悬浮在左上角 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/roomInfoLayout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:background="@drawable/bg_rounded_semi_transparent"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:paddingVertical="6dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/topBar">
|
||||
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
android:id="@+id/streamerAvatar"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:src="@drawable/ic_person_24"
|
||||
app:civ_border_color="#FFFFFF"
|
||||
app:civ_border_width="1dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/streamerName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="主播"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="13sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/roomTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxWidth="100dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="直播间"
|
||||
android:textColor="#CCFFFFFF"
|
||||
android:textSize="11sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/followButton"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="26dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:minWidth="48dp"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:text="关注"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="11sp"
|
||||
android:textAllCaps="false"
|
||||
app:backgroundTint="#FF4081"
|
||||
app:cornerRadius="13dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 底部渐变遮罩 -->
|
||||
<View
|
||||
android:id="@+id/bottomGradient"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="180dp"
|
||||
android:background="@drawable/bg_gradient_bottom"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/chatInput"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/bg_white_16"
|
||||
android:hint="说点什么..."
|
||||
android:imeOptions="actionSend"
|
||||
android:inputType="text"
|
||||
android:maxLines="1"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:textSize="14sp" />
|
||||
<!-- 弹幕列表 - 左下角悬浮 -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/chatRecyclerView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="160dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="70dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingTop="8dp"
|
||||
android:background="@android:color/transparent"
|
||||
app:layout_constraintBottom_toTopOf="@id/chatInputLayout"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<!-- 点赞按钮容器 -->
|
||||
<!-- 右侧悬浮功能按钮 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/rightButtons"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginBottom="70dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toTopOf="@id/chatInputLayout"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
|
||||
<!-- 点赞按钮 -->
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginStart="8dp">
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/likeButton"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:background="@drawable/bg_circle_semi_transparent"
|
||||
android:contentDescription="点赞"
|
||||
android:src="@drawable/ic_like_24"
|
||||
android:tint="#FF4081" />
|
||||
|
|
@ -341,39 +303,120 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:layout_marginBottom="-4dp"
|
||||
android:layout_marginBottom="-2dp"
|
||||
android:background="@drawable/bg_purple_20"
|
||||
android:paddingHorizontal="4dp"
|
||||
android:paddingHorizontal="5dp"
|
||||
android:paddingVertical="1dp"
|
||||
android:text="0"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="9sp"
|
||||
android:visibility="visible" />
|
||||
android:textSize="9sp" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<!-- 礼物按钮 -->
|
||||
<ImageButton
|
||||
android:id="@+id/giftButton"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:background="@drawable/bg_circle_semi_transparent"
|
||||
android:contentDescription="送礼物"
|
||||
android:src="@drawable/ic_gift_24"
|
||||
android:tint="#FF9800" />
|
||||
|
||||
<!-- 分享按钮 -->
|
||||
<ImageButton
|
||||
android:id="@+id/shareButton"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:background="@drawable/bg_circle_semi_transparent"
|
||||
android:contentDescription="分享"
|
||||
android:src="@drawable/ic_share_24"
|
||||
android:tint="@android:color/white" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 全屏按钮 - 右下角 -->
|
||||
<ImageButton
|
||||
android:id="@+id/fullscreenButton"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="@drawable/bg_circle_semi_transparent"
|
||||
android:contentDescription="全屏"
|
||||
android:src="@drawable/ic_fullscreen_24"
|
||||
android:tint="@android:color/white"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintBottom_toTopOf="@id/rightButtons"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<!-- 退出全屏按钮 -->
|
||||
<ImageButton
|
||||
android:id="@+id/exitFullscreenButton"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_margin="12dp"
|
||||
android:visibility="gone"
|
||||
android:background="@drawable/bg_circle_semi_transparent"
|
||||
android:contentDescription="退出全屏"
|
||||
android:src="@drawable/ic_arrow_back_24"
|
||||
android:tint="@android:color/white"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<!-- 底部输入栏 - 悬浮 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/chatInputLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:paddingVertical="10dp"
|
||||
android:background="@android:color/transparent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/chatInput"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="38dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/bg_chat_input_dark"
|
||||
android:hint="说点什么..."
|
||||
android:textColorHint="#80FFFFFF"
|
||||
android:imeOptions="actionSend"
|
||||
android:inputType="text"
|
||||
android:maxLines="1"
|
||||
android:paddingHorizontal="14dp"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="13sp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/sendButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="40dp"
|
||||
android:layout_height="38dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="发送"
|
||||
android:textSize="12sp"
|
||||
app:backgroundTint="@color/purple_500" />
|
||||
app:backgroundTint="#FF4081"
|
||||
app:cornerRadius="19dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 粉丝团加入横幅 -->
|
||||
<include
|
||||
android:id="@+id/fanGroupBannerInclude"
|
||||
layout="@layout/banner_join_fan_group"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/roomInfoLayout" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<!-- 加载指示器 -->
|
||||
|
|
@ -381,20 +424,15 @@
|
|||
android:id="@+id/loadingIndicator"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- 礼物特效覆盖层 - 显示在发送按钮上方 -->
|
||||
<!-- 礼物特效覆盖层 -->
|
||||
<include
|
||||
android:id="@+id/giftAnimationOverlay"
|
||||
layout="@layout/gift_animation_overlay"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
android:layout_gravity="bottom" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</FrameLayout>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=file:///D:/soft/gradle-8.1-bin.zip
|
||||
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.14-bin.zip
|
||||
networkTimeout=600000
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user