feat: 全面优化应用稳定性和用户体验
🐛 核心修复: - 修复 VodConfig/LiveConfig 空指针崩溃问题 - 添加构造函数初始化列表,防止 clear() 方法空指针异常 - 增强 Setting 类隐私协议状态管理 🎨 UI/UX 改进: - 新增隐私协议页面 (PrivacyAgreementActivity) - 修复按钮文字显示不完整问题(调整文字大小和按钮高度) - 空状态动画位置优化(向上移动40dp) - TV版选集按钮选中状态文字改为黄色显示 🌟 空状态优化: - 恢复完整的 Lottie 空状态动画 (54KB) - 新增多个空状态布局:搜索、收藏、通用 - 更新空状态文案为川渝方言风格:'这里撒子内容都没得~' 📺 TV版本优化: - 新增专用颜色选择器 episode_text.xml - 选集按钮选中状态文字颜色改为黄色 (#FFEB3B) - 仅影响视频详情页,不干扰其他页面 🔧 技术改进: - 优化生命周期管理和错误处理 - 增强任务栈管理,防止用户返回协议页面 - 添加空值安全检查,提升应用稳定性 版本:v3.0.7 - 包含所有修复和优化的稳定版本
This commit is contained in:
@@ -10,6 +10,13 @@
|
||||
|
||||
<application>
|
||||
|
||||
<activity
|
||||
android:name=".ui.activity.PrivacyAgreementActivity"
|
||||
android:configChanges="screenSize|smallestScreenSize|screenLayout|uiMode|orientation"
|
||||
android:exported="false"
|
||||
android:screenOrientation="fullUser"
|
||||
android:windowSoftInputMode="adjustPan" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.activity.HomeActivity"
|
||||
android:configChanges="screenSize|smallestScreenSize|screenLayout|uiMode|orientation"
|
||||
|
||||
@@ -56,6 +56,7 @@ public class Updater implements Download.Callback {
|
||||
|
||||
public Updater() {
|
||||
this.download = Download.create("", getFile(), this);
|
||||
this.forceCheck = false; // 默认不是用户主动检查更新
|
||||
}
|
||||
|
||||
public Updater force() {
|
||||
@@ -127,14 +128,14 @@ public class Updater implements Download.Callback {
|
||||
String response = OkHttp.string(jsonUrl);
|
||||
Logger.d("Update check response: " + response);
|
||||
|
||||
// 检查响应是否包含错误信息
|
||||
// 检查响应是否包含错误信息,只有在用户主动检查更新时才显示错误提示
|
||||
if (response.contains("rate limit exceeded")) {
|
||||
App.post(() -> Notify.show("检查更新失败:API请求过于频繁,请稍后重试"));
|
||||
showErrorIfForceCheck("检查更新失败:API请求过于频繁,请稍后重试");
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.contains("Not Found Project") || response.contains("Not Found")) {
|
||||
App.post(() -> Notify.show("检查更新失败:更新服务暂时不可用"));
|
||||
showErrorIfForceCheck("检查更新失败:更新服务暂时不可用");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -157,8 +158,10 @@ public class Updater implements Download.Callback {
|
||||
download = Download.create(downloadUrl, getFile(), this);
|
||||
App.post(() -> show(activity, tagName, body));
|
||||
} else if (downloadUrl != null) {
|
||||
// 找到APK但不需要更新,提示已是最新版
|
||||
App.post(() -> Notify.show("已是最新版本 " + tagName));
|
||||
// 找到APK但不需要更新,只在用户主动检查更新时提示已是最新版
|
||||
if (forceCheck) {
|
||||
App.post(() -> Notify.show("已是最新版本 " + tagName));
|
||||
}
|
||||
Logger.d("Already latest version: " + tagName);
|
||||
} else {
|
||||
// 未找到对应的APK文件
|
||||
@@ -171,17 +174,19 @@ public class Updater implements Download.Callback {
|
||||
} catch (Exception e) {
|
||||
Logger.e("Update check failed", e);
|
||||
e.printStackTrace();
|
||||
// 添加用户友好的错误提示
|
||||
// 添加用户友好的错误提示,只有在用户主动检查更新时才显示
|
||||
App.post(() -> {
|
||||
String errorMsg = "检查更新失败";
|
||||
if (e.getMessage() != null && e.getMessage().contains("rate limit")) {
|
||||
errorMsg = "检查更新失败:请求过于频繁,请稍后重试";
|
||||
} else if (e.getMessage() != null && e.getMessage().contains("Not Found")) {
|
||||
errorMsg = "检查更新失败:更新服务暂时不可用";
|
||||
} else {
|
||||
errorMsg = "检查更新失败,请稍后重试";
|
||||
if (forceCheck) { // 只有在用户主动检查更新时才显示错误提示
|
||||
String errorMsg = "检查更新失败";
|
||||
if (e.getMessage() != null && e.getMessage().contains("rate limit")) {
|
||||
errorMsg = "检查更新失败:API请求过于频繁,请稍后重试"; // 统一错误提示文本
|
||||
} else if (e.getMessage() != null && e.getMessage().contains("Not Found")) {
|
||||
errorMsg = "检查更新失败:更新服务暂时不可用";
|
||||
} else {
|
||||
errorMsg = "检查更新失败,请稍后重试";
|
||||
}
|
||||
Notify.show(errorMsg);
|
||||
}
|
||||
Notify.show(errorMsg);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -216,6 +221,16 @@ public class Updater implements Download.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 只有在用户主动检查更新时才显示错误提示
|
||||
* @param message 错误提示消息
|
||||
*/
|
||||
private void showErrorIfForceCheck(String message) {
|
||||
if (forceCheck) {
|
||||
App.post(() -> Notify.show(message));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void progress(int progress) {
|
||||
dialog.getButton(DialogInterface.BUTTON_POSITIVE).setText(String.format(Locale.getDefault(), "%1$d%%", progress));
|
||||
|
||||
@@ -44,6 +44,7 @@ import com.fongmi.android.tv.utils.Util;
|
||||
import com.github.catvod.net.OkHttp;
|
||||
import com.google.android.flexbox.FlexDirection;
|
||||
import com.google.android.flexbox.FlexboxLayoutManager;
|
||||
import com.airbnb.lottie.LottieAnimationView;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
@@ -151,12 +152,14 @@ public class CollectActivity extends BaseActivity implements CustomScroller.Call
|
||||
if (mCollectAdapter.getPosition() == 0) mSearchAdapter.addAll(result.getList());
|
||||
mCollectAdapter.add(Collect.create(result.getList()));
|
||||
mCollectAdapter.add(result.getList());
|
||||
updateEmptyState();
|
||||
});
|
||||
mViewModel.result.observe(this, result -> {
|
||||
boolean same = !result.getList().isEmpty() && mCollectAdapter.getActivated().getSite().equals(result.getList().get(0).getSite());
|
||||
if (same) mCollectAdapter.getActivated().getList().addAll(result.getList());
|
||||
if (same) mSearchAdapter.addAll(result.getList());
|
||||
mScroller.endLoading(result);
|
||||
updateEmptyState();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -187,6 +190,7 @@ public class CollectActivity extends BaseActivity implements CustomScroller.Call
|
||||
mBinding.agent.setVisibility(View.GONE);
|
||||
mBinding.view.setVisibility(View.VISIBLE);
|
||||
mBinding.result.setVisibility(View.VISIBLE);
|
||||
updateEmptyState(); // 搜索开始时显示空状态
|
||||
if (mExecutor != null) mExecutor.shutdownNow();
|
||||
mExecutor = new PauseExecutor(20);
|
||||
String keyword = mBinding.keyword.getText().toString().trim();
|
||||
@@ -194,6 +198,27 @@ public class CollectActivity extends BaseActivity implements CustomScroller.Call
|
||||
App.post(() -> mRecordAdapter.add(keyword), 250);
|
||||
}
|
||||
|
||||
private void updateEmptyState() {
|
||||
// 只有在结果页面可见且搜索结果为空时才显示空状态动画
|
||||
boolean isResultVisible = isVisible(mBinding.result);
|
||||
boolean isEmpty = mSearchAdapter.getItemCount() == 0;
|
||||
boolean shouldShowEmpty = isResultVisible && isEmpty;
|
||||
|
||||
mBinding.emptyLayout.getRoot().setVisibility(shouldShowEmpty ? View.VISIBLE : View.GONE);
|
||||
|
||||
// 控制Lottie动画播放
|
||||
if (shouldShowEmpty) {
|
||||
try {
|
||||
LottieAnimationView lottieView = mBinding.emptyLayout.getRoot().findViewById(R.id.lottieAnimation);
|
||||
if (lottieView != null) {
|
||||
lottieView.playAnimation();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 忽略错误
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void search(Site site, String keyword) {
|
||||
try {
|
||||
mViewModel.searchContent(site, keyword, false);
|
||||
@@ -235,6 +260,7 @@ public class CollectActivity extends BaseActivity implements CustomScroller.Call
|
||||
mBinding.result.setVisibility(View.GONE);
|
||||
mBinding.site.setVisibility(View.VISIBLE);
|
||||
mBinding.agent.setVisibility(View.VISIBLE);
|
||||
mBinding.emptyLayout.getRoot().setVisibility(View.GONE); // 隐藏空状态动画
|
||||
if (mExecutor != null) mExecutor.shutdownNow();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.fongmi.android.tv.ui.adapter.HistoryAdapter;
|
||||
import com.fongmi.android.tv.ui.base.BaseActivity;
|
||||
import com.fongmi.android.tv.ui.dialog.SyncDialog;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.airbnb.lottie.LottieAnimationView;
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
@@ -59,6 +60,25 @@ public class HistoryActivity extends BaseActivity implements HistoryAdapter.OnCl
|
||||
private void getHistory() {
|
||||
mAdapter.addAll(History.get());
|
||||
mBinding.delete.setVisibility(mAdapter.getItemCount() > 0 ? View.VISIBLE : View.GONE);
|
||||
updateEmptyState();
|
||||
}
|
||||
|
||||
private void updateEmptyState() {
|
||||
boolean isEmpty = mAdapter.getItemCount() == 0;
|
||||
mBinding.emptyLayout.getRoot().setVisibility(isEmpty ? View.VISIBLE : View.GONE);
|
||||
mBinding.recycler.setVisibility(isEmpty ? View.GONE : View.VISIBLE);
|
||||
|
||||
// 控制Lottie动画播放
|
||||
if (isEmpty) {
|
||||
try {
|
||||
LottieAnimationView lottieView = mBinding.emptyLayout.getRoot().findViewById(R.id.lottieAnimation);
|
||||
if (lottieView != null) {
|
||||
lottieView.playAnimation();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 忽略错误
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onSync(View view) {
|
||||
@@ -67,7 +87,10 @@ public class HistoryActivity extends BaseActivity implements HistoryAdapter.OnCl
|
||||
|
||||
private void onDelete(View view) {
|
||||
if (mAdapter.isDelete()) {
|
||||
new MaterialAlertDialogBuilder(this).setTitle(R.string.dialog_delete_record).setMessage(R.string.dialog_delete_history).setNegativeButton(R.string.dialog_negative, null).setPositiveButton(R.string.dialog_positive, (dialog, which) -> mAdapter.clear()).show();
|
||||
new MaterialAlertDialogBuilder(this).setTitle(R.string.dialog_delete_record).setMessage(R.string.dialog_delete_history).setNegativeButton(R.string.dialog_negative, null).setPositiveButton(R.string.dialog_positive, (dialog, which) -> {
|
||||
mAdapter.clear();
|
||||
updateEmptyState();
|
||||
}).show();
|
||||
} else if (mAdapter.getItemCount() > 0) {
|
||||
mAdapter.setDelete(true);
|
||||
} else {
|
||||
@@ -91,6 +114,7 @@ public class HistoryActivity extends BaseActivity implements HistoryAdapter.OnCl
|
||||
if (mAdapter.getItemCount() > 0) return;
|
||||
mBinding.delete.setVisibility(View.GONE);
|
||||
mAdapter.setDelete(false);
|
||||
updateEmptyState();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,6 +16,7 @@ import androidx.viewbinding.ViewBinding;
|
||||
|
||||
import com.fongmi.android.tv.App;
|
||||
import com.fongmi.android.tv.R;
|
||||
import com.fongmi.android.tv.Setting;
|
||||
import com.fongmi.android.tv.Updater;
|
||||
import com.fongmi.android.tv.api.config.LiveConfig;
|
||||
import com.fongmi.android.tv.api.config.VodConfig;
|
||||
@@ -62,6 +63,15 @@ public class HomeActivity extends BaseActivity implements NavigationBarView.OnIt
|
||||
|
||||
@Override
|
||||
protected void initView(Bundle savedInstanceState) {
|
||||
// 检查隐私协议
|
||||
if (!Setting.isPrivacyAgreed()) {
|
||||
Intent intent = new Intent(this, PrivacyAgreementActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
orientation = getResources().getConfiguration().orientation;
|
||||
Updater.create().release().start(this);
|
||||
initFragment(savedInstanceState);
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.fongmi.android.tv.ui.base.BaseActivity;
|
||||
import com.fongmi.android.tv.ui.dialog.SyncDialog;
|
||||
import com.fongmi.android.tv.utils.Notify;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.airbnb.lottie.LottieAnimationView;
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
@@ -63,6 +64,25 @@ public class KeepActivity extends BaseActivity implements KeepAdapter.OnClickLis
|
||||
private void getKeep() {
|
||||
mAdapter.addAll(Keep.getVod());
|
||||
mBinding.delete.setVisibility(mAdapter.getItemCount() > 0 ? View.VISIBLE : View.GONE);
|
||||
updateEmptyState();
|
||||
}
|
||||
|
||||
private void updateEmptyState() {
|
||||
boolean isEmpty = mAdapter.getItemCount() == 0;
|
||||
mBinding.emptyLayout.getRoot().setVisibility(isEmpty ? View.VISIBLE : View.GONE);
|
||||
mBinding.recycler.setVisibility(isEmpty ? View.GONE : View.VISIBLE);
|
||||
|
||||
// 控制Lottie动画播放
|
||||
if (isEmpty) {
|
||||
try {
|
||||
LottieAnimationView lottieView = mBinding.emptyLayout.getRoot().findViewById(R.id.lottieAnimation);
|
||||
if (lottieView != null) {
|
||||
lottieView.playAnimation();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 忽略错误
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onSync(View view) {
|
||||
@@ -71,7 +91,10 @@ public class KeepActivity extends BaseActivity implements KeepAdapter.OnClickLis
|
||||
|
||||
private void onDelete(View view) {
|
||||
if (mAdapter.isDelete()) {
|
||||
new MaterialAlertDialogBuilder(this).setTitle(R.string.dialog_delete_record).setMessage(R.string.dialog_delete_keep).setNegativeButton(R.string.dialog_negative, null).setPositiveButton(R.string.dialog_positive, (dialog, which) -> mAdapter.clear()).show();
|
||||
new MaterialAlertDialogBuilder(this).setTitle(R.string.dialog_delete_record).setMessage(R.string.dialog_delete_keep).setNegativeButton(R.string.dialog_negative, null).setPositiveButton(R.string.dialog_positive, (dialog, which) -> {
|
||||
mAdapter.clear();
|
||||
updateEmptyState();
|
||||
}).show();
|
||||
} else if (mAdapter.getItemCount() > 0) {
|
||||
mAdapter.setDelete(true);
|
||||
} else {
|
||||
@@ -114,6 +137,7 @@ public class KeepActivity extends BaseActivity implements KeepAdapter.OnClickLis
|
||||
if (mAdapter.getItemCount() > 0) return;
|
||||
mBinding.delete.setVisibility(View.GONE);
|
||||
mAdapter.setDelete(false);
|
||||
updateEmptyState();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.fongmi.android.tv.ui.activity;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.viewbinding.ViewBinding;
|
||||
|
||||
import com.fongmi.android.tv.R;
|
||||
import com.fongmi.android.tv.Setting;
|
||||
import com.fongmi.android.tv.databinding.ActivityPrivacyAgreementBinding;
|
||||
import com.fongmi.android.tv.ui.base.BaseActivity;
|
||||
|
||||
public class PrivacyAgreementActivity extends BaseActivity {
|
||||
|
||||
private ActivityPrivacyAgreementBinding mBinding;
|
||||
|
||||
@Override
|
||||
protected ViewBinding getBinding() {
|
||||
return mBinding = ActivityPrivacyAgreementBinding.inflate(getLayoutInflater());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initView(Bundle savedInstanceState) {
|
||||
// 隐私协议页面初始化完成
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initEvent() {
|
||||
if (mBinding != null) {
|
||||
if (mBinding.agreeButton != null) {
|
||||
mBinding.agreeButton.setOnClickListener(this::onAgree);
|
||||
}
|
||||
if (mBinding.disagreeButton != null) {
|
||||
mBinding.disagreeButton.setOnClickListener(this::onDisagree);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onAgree(View view) {
|
||||
// 用户同意协议
|
||||
Setting.setPrivacyAgreed(true);
|
||||
|
||||
// 跳转到主界面,清除任务栈避免用户通过任务管理器回到协议页面
|
||||
Intent intent = new Intent(this, HomeActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
|
||||
private void onDisagree(View view) {
|
||||
// 用户不同意协议,退出应用
|
||||
try {
|
||||
// 清除隐私协议状态(可选,确保下次启动重新询问)
|
||||
Setting.setPrivacyAgreed(false);
|
||||
|
||||
// 优雅地退出应用
|
||||
finishAffinity();
|
||||
|
||||
// 延迟退出,让 Activity 完成销毁
|
||||
new android.os.Handler(android.os.Looper.getMainLooper()).postDelayed(() -> {
|
||||
System.exit(0);
|
||||
}, 100);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
// 备选退出方案
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
// 禁用返回键,用户必须做出选择
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
onDisagree(null);
|
||||
return true;
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
// 清理 binding 引用
|
||||
mBinding = null;
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ import com.fongmi.android.tv.ui.activity.CollectActivity;
|
||||
import com.fongmi.android.tv.ui.activity.HistoryActivity;
|
||||
import com.fongmi.android.tv.ui.activity.KeepActivity;
|
||||
import com.fongmi.android.tv.ui.activity.VideoActivity;
|
||||
import com.airbnb.lottie.LottieAnimationView;
|
||||
import com.fongmi.android.tv.ui.adapter.TypeAdapter;
|
||||
import com.fongmi.android.tv.ui.base.BaseFragment;
|
||||
import com.fongmi.android.tv.ui.dialog.ConfigDialog;
|
||||
@@ -265,6 +266,15 @@ public class VodFragment extends BaseFragment implements SiteCallback, FilterCal
|
||||
}
|
||||
// 空源状态下隐藏所有悬浮按钮
|
||||
hideFabButtons();
|
||||
// 启动Lottie动画
|
||||
try {
|
||||
LottieAnimationView lottieView = mBinding.emptySourceHint.findViewById(R.id.lottieAnimation);
|
||||
if (lottieView != null) {
|
||||
lottieView.playAnimation();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 忽略错误
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,5 +154,15 @@
|
||||
app:spanCount="2"
|
||||
tools:listitem="@layout/adapter_vod_rect" />
|
||||
|
||||
<!-- 搜索结果空状态Lottie动画 -->
|
||||
<include
|
||||
android:id="@+id/emptyLayout"
|
||||
layout="@layout/view_empty_search"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_marginTop="-40dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
@@ -65,5 +65,15 @@
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="8dp" />
|
||||
|
||||
<!-- 空状态Lottie动画 -->
|
||||
<include
|
||||
android:id="@+id/emptyLayout"
|
||||
layout="@layout/view_empty_lottie"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="-40dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
@@ -65,5 +65,14 @@
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="8dp" />
|
||||
|
||||
<include
|
||||
android:id="@+id/emptyLayout"
|
||||
layout="@layout/view_empty_keep"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="-40dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
@@ -112,11 +112,13 @@
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:src="@drawable/ic_logo" />
|
||||
<com.airbnb.lottie.LottieAnimationView
|
||||
android:id="@+id/lottieAnimation"
|
||||
android:layout_width="180dp"
|
||||
android:layout_height="180dp"
|
||||
app:lottie_fileName="lottie_empty_1.json"
|
||||
app:lottie_loop="true"
|
||||
app:lottie_autoPlay="true" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
@@ -124,16 +126,17 @@
|
||||
android:gravity="center"
|
||||
android:text="@string/source_hint"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp" />
|
||||
android:textSize="14sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/add_source_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:backgroundTint="@color/primary"
|
||||
android:text="@string/add_source"
|
||||
android:textColor="@color/black" />
|
||||
android:textColor="@color/black"
|
||||
android:textSize="16sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
|
||||
Reference in New Issue
Block a user