主题:直播和作品按钮页面
This commit is contained in:
parent
669e2457a9
commit
d19d0cc631
|
|
@ -197,6 +197,11 @@
|
|||
android:name="com.example.livestreaming.UserProfileActivity"
|
||||
android:exported="false" />
|
||||
|
||||
<activity
|
||||
android:name="com.example.livestreaming.PublishCenterActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.example.livestreaming.WishTreeActivity"
|
||||
android:exported="false" />
|
||||
|
|
|
|||
|
|
@ -609,7 +609,8 @@ public class MainActivity extends AppCompatActivity {
|
|||
binding.fabAddLive.setOnClickListener(new DebounceClickListener() {
|
||||
@Override
|
||||
public void onDebouncedClick(View v) {
|
||||
showCreateRoomDialog();
|
||||
// 跳转到发布中心页面
|
||||
PublishCenterActivity.start(MainActivity.this);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -539,7 +539,7 @@ public class ProfileActivity extends AppCompatActivity {
|
|||
if (!AuthHelper.requireLogin(this, "发布作品需要登录")) {
|
||||
return;
|
||||
}
|
||||
PublishWorkActivity.start(this);
|
||||
PublishCenterActivity.start(this);
|
||||
});
|
||||
|
||||
// 悬浮按钮(固定显示)
|
||||
|
|
@ -548,7 +548,7 @@ public class ProfileActivity extends AppCompatActivity {
|
|||
if (!AuthHelper.requireLogin(this, "发布作品需要登录")) {
|
||||
return;
|
||||
}
|
||||
PublishWorkActivity.start(this);
|
||||
PublishCenterActivity.start(this);
|
||||
});
|
||||
binding.likedGoBrowseBtn.setOnClickListener(v -> startActivity(new Intent(this, MainActivity.class)));
|
||||
binding.favGoBrowseBtn.setOnClickListener(v -> startActivity(new Intent(this, MainActivity.class)));
|
||||
|
|
@ -578,7 +578,7 @@ public class ProfileActivity extends AppCompatActivity {
|
|||
if (!AuthHelper.requireLogin(this, "发布作品需要登录")) {
|
||||
return;
|
||||
}
|
||||
PublishWorkActivity.start(this);
|
||||
PublishCenterActivity.start(this);
|
||||
});
|
||||
|
||||
loadMyWorks();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,373 @@
|
|||
package com.example.livestreaming;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.example.livestreaming.databinding.ActivityPublishCenterBinding;
|
||||
import com.example.livestreaming.net.ApiClient;
|
||||
import com.example.livestreaming.net.ApiResponse;
|
||||
import com.example.livestreaming.net.CategoryResponse;
|
||||
import com.example.livestreaming.net.CreateRoomRequest;
|
||||
import com.example.livestreaming.net.FileUploadResponse;
|
||||
import com.example.livestreaming.net.Room;
|
||||
import com.example.livestreaming.net.StreamUrls;
|
||||
import com.example.livestreaming.net.WorksRequest;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.MultipartBody;
|
||||
import okhttp3.RequestBody;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
public class PublishCenterActivity extends AppCompatActivity {
|
||||
|
||||
private ActivityPublishCenterBinding binding;
|
||||
private int currentTab = 0;
|
||||
private List<CategoryResponse> categoryList = new ArrayList<>();
|
||||
private int selectedCategoryId = -1;
|
||||
private Uri dynamicCoverUri = null;
|
||||
private ActivityResultLauncher<Intent> imagePickerLauncher;
|
||||
|
||||
public static void start(Context context) {
|
||||
context.startActivity(new Intent(context, PublishCenterActivity.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (!AuthHelper.requireLogin(this, "发布内容需要登录")) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
binding = ActivityPublishCenterBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
setupImagePicker();
|
||||
setupToolbar();
|
||||
setupTabs();
|
||||
setupClickListeners();
|
||||
loadCategories();
|
||||
showTab(0);
|
||||
}
|
||||
|
||||
private void setupImagePicker() {
|
||||
imagePickerLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.StartActivityForResult(),
|
||||
result -> {
|
||||
if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) {
|
||||
Uri uri = result.getData().getData();
|
||||
if (uri != null) {
|
||||
dynamicCoverUri = uri;
|
||||
showDynamicCover(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private void setupToolbar() {
|
||||
binding.btnBack.setOnClickListener(v -> finish());
|
||||
}
|
||||
|
||||
private void setupTabs() {
|
||||
binding.tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab) { showTab(tab.getPosition()); }
|
||||
@Override
|
||||
public void onTabUnselected(TabLayout.Tab tab) {}
|
||||
@Override
|
||||
public void onTabReselected(TabLayout.Tab tab) {}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupClickListeners() {
|
||||
binding.btnStartLive.setOnClickListener(v -> startMobileLive());
|
||||
binding.btnPublishDynamic.setOnClickListener(v -> publishDynamic());
|
||||
binding.dynamicCoverContainer.setOnClickListener(v -> pickDynamicCover());
|
||||
binding.btnRemoveDynamicCover.setOnClickListener(v -> removeDynamicCover());
|
||||
binding.btnPublishWork.setOnClickListener(v -> PublishWorkActivity.start(this));
|
||||
binding.btnCopyStreamUrl.setOnClickListener(v -> copyToClipboard("推流地址", binding.tvStreamUrl.getText().toString()));
|
||||
binding.btnCopyStreamKey.setOnClickListener(v -> copyToClipboard("推流码", binding.tvStreamKey.getText().toString()));
|
||||
binding.btnGetStreamInfo.setOnClickListener(v -> createPcLiveRoom());
|
||||
}
|
||||
|
||||
private void showTab(int position) {
|
||||
currentTab = position;
|
||||
binding.contentMobileLive.setVisibility(View.GONE);
|
||||
binding.contentDynamic.setVisibility(View.GONE);
|
||||
binding.contentWork.setVisibility(View.GONE);
|
||||
binding.contentPcLive.setVisibility(View.GONE);
|
||||
switch (position) {
|
||||
case 0: binding.contentMobileLive.setVisibility(View.VISIBLE); break;
|
||||
case 1: binding.contentDynamic.setVisibility(View.VISIBLE); break;
|
||||
case 2: binding.contentWork.setVisibility(View.VISIBLE); break;
|
||||
case 3: binding.contentPcLive.setVisibility(View.VISIBLE); break;
|
||||
}
|
||||
}
|
||||
|
||||
private void loadCategories() {
|
||||
ApiClient.getService(this).getLiveRoomCategories().enqueue(new Callback<ApiResponse<List<CategoryResponse>>>() {
|
||||
@Override
|
||||
public void onResponse(Call<ApiResponse<List<CategoryResponse>>> call, Response<ApiResponse<List<CategoryResponse>>> response) {
|
||||
if (response.isSuccessful() && response.body() != null && response.body().isOk()) {
|
||||
categoryList = response.body().getData();
|
||||
if (categoryList == null) categoryList = new ArrayList<>();
|
||||
}
|
||||
setupCategorySpinner();
|
||||
}
|
||||
@Override
|
||||
public void onFailure(Call<ApiResponse<List<CategoryResponse>>> call, Throwable t) {
|
||||
setupCategorySpinner();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupCategorySpinner() {
|
||||
List<String> names = new ArrayList<>();
|
||||
names.add("请选择分类");
|
||||
for (CategoryResponse cat : categoryList) names.add(cat.getName());
|
||||
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, names);
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
binding.spinnerPcCategory.setAdapter(adapter);
|
||||
binding.spinnerPcCategory.setOnItemSelectedListener(new android.widget.AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(android.widget.AdapterView<?> parent, View view, int pos, long id) {
|
||||
selectedCategoryId = (pos > 0 && pos <= categoryList.size()) ? categoryList.get(pos - 1).getId() : -1;
|
||||
}
|
||||
@Override
|
||||
public void onNothingSelected(android.widget.AdapterView<?> parent) { selectedCategoryId = -1; }
|
||||
});
|
||||
}
|
||||
|
||||
private void startMobileLive() {
|
||||
String title = binding.etLiveTitle.getText().toString().trim();
|
||||
if (TextUtils.isEmpty(title)) title = "我的直播间";
|
||||
Intent intent = new Intent(this, BroadcastActivity.class);
|
||||
intent.putExtra("title", title);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
|
||||
private void pickDynamicCover() {
|
||||
Intent intent = new Intent(Intent.ACTION_PICK);
|
||||
intent.setType("image/*");
|
||||
imagePickerLauncher.launch(intent);
|
||||
}
|
||||
|
||||
private void showDynamicCover(Uri uri) {
|
||||
binding.ivDynamicCover.setVisibility(View.VISIBLE);
|
||||
binding.dynamicCoverPlaceholder.setVisibility(View.GONE);
|
||||
binding.btnRemoveDynamicCover.setVisibility(View.VISIBLE);
|
||||
Glide.with(this).load(uri).centerCrop().into(binding.ivDynamicCover);
|
||||
}
|
||||
|
||||
private void removeDynamicCover() {
|
||||
dynamicCoverUri = null;
|
||||
binding.ivDynamicCover.setVisibility(View.GONE);
|
||||
binding.dynamicCoverPlaceholder.setVisibility(View.VISIBLE);
|
||||
binding.btnRemoveDynamicCover.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private void publishDynamic() {
|
||||
String content = binding.etDynamicContent.getText().toString().trim();
|
||||
if (TextUtils.isEmpty(content)) {
|
||||
Toast.makeText(this, "请输入动态内容", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
if (content.length() > 1000) {
|
||||
Toast.makeText(this, "内容不能超过1000字", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
binding.btnPublishDynamic.setEnabled(false);
|
||||
binding.btnPublishDynamic.setText("发布中...");
|
||||
|
||||
if (dynamicCoverUri != null) {
|
||||
// 用户选择了封面,上传后发布
|
||||
uploadDynamicCoverAndPublish(content);
|
||||
} else {
|
||||
// 用户没选封面,使用特殊标记(纯文字动态)
|
||||
// 使用 "text_only" 作为标记,在展示时识别为纯文字动态
|
||||
doPublishDynamic(content, "text_only");
|
||||
}
|
||||
}
|
||||
|
||||
private void uploadDynamicCoverAndPublish(String content) {
|
||||
try {
|
||||
File file = uriToFile(dynamicCoverUri);
|
||||
if (file == null) {
|
||||
Toast.makeText(this, "无法读取图片", Toast.LENGTH_SHORT).show();
|
||||
resetDynamicButton();
|
||||
return;
|
||||
}
|
||||
RequestBody requestFile = RequestBody.create(MediaType.parse("image/*"), file);
|
||||
MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), requestFile);
|
||||
RequestBody model = RequestBody.create(MediaType.parse("text/plain"), "work");
|
||||
RequestBody pid = RequestBody.create(MediaType.parse("text/plain"), "0");
|
||||
ApiClient.getService(this).uploadImage(body, model, pid).enqueue(new Callback<ApiResponse<FileUploadResponse>>() {
|
||||
@Override
|
||||
public void onResponse(Call<ApiResponse<FileUploadResponse>> call, Response<ApiResponse<FileUploadResponse>> response) {
|
||||
if (response.isSuccessful() && response.body() != null && response.body().isOk()) {
|
||||
FileUploadResponse data = response.body().getData();
|
||||
doPublishDynamic(content, data != null ? data.getUrl() : null);
|
||||
} else {
|
||||
resetDynamicButton();
|
||||
Toast.makeText(PublishCenterActivity.this, "封面上传失败", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onFailure(Call<ApiResponse<FileUploadResponse>> call, Throwable t) {
|
||||
resetDynamicButton();
|
||||
Toast.makeText(PublishCenterActivity.this, "网络错误", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
resetDynamicButton();
|
||||
Toast.makeText(this, "图片处理失败", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
private void doPublishDynamic(String content, String coverUrl) {
|
||||
WorksRequest request = new WorksRequest();
|
||||
request.setTitle("");
|
||||
request.setDescription(content);
|
||||
request.setType("IMAGE");
|
||||
request.setImageUrls(new ArrayList<>());
|
||||
request.setCoverUrl(coverUrl != null ? coverUrl : "");
|
||||
ApiClient.getService(this).publishWork(request).enqueue(new Callback<ApiResponse<Long>>() {
|
||||
@Override
|
||||
public void onResponse(Call<ApiResponse<Long>> call, Response<ApiResponse<Long>> response) {
|
||||
resetDynamicButton();
|
||||
if (response.isSuccessful() && response.body() != null && response.body().isOk()) {
|
||||
Toast.makeText(PublishCenterActivity.this, "动态发布成功", Toast.LENGTH_SHORT).show();
|
||||
binding.etDynamicContent.setText("");
|
||||
removeDynamicCover();
|
||||
finish();
|
||||
} else {
|
||||
String msg = response.body() != null ? response.body().getMessage() : "发布失败";
|
||||
Toast.makeText(PublishCenterActivity.this, msg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onFailure(Call<ApiResponse<Long>> call, Throwable t) {
|
||||
resetDynamicButton();
|
||||
Toast.makeText(PublishCenterActivity.this, "网络错误", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void resetDynamicButton() {
|
||||
binding.btnPublishDynamic.setEnabled(true);
|
||||
binding.btnPublishDynamic.setText("发布动态");
|
||||
}
|
||||
|
||||
private File uriToFile(Uri uri) {
|
||||
try {
|
||||
InputStream is = getContentResolver().openInputStream(uri);
|
||||
if (is == null) return null;
|
||||
File file = new File(getCacheDir(), "temp_cover_" + System.currentTimeMillis() + ".jpg");
|
||||
FileOutputStream os = new FileOutputStream(file);
|
||||
byte[] buf = new byte[4096];
|
||||
int len;
|
||||
while ((len = is.read(buf)) != -1) os.write(buf, 0, len);
|
||||
is.close();
|
||||
os.close();
|
||||
return file;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void createPcLiveRoom() {
|
||||
String title = binding.etPcLiveTitle.getText().toString().trim();
|
||||
if (TextUtils.isEmpty(title)) {
|
||||
Toast.makeText(this, "请输入直播标题", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
if (selectedCategoryId <= 0) {
|
||||
Toast.makeText(this, "请选择直播分类", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
binding.btnGetStreamInfo.setEnabled(false);
|
||||
binding.btnGetStreamInfo.setText("创建中...");
|
||||
binding.streamInfoLoading.setVisibility(View.VISIBLE);
|
||||
|
||||
// 获取当前用户昵称作为主播名称
|
||||
String streamerName = com.example.livestreaming.net.AuthStore.getNickname(this);
|
||||
if (TextUtils.isEmpty(streamerName)) {
|
||||
streamerName = title; // 如果没有昵称,使用标题
|
||||
}
|
||||
|
||||
CreateRoomRequest request = new CreateRoomRequest(title, streamerName, "pc");
|
||||
request.setCategoryId(selectedCategoryId);
|
||||
|
||||
ApiClient.getService(this).createRoom(request).enqueue(new Callback<ApiResponse<Room>>() {
|
||||
@Override
|
||||
public void onResponse(Call<ApiResponse<Room>> call, Response<ApiResponse<Room>> response) {
|
||||
binding.btnGetStreamInfo.setEnabled(true);
|
||||
binding.btnGetStreamInfo.setText("创建直播间并获取推流信息");
|
||||
binding.streamInfoLoading.setVisibility(View.GONE);
|
||||
if (response.isSuccessful() && response.body() != null && response.body().isOk()) {
|
||||
Room room = response.body().getData();
|
||||
if (room != null) {
|
||||
showStreamInfo(room);
|
||||
} else {
|
||||
Toast.makeText(PublishCenterActivity.this, "创建成功但未获取到推流信息", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
} else {
|
||||
String msg = response.body() != null ? response.body().getMessage() : "创建直播间失败";
|
||||
Toast.makeText(PublishCenterActivity.this, msg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onFailure(Call<ApiResponse<Room>> call, Throwable t) {
|
||||
binding.btnGetStreamInfo.setEnabled(true);
|
||||
binding.btnGetStreamInfo.setText("创建直播间并获取推流信息");
|
||||
binding.streamInfoLoading.setVisibility(View.GONE);
|
||||
Toast.makeText(PublishCenterActivity.this, "网络错误", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showStreamInfo(Room room) {
|
||||
binding.streamInfoContent.setVisibility(View.VISIBLE);
|
||||
String streamKey = room.getStreamKey();
|
||||
StreamUrls streamUrls = room.getStreamUrls();
|
||||
String pushUrl = (streamUrls != null && streamUrls.getRtmp() != null) ? streamUrls.getRtmp() : "";
|
||||
binding.tvStreamUrl.setText(!TextUtils.isEmpty(pushUrl) ? pushUrl : "未获取到推流地址");
|
||||
binding.tvStreamKey.setText(!TextUtils.isEmpty(streamKey) ? streamKey : "未获取到推流码");
|
||||
Toast.makeText(this, "直播间创建成功!", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
private void copyToClipboard(String label, String text) {
|
||||
if (TextUtils.isEmpty(text) || text.startsWith("未获取")) {
|
||||
Toast.makeText(this, "内容为空", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
|
||||
if (clipboard != null) {
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText(label, text));
|
||||
Toast.makeText(this, label + "已复制", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -59,7 +59,10 @@ public class WorksAdapter extends RecyclerView.Adapter<WorksAdapter.WorksViewHol
|
|||
}
|
||||
|
||||
static class WorksViewHolder extends RecyclerView.ViewHolder {
|
||||
private final View coverContainer;
|
||||
private final View textContentContainer;
|
||||
private final ImageView coverImage;
|
||||
private final TextView contentText;
|
||||
private final TextView titleText;
|
||||
private final TextView authorText;
|
||||
private final TextView likeCountText;
|
||||
|
|
@ -67,7 +70,10 @@ public class WorksAdapter extends RecyclerView.Adapter<WorksAdapter.WorksViewHol
|
|||
|
||||
public WorksViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
coverContainer = itemView.findViewById(R.id.coverContainer);
|
||||
textContentContainer = itemView.findViewById(R.id.textContentContainer);
|
||||
coverImage = itemView.findViewById(R.id.worksCoverImage);
|
||||
contentText = itemView.findViewById(R.id.worksContentText);
|
||||
titleText = itemView.findViewById(R.id.worksTitleText);
|
||||
authorText = itemView.findViewById(R.id.worksAuthorText);
|
||||
likeCountText = itemView.findViewById(R.id.worksLikeCountText);
|
||||
|
|
@ -82,18 +88,36 @@ public class WorksAdapter extends RecyclerView.Adapter<WorksAdapter.WorksViewHol
|
|||
"title=" + works.getTitle() +
|
||||
", userName=" + works.getUserName() +
|
||||
", authorName=" + works.getAuthorName() +
|
||||
", likeCount=" + works.getLikeCount());
|
||||
", likeCount=" + works.getLikeCount() +
|
||||
", coverUrl=" + works.getCoverUrl());
|
||||
|
||||
// 设置封面图片
|
||||
if (works.getCoverUrl() != null && !works.getCoverUrl().isEmpty()) {
|
||||
// 判断是否有有效封面(排除纯文字动态标记)
|
||||
String coverUrl = works.getCoverUrl();
|
||||
boolean hasValidCover = coverUrl != null && !coverUrl.isEmpty()
|
||||
&& !coverUrl.equals("text_only"); // 排除纯文字动态标记
|
||||
|
||||
if (hasValidCover) {
|
||||
// 有封面:显示封面图片
|
||||
coverContainer.setVisibility(View.VISIBLE);
|
||||
textContentContainer.setVisibility(View.GONE);
|
||||
|
||||
Glide.with(itemView.getContext())
|
||||
.load(works.getCoverUrl())
|
||||
.load(coverUrl)
|
||||
.centerCrop()
|
||||
.placeholder(R.drawable.bg_cover_placeholder)
|
||||
.error(R.drawable.bg_cover_placeholder)
|
||||
.into(coverImage);
|
||||
} else {
|
||||
coverImage.setImageResource(R.drawable.bg_cover_placeholder);
|
||||
// 无封面:显示文字内容
|
||||
coverContainer.setVisibility(View.GONE);
|
||||
textContentContainer.setVisibility(View.VISIBLE);
|
||||
|
||||
String content = works.getDescription();
|
||||
if (content != null && !content.isEmpty()) {
|
||||
contentText.setText(content);
|
||||
} else {
|
||||
contentText.setText("暂无内容");
|
||||
}
|
||||
}
|
||||
|
||||
// 设置标题
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="8dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#CCCCCC"
|
||||
android:dashWidth="4dp"
|
||||
android:dashGap="2dp" />
|
||||
<corners android:radius="8dp" />
|
||||
<solid android:color="#F5F5F5" />
|
||||
</shape>
|
||||
|
|
|
|||
9
android-app/app/src/main/res/drawable/bg_spinner.xml
Normal file
9
android-app/app/src/main/res/drawable/bg_spinner.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#DDDDDD" />
|
||||
<corners android:radius="8dp" />
|
||||
<solid android:color="#FFFFFF" />
|
||||
</shape>
|
||||
10
android-app/app/src/main/res/drawable/ic_close_circle_24.xml
Normal file
10
android-app/app/src/main/res/drawable/ic_close_circle_24.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF4757"
|
||||
android:pathData="M12,2C6.47,2 2,6.47 2,12s4.47,10 10,10 10,-4.47 10,-10S17.53,2 12,2zM17,15.59L15.59,17 12,13.41 8.41,17 7,15.59 10.59,12 7,8.41 8.41,7 12,10.59 15.59,7 17,8.41 13.41,12 17,15.59z"/>
|
||||
</vector>
|
||||
494
android-app/app/src/main/res/layout/activity_publish_center.xml
Normal file
494
android-app/app/src/main/res/layout/activity_publish_center.xml
Normal file
|
|
@ -0,0 +1,494 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout 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="@color/white">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/topBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:background="@color/white"
|
||||
android:elevation="2dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/btnBack"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/ic_close_24"
|
||||
android:contentDescription="关闭"
|
||||
app:tint="#333333" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="16dp"
|
||||
android:text="发布"
|
||||
android:textSize="18sp"
|
||||
android:textColor="#333333"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tabLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginTop="56dp"
|
||||
android:background="@color/white"
|
||||
app:tabMode="fixed"
|
||||
app:tabGravity="fill"
|
||||
app:tabIndicatorColor="#FF4757"
|
||||
app:tabIndicatorHeight="3dp"
|
||||
app:tabSelectedTextColor="#FF4757"
|
||||
app:tabTextColor="#666666"
|
||||
app:tabRippleColor="@android:color/transparent">
|
||||
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="手机开播" />
|
||||
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="发布动态" />
|
||||
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="发布作品" />
|
||||
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="电脑开播" />
|
||||
|
||||
</com.google.android.material.tabs.TabLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="104dp">
|
||||
|
||||
<!-- 手机开播 -->
|
||||
<ScrollView
|
||||
android:id="@+id/contentMobileLive"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="visible">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="20dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="手机开播"
|
||||
android:textSize="20sp"
|
||||
android:textColor="#333333"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="使用手机摄像头进行直播"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#999999" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:hint="直播标题"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/etLiveTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text"
|
||||
android:maxLength="30" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnStartLive"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="52dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:text="开始直播"
|
||||
android:textSize="16sp"
|
||||
app:backgroundTint="#FF4757"
|
||||
app:cornerRadius="26dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<!-- 发布动态 -->
|
||||
<ScrollView
|
||||
android:id="@+id/contentDynamic"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="20dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="发布动态"
|
||||
android:textSize="20sp"
|
||||
android:textColor="#333333"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="快速发布文字动态,可选择添加封面图片"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#999999" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:hint="说点什么..."
|
||||
app:counterEnabled="true"
|
||||
app:counterMaxLength="1000"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/etDynamicContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textMultiLine"
|
||||
android:minLines="5"
|
||||
android:gravity="top"
|
||||
android:maxLength="1000" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!-- 封面图片选择(可选) -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:text="封面图片(可选)"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#666666" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/dynamicCoverContainer"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="120dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@drawable/bg_dashed_border"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivDynamicCover"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/dynamicCoverPlaceholder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:src="@drawable/ic_add_photo_24"
|
||||
app:tint="#999999" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="添加封面"
|
||||
android:textSize="12sp"
|
||||
android:textColor="#999999" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/btnRemoveDynamicCover"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="top|end"
|
||||
android:layout_margin="4dp"
|
||||
android:src="@drawable/ic_close_circle_24"
|
||||
android:visibility="gone"
|
||||
android:contentDescription="移除封面" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnPublishDynamic"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="52dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:text="发布动态"
|
||||
android:textSize="16sp"
|
||||
app:backgroundTint="#FF4757"
|
||||
app:cornerRadius="26dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<!-- 发布作品 -->
|
||||
<ScrollView
|
||||
android:id="@+id/contentWork"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="20dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="发布作品"
|
||||
android:textSize="20sp"
|
||||
android:textColor="#333333"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="发布图片或视频作品,支持添加标题、描述等"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#999999" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnPublishWork"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="52dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:text="去发布作品"
|
||||
android:textSize="16sp"
|
||||
app:backgroundTint="#FF4757"
|
||||
app:cornerRadius="26dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<!-- 电脑开播 -->
|
||||
<ScrollView
|
||||
android:id="@+id/contentPcLive"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="20dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="电脑开播"
|
||||
android:textSize="20sp"
|
||||
android:textColor="#333333"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="使用OBS等推流软件进行直播"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#999999" />
|
||||
|
||||
<!-- 直播标题 -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:hint="直播标题"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/etPcLiveTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text"
|
||||
android:maxLength="30" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!-- 分类选择 -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="选择分类"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#666666" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinnerPcCategory"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@drawable/bg_spinner"
|
||||
android:paddingHorizontal="12dp" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/streamInfoLoading"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="24dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/streamInfoContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="24dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="推流地址"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#666666" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:orientation="horizontal"
|
||||
android:background="@drawable/bg_edit_text"
|
||||
android:padding="12dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvStreamUrl"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text=""
|
||||
android:textSize="13sp"
|
||||
android:textColor="#333333"
|
||||
android:maxLines="2"
|
||||
android:ellipsize="end" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/btnCopyStreamUrl"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:src="@drawable/ic_copy_24"
|
||||
android:contentDescription="复制"
|
||||
app:tint="#666666" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="推流码"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#666666" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:orientation="horizontal"
|
||||
android:background="@drawable/bg_edit_text"
|
||||
android:padding="12dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvStreamKey"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text=""
|
||||
android:textSize="13sp"
|
||||
android:textColor="#333333"
|
||||
android:maxLines="2"
|
||||
android:ellipsize="end" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/btnCopyStreamKey"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:src="@drawable/ic_copy_24"
|
||||
android:contentDescription="复制"
|
||||
app:tint="#666666" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnGetStreamInfo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:text="创建直播间并获取推流信息"
|
||||
android:textSize="14sp"
|
||||
app:backgroundTint="#FF4757"
|
||||
app:cornerRadius="24dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:text="使用说明"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#333333"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="1. 填写直播标题并选择分类\n2. 点击按钮创建直播间获取推流信息\n3. 下载并安装OBS Studio\n4. 打开OBS,点击设置 - 推流\n5. 服务选择自定义\n6. 将上方的推流地址和推流码填入\n7. 点击开始推流即可"
|
||||
android:textSize="13sp"
|
||||
android:textColor="#666666"
|
||||
android:lineSpacingExtra="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
@ -12,8 +12,9 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- 封面图片 -->
|
||||
<!-- 封面图片区域 -->
|
||||
<FrameLayout
|
||||
android:id="@+id/coverContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="240dp">
|
||||
|
||||
|
|
@ -49,6 +50,29 @@
|
|||
|
||||
</FrameLayout>
|
||||
|
||||
<!-- 纯文字动态区域(无封面时显示) -->
|
||||
<LinearLayout
|
||||
android:id="@+id/textContentContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="120dp"
|
||||
android:orientation="vertical"
|
||||
android:padding="12dp"
|
||||
android:background="#F8F8F8"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/worksContentText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="15sp"
|
||||
android:textColor="#333333"
|
||||
android:lineSpacingExtra="4dp"
|
||||
android:maxLines="6"
|
||||
android:ellipsize="end" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 作品信息 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user