Compare commits
28 Commits
powerbell-
...
powerbell-
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b69e04706 | |||
| a2a61bbf0b | |||
| 9f4211c83e | |||
| 447a786632 | |||
| ff0f239ffc | |||
| 7c59a982fc | |||
| 895cc4630d | |||
| 851a539364 | |||
| d79f2937ba | |||
| c524a21429 | |||
| a148de2ab8 | |||
| de34e823b6 | |||
| fd0833476e | |||
| 361b533b0d | |||
| f277f76468 | |||
| ec54865a8e | |||
| 6b3682994e | |||
| 7145bff552 | |||
| 4c3b60128f | |||
| 29d30f3831 | |||
| c7b0b1bc80 | |||
| 9082b67bbd | |||
| 2b5447e65f | |||
| 6a5c2dbbe8 | |||
| 8cad25bb11 | |||
| e440943992 | |||
| 7c5f8c3cc2 | |||
| 016b3b5e48 |
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Sun Dec 07 15:19:14 HKT 2025
|
||||
stageCount=2
|
||||
#Thu Dec 11 03:04:35 HKT 2025
|
||||
stageCount=14
|
||||
libraryProject=
|
||||
baseVersion=15.12
|
||||
publishVersion=15.12.1
|
||||
publishVersion=15.12.13
|
||||
buildCount=0
|
||||
baseBetaVersion=15.12.2
|
||||
baseBetaVersion=15.12.14
|
||||
|
||||
@@ -2,28 +2,36 @@ package cc.winboll.studio.powerbell;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import cc.winboll.studio.libaes.utils.WinBoLLActivityManager;
|
||||
import cc.winboll.studio.libappbase.GlobalApplication;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.ToastUtils;
|
||||
import cc.winboll.studio.powerbell.model.BackgroundBean;
|
||||
import cc.winboll.studio.powerbell.receivers.GlobalApplicationReceiver;
|
||||
import cc.winboll.studio.powerbell.utils.AppCacheUtils;
|
||||
import cc.winboll.studio.powerbell.utils.AppConfigUtils;
|
||||
import cc.winboll.studio.powerbell.utils.BackgroundSourceUtils;
|
||||
import cc.winboll.studio.powerbell.utils.BitmapCacheUtils;
|
||||
import java.io.File;
|
||||
|
||||
public class App extends GlobalApplication {
|
||||
|
||||
public static final String TAG = "App";
|
||||
|
||||
public static final String COMPONENT_EN1 = "cc.winboll.studio.powerbell.MainActivityEN1";
|
||||
public static final String COMPONENT_CN1 = "cc.winboll.studio.powerbell.MainActivityCN1";
|
||||
public static final String COMPONENT_CN2 = "cc.winboll.studio.powerbell.MainActivityCN2";
|
||||
public static final String ACTION_SWITCHTO_EN1 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_EN1";
|
||||
public static final String ACTION_SWITCHTO_CN1 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_CN1";
|
||||
public static final String ACTION_SWITCHTO_CN2 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_CN2";
|
||||
public static final String COMPONENT_EN1 = "cc.winboll.studio.powerbell.MainActivityEN1";
|
||||
public static final String COMPONENT_CN1 = "cc.winboll.studio.powerbell.MainActivityCN1";
|
||||
public static final String COMPONENT_CN2 = "cc.winboll.studio.powerbell.MainActivityCN2";
|
||||
public static final String ACTION_SWITCHTO_EN1 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_EN1";
|
||||
public static final String ACTION_SWITCHTO_CN1 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_CN1";
|
||||
public static final String ACTION_SWITCHTO_CN2 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_CN2";
|
||||
|
||||
// 数据配置存储工具
|
||||
static AppConfigUtils _mAppConfigUtils;
|
||||
static AppCacheUtils _mAppCacheUtils;
|
||||
// 新增:全局 Bitmap 缓存工具(常驻内存)
|
||||
public static BitmapCacheUtils _mBitmapCacheUtils;
|
||||
|
||||
GlobalApplicationReceiver mReceiver;
|
||||
static String szTempDir = "";
|
||||
|
||||
@@ -34,25 +42,16 @@ public class App extends GlobalApplication {
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
setIsDebugging(BuildConfig.DEBUG);
|
||||
//setIsDebugging(false);
|
||||
setIsDebugging(BuildConfig.DEBUG);
|
||||
|
||||
// 初始化活动窗口管理
|
||||
WinBoLLActivityManager.init(this);
|
||||
// 初始化活动窗口管理
|
||||
WinBoLLActivityManager.init(this);
|
||||
// 初始化 Toast 框架
|
||||
ToastUtils.init(this);
|
||||
|
||||
// 临时文件夹方案1
|
||||
// 获取Pictures文件夹路径(Android 10及以上推荐使用MediaStore,此处为传统方式)
|
||||
|
||||
// 临时文件夹初始化(保持原有逻辑)
|
||||
File picturesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
|
||||
// 定义目标文件路径(在Pictures目录下创建"PowerBell"子文件夹及文件)
|
||||
File powerBellDir = new File(picturesDir, "PowerBell");
|
||||
|
||||
// 临时文件夹方案2 <图片保存失败>
|
||||
// 获取Pictures文件夹路径(Android 10及以上推荐使用MediaStore,此处为传统方式)
|
||||
//File powerBellDir = getExternalFilesDir("TempDir");
|
||||
|
||||
// 先创建文件夹(如果不存在)
|
||||
if (!powerBellDir.exists()) {
|
||||
powerBellDir.mkdirs();
|
||||
}
|
||||
@@ -61,11 +60,54 @@ public class App extends GlobalApplication {
|
||||
// 设置数据配置存储工具
|
||||
_mAppConfigUtils = getAppConfigUtils(this);
|
||||
_mAppCacheUtils = getAppCacheUtils(this);
|
||||
// 初始化全局 Bitmap 缓存工具(关键:App 启动时初始化,常驻内存)
|
||||
_mBitmapCacheUtils = BitmapCacheUtils.getInstance();
|
||||
|
||||
mReceiver = new GlobalApplicationReceiver(this);
|
||||
mReceiver.registerAction();
|
||||
|
||||
// ======================== 新增:异步预加载背景图 ========================
|
||||
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
// 1. 获取背景源工具类实例
|
||||
BackgroundSourceUtils bgSourceUtils = BackgroundSourceUtils.getInstance(App.this);
|
||||
if (bgSourceUtils == null) {
|
||||
LogUtils.e(TAG, "preloadBitmap: BackgroundSourceUtils 实例为空");
|
||||
return;
|
||||
}
|
||||
// 2. 获取当前背景Bean
|
||||
BackgroundBean bgBean = bgSourceUtils.getCurrentBackgroundBean();
|
||||
if (bgBean == null || !bgBean.isUseBackgroundFile()) {
|
||||
LogUtils.d(TAG, "preloadBitmap: 无有效背景文件,跳过预加载");
|
||||
return;
|
||||
}
|
||||
// 3. 获取背景图路径(优先取压缩图路径)
|
||||
String bgPath = bgBean.isUseBackgroundScaledCompressFile()
|
||||
? bgBean.getBackgroundScaledCompressFilePath()
|
||||
: bgBean.getBackgroundFilePath();
|
||||
// 4. 预加载到全局缓存
|
||||
if (_mBitmapCacheUtils != null) {
|
||||
_mBitmapCacheUtils.cacheBitmap(bgPath);
|
||||
LogUtils.d(TAG, "preloadBitmap: 应用启动时预加载成功 - " + bgPath);
|
||||
} else {
|
||||
LogUtils.e(TAG, "preloadBitmap: 全局 BitmapCacheUtils 未初始化");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "preloadBitmap: 预加载失败 - " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}, 1000); // 延迟1秒执行,避免阻塞应用初始化
|
||||
// ======================== 预加载逻辑结束 ========================
|
||||
}
|
||||
|
||||
// 保持原有方法不变
|
||||
public static AppConfigUtils getAppConfigUtils(Context context) {
|
||||
if (_mAppConfigUtils == null) {
|
||||
_mAppConfigUtils = AppConfigUtils.getInstance(context);
|
||||
@@ -84,12 +126,14 @@ public class App extends GlobalApplication {
|
||||
_mAppCacheUtils.clearBatteryHistory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTerminate() {
|
||||
super.onTerminate();
|
||||
ToastUtils.release();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onTerminate() {
|
||||
super.onTerminate();
|
||||
ToastUtils.release();
|
||||
// 可选:App 终止时清空 Bitmap 缓存,释放内存
|
||||
if (_mBitmapCacheUtils != null) {
|
||||
_mBitmapCacheUtils.clearAllCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,7 @@ import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.CompressFormat;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
@@ -14,6 +15,7 @@ import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.provider.MediaStore;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Toast;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.FileProvider;
|
||||
@@ -35,6 +37,8 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import cc.winboll.studio.powerbell.utils.UriUtil;
|
||||
import cc.winboll.studio.powerbell.utils.FileUtils;
|
||||
|
||||
public class BackgroundSettingsActivity extends WinBoLLActivity implements BackgroundPicturePreviewDialog.IOnRecivedPictureListener {
|
||||
|
||||
@@ -50,6 +54,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
|
||||
private BackgroundView mBackgroundView;
|
||||
private File mfTakePhoto;
|
||||
volatile boolean isCommitSettings = false;
|
||||
volatile boolean isPreviewBackgroundChanged = false;
|
||||
|
||||
@Override
|
||||
public Activity getActivity() {
|
||||
@@ -68,6 +73,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
|
||||
|
||||
mBackgroundView = (BackgroundView) findViewById(R.id.background_view);
|
||||
mBgSourceUtils = BackgroundSourceUtils.getInstance(this);
|
||||
mBgSourceUtils.loadSettings();
|
||||
mPermissionUtils = PermissionUtils.getInstance();
|
||||
|
||||
File tempDir = new File(App.getTempDirPath());
|
||||
@@ -84,25 +90,32 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
|
||||
|
||||
initToolbar();
|
||||
initClickListeners();
|
||||
initBackgroundViewByPreviewBean();
|
||||
handleShareIntent();
|
||||
|
||||
if (handleShareIntent()) {
|
||||
ToastUtils.show("handleShareIntent");
|
||||
} else {
|
||||
mBgSourceUtils.setCurrentSourceToPreview();
|
||||
}
|
||||
|
||||
Uri uriSelectedImage = UriUtil.getUriForFile(this, new File(mBgSourceUtils.getPreviewBackgroundBean().getBackgroundFilePath()));
|
||||
// 创建预览数据剪裁环境
|
||||
mBgSourceUtils.createAndUpdatePreviewEnvironmentForCropping(mBgSourceUtils.getPreviewBackgroundBean());
|
||||
doubleRefreshPreview();
|
||||
LogUtils.d(TAG, "【初始化】BackgroundSettingsActivity 初始化完成");
|
||||
}
|
||||
|
||||
private void initBackgroundViewByPreviewBean() {
|
||||
LogUtils.d(TAG, "【Bean初始化】正式Bean → 预览Bean");
|
||||
mBgSourceUtils.setCurrentSourceToPreview();
|
||||
@Override
|
||||
protected void onPostCreate(Bundle savedInstanceState) {
|
||||
super.onPostCreate(savedInstanceState);
|
||||
doubleRefreshPreview();
|
||||
LogUtils.d(TAG, "【Bean初始化】预览Bean初始化完成");
|
||||
}
|
||||
|
||||
private void initToolbar() {
|
||||
mToolbar = findViewById(R.id.toolbar);
|
||||
mToolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(mToolbar);
|
||||
mToolbar.setSubtitle(getTag());
|
||||
mToolbar.setSubtitle(getTag());
|
||||
mToolbar.setTitleTextAppearance(this, R.style.Toolbar_TitleText);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@@ -123,7 +136,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
|
||||
findViewById(R.id.activitybackgroundpictureAButton8).setOnClickListener(onCleanPixelClickListener);
|
||||
}
|
||||
|
||||
private void handleShareIntent() {
|
||||
private boolean handleShareIntent() {
|
||||
Intent intent = getIntent();
|
||||
if (intent != null) {
|
||||
String action = intent.getAction();
|
||||
@@ -132,8 +145,10 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
|
||||
BackgroundPicturePreviewDialog dlg = new BackgroundPicturePreviewDialog(this);
|
||||
dlg.show();
|
||||
LogUtils.d(TAG, "【分享处理】收到分享图片意图");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isImageType(String lowerMimeType) {
|
||||
@@ -242,8 +257,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
|
||||
mBackgroundView.getWidth(),
|
||||
mBackgroundView.getHeight(),
|
||||
false,
|
||||
REQUEST_CROP_IMAGE
|
||||
);
|
||||
REQUEST_CROP_IMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -257,8 +271,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
|
||||
0,
|
||||
0,
|
||||
true,
|
||||
REQUEST_CROP_IMAGE
|
||||
);
|
||||
REQUEST_CROP_IMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -416,8 +429,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
|
||||
mBackgroundView.getWidth(),
|
||||
mBackgroundView.getHeight(),
|
||||
false,
|
||||
REQUEST_CROP_IMAGE
|
||||
);
|
||||
REQUEST_CROP_IMAGE);
|
||||
LogUtils.d(TAG, "【拍照完成】已启动裁剪");
|
||||
}
|
||||
|
||||
@@ -457,41 +469,52 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
|
||||
return null;
|
||||
}
|
||||
|
||||
private void handleSelectPictureResult(int resultCode, Intent data) {
|
||||
if (resultCode != RESULT_OK || data == null) {
|
||||
handleOperationCancelOrFail();
|
||||
return;
|
||||
}
|
||||
private void handleSelectPictureResult(int resultCode, Intent data) {
|
||||
if (resultCode != RESULT_OK || data == null) {
|
||||
handleOperationCancelOrFail();
|
||||
return;
|
||||
}
|
||||
|
||||
Uri selectedImage = data.getData();
|
||||
if (selectedImage == null) {
|
||||
ToastUtils.show("图片Uri为空");
|
||||
return;
|
||||
}
|
||||
LogUtils.d(TAG, "【选图回调】Uri : " + selectedImage.toString());
|
||||
Uri selectedImage = data.getData();
|
||||
if (selectedImage == null) {
|
||||
ToastUtils.show("图片Uri为空");
|
||||
return;
|
||||
}
|
||||
LogUtils.d(TAG, "【选图回调】Uri : " + selectedImage.toString());
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
getContentResolver().takePersistableUriPermission(
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
getContentResolver().takePersistableUriPermission(
|
||||
selectedImage,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
);
|
||||
LogUtils.d(TAG, "【选图权限】已添加持久化权限");
|
||||
}
|
||||
);
|
||||
LogUtils.d(TAG, "【选图权限】已添加持久化权限");
|
||||
}
|
||||
|
||||
mBgSourceUtils.createCropFileProviderBackgroundBean(selectedImage);
|
||||
|
||||
LogUtils.d(TAG, "【选图同步】路径绑定完成");
|
||||
// 选图后启动固定比例裁剪(调用工具类)
|
||||
mBgSourceUtils.loadSettings();
|
||||
ImageCropUtils.startImageCrop(BackgroundSettingsActivity.this,
|
||||
LogUtils.d(TAG, "【选图同步】路径绑定完成");
|
||||
// 选图后启动固定比例裁剪(调用工具类)
|
||||
putUriFileToPreviewSource(selectedImage);
|
||||
ImageCropUtils.startImageCrop(BackgroundSettingsActivity.this,
|
||||
mBgSourceUtils.getPreviewBackgroundBean(),
|
||||
mBackgroundView.getWidth(),
|
||||
mBackgroundView.getHeight(),
|
||||
false,
|
||||
REQUEST_CROP_IMAGE
|
||||
);
|
||||
}
|
||||
REQUEST_CROP_IMAGE);
|
||||
}
|
||||
|
||||
boolean putUriFileToPreviewSource(Uri srcUriFile) {
|
||||
File srcFile = new File(UriUtil.getFilePathFromUri(this, srcUriFile));
|
||||
return putUriFileToPreviewSource(srcFile);
|
||||
}
|
||||
|
||||
boolean putUriFileToPreviewSource(File srcFile) {
|
||||
mBgSourceUtils.loadSettings();
|
||||
File dstFile = new File(mBgSourceUtils.getPreviewBackgroundBean().getBackgroundFilePath());
|
||||
return FileUtils.copyFile(srcFile, dstFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心修改:裁剪成功后调用双重刷新,确保最新图片加载
|
||||
*/
|
||||
private void handleCropImageResult(int requestCode, int resultCode, Intent data) {
|
||||
LogUtils.d(TAG, "handleCropImageResult: 处理裁剪结果");
|
||||
File cropTempFile = new File(mBgSourceUtils.getPreviewBackgroundBean().getBackgroundScaledCompressFilePath());
|
||||
@@ -501,8 +524,9 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
|
||||
boolean isCropSuccess = (resultCode == RESULT_OK) && isFileExist && isFileReadable && fileSize > 100;
|
||||
|
||||
if (isCropSuccess) {
|
||||
isPreviewBackgroundChanged = true;
|
||||
LogUtils.d(TAG, "handleCropImageResult: 裁剪成功");
|
||||
BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
|
||||
final BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
|
||||
previewBean.setIsUseBackgroundFile(true);
|
||||
previewBean.setIsUseBackgroundScaledCompressFile(true);
|
||||
mBgSourceUtils.saveSettings();
|
||||
@@ -523,15 +547,16 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
|
||||
}
|
||||
}
|
||||
|
||||
// 关键修改:延迟300ms调用双重刷新,确保文件写入完成
|
||||
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mBackgroundView != null && !isFinishing()) {
|
||||
mBackgroundView.loadBackgroundBean(mBgSourceUtils.getPreviewBackgroundBean());
|
||||
LogUtils.d(TAG, "handleCropImageResult: 裁剪图片加载完成");
|
||||
if (!isFinishing()) {
|
||||
doubleRefreshPreview();
|
||||
LogUtils.d(TAG, "handleCropImageResult: 触发双重刷新");
|
||||
}
|
||||
}
|
||||
}, 50);
|
||||
}, 300);
|
||||
} else {
|
||||
handleOperationCancelOrFail();
|
||||
}
|
||||
@@ -674,9 +699,42 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
|
||||
return cropBitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心修改:添加缓存清理 + 控件 Bitmap 清空逻辑
|
||||
*/
|
||||
private void doubleRefreshPreview() {
|
||||
LogUtils.d(TAG, "【双重刷新】开始");
|
||||
// 1. 清空缓存工具类的旧数据
|
||||
if (mBgSourceUtils != null) {
|
||||
BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
|
||||
if (previewBean != null && previewBean.isUseBackgroundFile()) {
|
||||
String bgPath = previewBean.isUseBackgroundScaledCompressFile()
|
||||
? previewBean.getBackgroundScaledCompressFilePath()
|
||||
: previewBean.getBackgroundFilePath();
|
||||
// 强制清除缓存
|
||||
App._mBitmapCacheUtils.removeCachedBitmap(bgPath);
|
||||
LogUtils.d(TAG, "【双重刷新】已清空工具类缓存:" + bgPath);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 清空 BackgroundView 自身的 Bitmap 引用
|
||||
// if (mBackgroundView != null) {
|
||||
// // 清空 ImageView 持有的 Bitmap
|
||||
// if (mBackgroundView instanceof BackgroundView) {
|
||||
// ((BackgroundView) mBackgroundView).setImageBitmap(null);
|
||||
// }
|
||||
// // 清空背景 Drawable 引用
|
||||
// Drawable drawable = mBackgroundView.getBackground();
|
||||
// if (drawable != null) {
|
||||
// drawable.setCallback(null);
|
||||
// mBackgroundView.setBackground(null);
|
||||
// }
|
||||
// LogUtils.d(TAG, "【双重刷新】已清空控件 Bitmap 引用");
|
||||
// }
|
||||
|
||||
// 3. 重新加载最新数据
|
||||
if (mBackgroundView != null && !isFinishing()) {
|
||||
mBgSourceUtils.loadSettings();
|
||||
mBackgroundView.loadBackgroundBean(mBgSourceUtils.getPreviewBackgroundBean());
|
||||
LogUtils.d(TAG, "【双重刷新】第一重完成");
|
||||
} else {
|
||||
@@ -684,52 +742,34 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. 延长延迟到200ms,确保文件完全加载
|
||||
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mBackgroundView != null && !isFinishing()) {
|
||||
mBgSourceUtils.loadSettings();
|
||||
mBackgroundView.loadBackgroundBean(mBgSourceUtils.getPreviewBackgroundBean());
|
||||
LogUtils.d(TAG, "【双重刷新】第二重完成");
|
||||
}
|
||||
}
|
||||
}, 50);
|
||||
}, 200);
|
||||
}
|
||||
|
||||
|
||||
private void handleOperationCancelOrFail() {
|
||||
initBackgroundViewByPreviewBean();
|
||||
mBgSourceUtils.setCurrentSourceToPreview();
|
||||
LogUtils.d(TAG, "【操作回调】取消或失败");
|
||||
ToastUtils.show("操作已取消");
|
||||
ToastUtils.show("【操作回调】取消或失败");
|
||||
doubleRefreshPreview();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 启动系统裁剪工具
|
||||
* @param activity 上下文
|
||||
* @param srcFile 裁剪原图
|
||||
* @param aspectX 裁剪宽比例(自由裁剪传0)
|
||||
* @param aspectY 裁剪高比例(自由裁剪传0)
|
||||
* @param isFreeCrop 是否自由裁剪
|
||||
* @param requestCode 裁剪请求码
|
||||
*/
|
||||
/**
|
||||
* 启动系统裁剪工具
|
||||
* @param activity 上下文
|
||||
* @param srcFile 裁剪原图
|
||||
* @param aspectX 裁剪宽比例(自由裁剪传0)
|
||||
* @param aspectY 裁剪高比例(自由裁剪传0)
|
||||
* @param isFreeCrop 是否自由裁剪
|
||||
* @param requestCode 裁剪请求码
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* 获取FileProvider Uri(复用方法,避免重复代码)
|
||||
*/
|
||||
public Uri getFileProviderUri(File file) {
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
String FILE_PROVIDER_AUTHORITY = getPackageName() + ".fileprovider";
|
||||
String FILE_PROVIDER_AUTHORITY = getPackageName() + ".fileprovider";
|
||||
|
||||
return FileProvider.getUriForFile(this, FILE_PROVIDER_AUTHORITY, file);
|
||||
} else {
|
||||
@@ -753,20 +793,27 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
|
||||
if (isCommitSettings) {
|
||||
super.finish();
|
||||
} else {
|
||||
YesNoAlertDialog.show(this, "背景更换问题", "是否确定背景图片设置?", new YesNoAlertDialog.OnDialogResultListener(){
|
||||
@Override
|
||||
public void onYes() {
|
||||
mBgSourceUtils.commitPreviewSourceToCurrent();
|
||||
isCommitSettings = true;
|
||||
finish();
|
||||
}
|
||||
// 如果预览背景改变过就提示是否更换背景
|
||||
if (isPreviewBackgroundChanged) {
|
||||
YesNoAlertDialog.show(this, "背景更换问题", "是否确定背景图片设置?", new YesNoAlertDialog.OnDialogResultListener() {
|
||||
@Override
|
||||
public void onYes() {
|
||||
mBgSourceUtils.commitPreviewSourceToCurrent();
|
||||
isCommitSettings = true;
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNo() {
|
||||
isCommitSettings = true;
|
||||
finish();
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void onNo() {
|
||||
isCommitSettings = true;
|
||||
finish();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 如果预览背景未改变就直接退出
|
||||
isCommitSettings = true;
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,333 +33,8 @@ public class MainViewFragment extends Fragment {
|
||||
|
||||
public static final String TAG = "MainViewFragment";
|
||||
|
||||
public static final int MSG_RELOAD_APPCONFIG = 0;
|
||||
public static final int MSG_CURRENTVALUEBATTERY = 1;
|
||||
|
||||
static MainViewFragment _mMainViewFragment;
|
||||
AppConfigUtils mAppConfigUtils;
|
||||
View mView;
|
||||
Drawable mDrawableFrame;
|
||||
LinearLayout mllLeftSeekBar;
|
||||
LinearLayout mllRightSeekBar;
|
||||
CheckBox mcbIsEnableChargeReminder;
|
||||
CheckBox mcbIsEnableUsegeReminder;
|
||||
Switch mswIsEnableService;
|
||||
TextView mtvTips;
|
||||
|
||||
private BackgroundSourceUtils mBgSourceUtils;
|
||||
|
||||
// 背景布局
|
||||
//LinearLayout mLinearLayoutloadBackground;
|
||||
|
||||
// 现在电量图示
|
||||
BatteryDrawable mCurrentValueBatteryDrawable;
|
||||
// 现在充电提醒电量图示
|
||||
BatteryDrawable mChargeReminderValueBatteryDrawable;
|
||||
// 现在耗电提醒电量图示
|
||||
BatteryDrawable mUsegeReminderValueBatteryDrawable;
|
||||
|
||||
ImageView mCurrentValueBatteryImageView;
|
||||
ImageView mChargeReminderValueBatteryImageView;
|
||||
ImageView mUsegeReminderValueBatteryImageView;
|
||||
|
||||
VerticalSeekBar mChargeReminderSeekBar;
|
||||
ChargeReminderSeekBarChangeListener mChargeReminderSeekBarChangeListener;
|
||||
TextView mtvChargeReminderValue;
|
||||
|
||||
|
||||
VerticalSeekBar mUsegeReminderSeekBar;
|
||||
UsegeReminderSeekBarChangeListener mUsegeReminderSeekBarChangeListener;
|
||||
TextView mtvUsegeReminderValue;
|
||||
CheckBox mcbUsegeReminderValue;
|
||||
TextView mtvCurrentValue;
|
||||
BackgroundView mBackgroundView;
|
||||
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
mView = inflater.inflate(R.layout.fragment_mainview, container, false);
|
||||
_mMainViewFragment = MainViewFragment.this;
|
||||
mAppConfigUtils = App.getAppConfigUtils(getActivity());
|
||||
mBgSourceUtils = BackgroundSourceUtils.getInstance(getActivity());
|
||||
// 获取指定ID的View实例
|
||||
mBackgroundView = mView.findViewById(R.id.fragmentmainviewBackgroundView1);
|
||||
|
||||
loadBackground();
|
||||
/*final View mainImageView = mView.findViewById(R.id.fragmentmainviewImageView1);
|
||||
|
||||
// 注册OnGlobalLayoutListener
|
||||
mainImageView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
// 获取宽度和高度
|
||||
int width = mainImageView.getMeasuredWidth();
|
||||
int height = mainImageView.getMeasuredHeight();
|
||||
|
||||
BackgroundPictureUtils utils = BackgroundPictureUtils.getInstance(getActivity());
|
||||
BackgroundPictureBean bean = utils.loadBackgroundPictureBean();
|
||||
bean.setBackgroundWidth(width);
|
||||
bean.setBackgroundHeight(height);
|
||||
utils.saveData();
|
||||
// 移除监听器以避免内存泄漏
|
||||
mainImageView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
}
|
||||
});*/
|
||||
|
||||
mDrawableFrame = getActivity().getDrawable(R.drawable.bg_frame);
|
||||
mllLeftSeekBar = (LinearLayout) mView.findViewById(R.id.fragmentmainviewLinearLayout1);
|
||||
mllRightSeekBar = (LinearLayout) mView.findViewById(R.id.fragmentmainviewLinearLayout2);
|
||||
|
||||
// 初始化充电电量提醒设置控件
|
||||
mtvChargeReminderValue = (TextView) mView.findViewById(R.id.fragmentandroidviewTextView2);
|
||||
mChargeReminderSeekBar = (VerticalSeekBar) mView.findViewById(R.id.fragmentandroidviewVerticalSeekBar1);
|
||||
mcbIsEnableChargeReminder = mView.findViewById(R.id.fragmentmainviewCheckBox1);
|
||||
|
||||
// 初始化耗电电量提醒设置控件
|
||||
mtvUsegeReminderValue = (TextView) mView.findViewById(R.id.fragmentandroidviewTextView3);
|
||||
mUsegeReminderSeekBar = (VerticalSeekBar) mView.findViewById(R.id.fragmentandroidviewVerticalSeekBar2);
|
||||
mcbIsEnableUsegeReminder = mView.findViewById(R.id.fragmentmainviewCheckBox2);
|
||||
|
||||
// 初始化现在电量显示控件
|
||||
mtvCurrentValue = (TextView) mView.findViewById(R.id.fragmentandroidviewTextView4);
|
||||
|
||||
// 初始化服务总开关
|
||||
mswIsEnableService = (Switch) mView.findViewById(R.id.fragmentandroidviewSwitch1);
|
||||
mtvTips = mView.findViewById(R.id.fragmentandroidviewTextView1);
|
||||
|
||||
// 设置视图显示数据
|
||||
setViewData();
|
||||
// 设置视图控件响应
|
||||
setViewListener();
|
||||
|
||||
// 注册一个广播接收
|
||||
//mMainActivityReceiver = new MainActivityReceiver(this);
|
||||
//mMainActivityReceiver.registerAction();
|
||||
|
||||
// 启动的时候检查一下服务
|
||||
if (mAppConfigUtils.getIsEnableService()
|
||||
&& ServiceUtils.isServiceAlive(getActivity(), ControlCenterService.class.getName()) == false) {
|
||||
// 如果配置了服务启动,服务没有启动
|
||||
// 就启动服务
|
||||
Intent intent = new Intent(getActivity(), ControlCenterService.class);
|
||||
getActivity().startForegroundService(intent);
|
||||
}
|
||||
|
||||
return mView;
|
||||
}
|
||||
|
||||
void loadBackground() {
|
||||
BackgroundBean bean = mBgSourceUtils.getCurrentBackgroundBean();
|
||||
mBackgroundView.loadBackgroundBean(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
loadBackground();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setViewData() {
|
||||
int nChargeReminderValue = mAppConfigUtils.getChargeReminderValue();
|
||||
int nUsegeReminderValue = mAppConfigUtils.getUsegeReminderValue();
|
||||
int nCurrentValue = mAppConfigUtils.getCurrentValue();
|
||||
|
||||
mllLeftSeekBar.setBackground(mDrawableFrame);
|
||||
mllRightSeekBar.setBackground(mDrawableFrame);
|
||||
|
||||
// 初始化电量图
|
||||
mCurrentValueBatteryDrawable = new BatteryDrawable(getActivity().getColor(R.color.colorCurrent));
|
||||
mCurrentValueBatteryDrawable.setValue(mAppConfigUtils.getCurrentValue());
|
||||
mCurrentValueBatteryImageView = mView.findViewById(R.id.fragmentandroidviewImageView1);
|
||||
mCurrentValueBatteryImageView.setImageDrawable(mCurrentValueBatteryDrawable);
|
||||
|
||||
// 初始化充电电量提醒图
|
||||
mChargeReminderValueBatteryDrawable = new BatteryDrawable(getActivity().getColor(R.color.colorCharge));
|
||||
mChargeReminderValueBatteryDrawable.setValue(nChargeReminderValue);
|
||||
mChargeReminderValueBatteryImageView = mView.findViewById(R.id.fragmentandroidviewImageView3);
|
||||
mChargeReminderValueBatteryImageView.setImageDrawable(mChargeReminderValueBatteryDrawable);
|
||||
|
||||
// 初始化耗电电量提醒图
|
||||
mUsegeReminderValueBatteryDrawable = new BatteryDrawable(getActivity().getColor(R.color.colorUsege));
|
||||
mUsegeReminderValueBatteryDrawable.setValue(nUsegeReminderValue);
|
||||
mUsegeReminderValueBatteryImageView = mView.findViewById(R.id.fragmentandroidviewImageView2);
|
||||
mUsegeReminderValueBatteryImageView.setImageDrawable(mUsegeReminderValueBatteryDrawable);
|
||||
|
||||
// 初始化充电电量提醒设置控件
|
||||
mtvChargeReminderValue.setTextColor(getActivity().getColor(R.color.colorCharge));
|
||||
//LogUtils.d(TAG, "Color.YELLOW is " + Integer.toString(mApplication.getColor(R.color.colorCharge)));
|
||||
mtvChargeReminderValue.setText(Integer.toString(nChargeReminderValue) + "%");
|
||||
mChargeReminderSeekBar.setProgress(nChargeReminderValue);
|
||||
mcbIsEnableChargeReminder.setChecked(mAppConfigUtils.getIsEnableChargeReminder());
|
||||
|
||||
// 初始化耗电电量提醒设置控件
|
||||
mtvUsegeReminderValue.setTextColor(getActivity().getColor(R.color.colorUsege));
|
||||
mtvUsegeReminderValue.setText(Integer.toString(nUsegeReminderValue) + "%");
|
||||
mUsegeReminderSeekBar.setProgress(nUsegeReminderValue);
|
||||
mcbIsEnableUsegeReminder.setChecked(mAppConfigUtils.getIsEnableUsegeReminder());
|
||||
|
||||
// 初始化现在电量显示控件
|
||||
mtvCurrentValue.setTextColor(getActivity().getColor(R.color.colorCurrent));
|
||||
mtvCurrentValue.setText(Integer.toString(nCurrentValue) + "%");
|
||||
|
||||
// 初始化服务总开关
|
||||
mswIsEnableService.setChecked(mAppConfigUtils.getIsEnableService());
|
||||
if (mAppConfigUtils.getIsEnableService()) {
|
||||
//LogUtils.d(TAG, "mApplication.getIsEnableService() " + Boolean.toString(mAppConfigUtils.getIsEnableService()));
|
||||
ControlCenterService.startControlCenterService(getActivity());
|
||||
} else {
|
||||
//LogUtils.d(TAG, "mApplication.getIsEnableService() " + Boolean.toString(mAppConfigUtils.getIsEnableService()));
|
||||
ControlCenterService.stopControlCenterService(getActivity());
|
||||
}
|
||||
mswIsEnableService.setText(getString(R.string.txt_aboveswitch));
|
||||
mtvTips.setText(getString(R.string.txt_aboveswitchtips));
|
||||
|
||||
}
|
||||
|
||||
void setViewListener() {
|
||||
// 初始化充电电量提醒设置控件
|
||||
mChargeReminderSeekBarChangeListener = new ChargeReminderSeekBarChangeListener();
|
||||
mChargeReminderSeekBar.setOnSeekBarChangeListener(mChargeReminderSeekBarChangeListener);
|
||||
mcbIsEnableChargeReminder.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
LogUtils.d(TAG, "setIsEnableChargeReminder");
|
||||
mAppConfigUtils.setIsEnableChargeReminder(mcbIsEnableChargeReminder.isChecked());
|
||||
//ControlCenterService.updateIsEnableChargeReminder(mcbIsEnableChargeReminder.isChecked());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// 初始化耗电电量提醒设置控件
|
||||
mUsegeReminderSeekBarChangeListener = new UsegeReminderSeekBarChangeListener();
|
||||
mUsegeReminderSeekBar.setOnSeekBarChangeListener(mUsegeReminderSeekBarChangeListener);
|
||||
mcbIsEnableUsegeReminder.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
LogUtils.d(TAG, "setIsEnableUsegeReminder");
|
||||
mAppConfigUtils.setIsEnableUsegeReminder(mcbIsEnableUsegeReminder.isChecked());
|
||||
//ControlCenterService.updateIsEnableUsegeReminder(mcbIsEnableUsegeReminder.isChecked());
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化服务总开关
|
||||
mswIsEnableService.setOnClickListener(new CompoundButton.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
mAppConfigUtils.setIsEnableService(getActivity(), mswIsEnableService.isChecked());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void setCurrentValueBattery(int value) {
|
||||
//LogUtils.d(TAG, "setCurrentValueBattery");
|
||||
mtvCurrentValue.setText(Integer.toString(value) + "%");
|
||||
mCurrentValueBatteryDrawable.setValue(value);
|
||||
mCurrentValueBatteryDrawable.invalidateSelf();
|
||||
}
|
||||
|
||||
class ChargeReminderSeekBarChangeListener implements SeekBar.OnSeekBarChangeListener {
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
//LogUtils.d(TAG, "call onProgressChanged");
|
||||
int nChargeReminderValue = progress;
|
||||
mtvChargeReminderValue.setText(Integer.toString(nChargeReminderValue) + "%");
|
||||
mChargeReminderValueBatteryDrawable.setValue(nChargeReminderValue);
|
||||
mChargeReminderValueBatteryDrawable.invalidateSelf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
//LogUtils.d(TAG, "call onStartTrackingTouch");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
//LogUtils.d(TAG, "call onStopTrackingTouch");
|
||||
//取得当前进度条的刻度
|
||||
int nChargeReminderValue = ((VerticalSeekBar)seekBar)._mnProgress;
|
||||
|
||||
mAppConfigUtils.setChargeReminderValue(nChargeReminderValue);
|
||||
mtvChargeReminderValue.setText(Integer.toString(nChargeReminderValue) + "%");
|
||||
//ControlCenterService.updateChargeReminderValue(nChargeReminderValue);
|
||||
}
|
||||
}
|
||||
|
||||
class UsegeReminderSeekBarChangeListener implements SeekBar.OnSeekBarChangeListener {
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
//LogUtils.d(TAG, "call onProgressChanged");
|
||||
int nUsegeReminderValue = progress;
|
||||
mtvUsegeReminderValue.setText(Integer.toString(nUsegeReminderValue) + "%");
|
||||
mUsegeReminderValueBatteryDrawable.setValue(nUsegeReminderValue);
|
||||
mUsegeReminderValueBatteryDrawable.invalidateSelf();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
//LogUtils.d(TAG, "call onStartTrackingTouch");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
//LogUtils.d(TAG, "call onStopTrackingTouch");
|
||||
//取得当前进度条的刻度
|
||||
int nUsegeReminderValue = ((VerticalSeekBar)seekBar)._mnProgress;
|
||||
LogUtils.d(TAG, "nUsegeReminderValue is " + Integer.toString(nUsegeReminderValue));
|
||||
//LogUtils.d(TAG, "mPowerReminder is " + mApplication);
|
||||
mAppConfigUtils.setUsegeReminderValue(nUsegeReminderValue);
|
||||
//LogUtils.d(TAG, "opopopopopopopop");
|
||||
mtvUsegeReminderValue.setText(Integer.toString(nUsegeReminderValue) + "%");
|
||||
//ControlCenterService.updateUsegeReminderValue(nUsegeReminderValue);
|
||||
}
|
||||
}
|
||||
|
||||
public void reloadBackground() {
|
||||
BackgroundSourceUtils utils = BackgroundSourceUtils.getInstance(getActivity());
|
||||
mBgSourceUtils.loadSettings();
|
||||
BackgroundBean bean = utils.getCurrentBackgroundBean();
|
||||
mBackgroundView.loadBackgroundBean(bean);
|
||||
}
|
||||
|
||||
Handler mHandler = new Handler(){
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_RELOAD_APPCONFIG : {
|
||||
setViewData();
|
||||
break;
|
||||
}
|
||||
case MSG_CURRENTVALUEBATTERY : {
|
||||
setCurrentValueBattery(msg.arg1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
super.handleMessage(msg);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public static void relaodAppConfigs() {
|
||||
if (_mMainViewFragment != null) {
|
||||
Handler handler = _mMainViewFragment.mHandler;
|
||||
handler.sendMessage(handler.obtainMessage(MSG_RELOAD_APPCONFIG));
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendMsgCurrentValueBattery(int value) {
|
||||
if (_mMainViewFragment != null) {
|
||||
Handler handler = _mMainViewFragment.mHandler;
|
||||
Message msg = handler.obtainMessage(MSG_CURRENTVALUEBATTERY);
|
||||
msg.arg1 = value;
|
||||
handler.sendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,13 +4,14 @@ import android.util.JsonReader;
|
||||
import android.util.JsonWriter;
|
||||
import cc.winboll.studio.libappbase.BaseBean;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen<zhangsken@qq.com>
|
||||
* @Date 2024/07/18 11:52:28
|
||||
* @Describe 应用背景图片数据类(存储正式/预览背景配置,支持JSON序列化/反序列化)
|
||||
*/
|
||||
public class BackgroundBean extends BaseBean {
|
||||
public class BackgroundBean extends BaseBean implements Serializable {
|
||||
|
||||
public static final String TAG = "BackgroundPictureBean";
|
||||
|
||||
|
||||
@@ -5,10 +5,9 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import cc.winboll.studio.powerbell.App;
|
||||
import cc.winboll.studio.powerbell.fragments.MainViewFragment;
|
||||
import cc.winboll.studio.powerbell.MainActivity;
|
||||
import cc.winboll.studio.powerbell.utils.AppConfigUtils;
|
||||
import cc.winboll.studio.powerbell.utils.BatteryUtils;
|
||||
import cc.winboll.studio.powerbell.utils.NotificationHelper;
|
||||
|
||||
public class GlobalApplicationReceiver extends BroadcastReceiver {
|
||||
|
||||
@@ -48,7 +47,7 @@ public class GlobalApplicationReceiver extends BroadcastReceiver {
|
||||
//NotificationHelper.cancelRemindNotification(context);
|
||||
|
||||
App.getAppCacheUtils(context).addChangingTime(nTheQuantityOfElectricity);
|
||||
MainViewFragment.sendMsgCurrentValueBattery(nTheQuantityOfElectricity);
|
||||
MainActivity.sendMsgCurrentValueBattery(nTheQuantityOfElectricity);
|
||||
// 保存好新的电池状态标志
|
||||
_mIsCharging = isCharging;
|
||||
_mnTheQuantityOfElectricityOld = nTheQuantityOfElectricity;
|
||||
|
||||
@@ -79,7 +79,7 @@ public class AppConfigUtils {
|
||||
|
||||
@Override
|
||||
public void onNo() {
|
||||
MainViewFragment.relaodAppConfigs();
|
||||
MainActivity.relaodAppConfigs();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -183,7 +183,7 @@ public class AppConfigUtils {
|
||||
@Override
|
||||
public void onNo() {
|
||||
AppConfigUtils.getInstance(activity).loadAppConfigBean();
|
||||
MainViewFragment.relaodAppConfigs();
|
||||
MainActivity.relaodAppConfigs();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -198,6 +198,6 @@ public class AppConfigUtils {
|
||||
AppConfigBean.saveBean(mContext, mAppConfigBean);
|
||||
// 通知活动窗口和服务配置已更新
|
||||
ControlCenterService.updateStatus(mContext, mAppConfigBean);
|
||||
MainViewFragment.relaodAppConfigs();
|
||||
MainActivity.relaodAppConfigs();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ public class BackgroundSourceUtils {
|
||||
clearCropTempFiles();
|
||||
LogUtils.d(TAG, "【文件初始化】完成。");
|
||||
}
|
||||
|
||||
|
||||
// 【核心实现】定义 getFileProviderUri 方法:将 File 转为 ContentUri(适配 FileProvider)
|
||||
public Uri getFileProviderUri(File file) {
|
||||
Log.d("BackgroundSourceUtils", "getFileProviderUri: 生成FileProvider Uri,文件路径:" + file.getAbsolutePath());
|
||||
@@ -245,13 +245,16 @@ public class BackgroundSourceUtils {
|
||||
return contentUri;
|
||||
}
|
||||
|
||||
public boolean createCropFileProviderBackgroundBean(Uri uri) {
|
||||
/*
|
||||
* 创建预览数据剪裁环境
|
||||
*/
|
||||
public boolean createAndUpdatePreviewEnvironmentForCropping(BackgroundBean oldPreviewBackgroundBean) {
|
||||
InputStream is = null;
|
||||
FileOutputStream fos = null;
|
||||
loadSettings();
|
||||
|
||||
try {
|
||||
clearCropTempFiles();
|
||||
Uri uri = UriUtil.getUriForFile(mContext, oldPreviewBackgroundBean.getBackgroundFilePath());
|
||||
//String szType = mContext.getContentResolver().getType(uri);
|
||||
// 2. 截取MIME类型后缀(如从image/jpeg中提取jpeg)【核心新增逻辑】
|
||||
String fileSuffix = FileUtils.getFileSuffix(mContext, uri);
|
||||
@@ -259,51 +262,63 @@ public class BackgroundSourceUtils {
|
||||
mCropSourceFile = new File(fCropCacheDir, newCropFileName + "." + fileSuffix);
|
||||
mCropResultFile = new File(fCropCacheDir, "SelectCompress_" + newCropFileName + "." + fileSuffix);
|
||||
|
||||
mCropSourceFile.createNewFile();
|
||||
mCropResultFile.createNewFile();
|
||||
|
||||
// 1. 打开Uri输入流(兼容content:///file:// 等多种Uri格式)
|
||||
is = mContext.getContentResolver().openInputStream(uri);
|
||||
if (is == null) {
|
||||
LogUtils.e(TAG, "【选图解析】ContentResolver打开Uri失败,Uri:" + uri.toString());
|
||||
return false;
|
||||
if (FileUtils.isFileExists(oldPreviewBackgroundBean.getBackgroundScaledCompressFilePath())) {
|
||||
FileUtils.copyFile(new File(oldPreviewBackgroundBean.getBackgroundScaledCompressFilePath()), mCropResultFile);
|
||||
} else {
|
||||
mCropResultFile.createNewFile();
|
||||
}
|
||||
|
||||
// 2. 初始化选图临时文件输出流(Java7 手动创建流,不依赖try-with-resources)
|
||||
fos = new FileOutputStream(mCropSourceFile);
|
||||
byte[] buffer = new byte[1024 * 8]; // 8KB缓冲区,平衡读写性能与内存占用
|
||||
int readLen; // 每次读取的字节长度
|
||||
if (FileUtils.isFileExists(oldPreviewBackgroundBean.getBackgroundFilePath())) {
|
||||
FileUtils.copyFile(new File(oldPreviewBackgroundBean.getBackgroundFilePath()), mCropSourceFile);
|
||||
} else {
|
||||
mCropSourceFile.createNewFile();
|
||||
// 1. 打开Uri输入流(兼容content:///file:// 等多种Uri格式)
|
||||
is = mContext.getContentResolver().openInputStream(uri);
|
||||
if (is == null) {
|
||||
LogUtils.e(TAG, "【选图解析】ContentResolver打开Uri失败,Uri:" + uri.toString());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. 流复制(Java7 标准while循环,避免Java8+语法)
|
||||
while ((readLen = is.read(buffer)) != -1) {
|
||||
fos.write(buffer, 0, readLen); // 精准写入读取到的字节,避免空字节填充
|
||||
}
|
||||
// 2. 初始化选图临时文件输出流(Java7 手动创建流,不依赖try-with-resources)
|
||||
fos = new FileOutputStream(mCropSourceFile);
|
||||
byte[] buffer = new byte[1024 * 8]; // 8KB缓冲区,平衡读写性能与内存占用
|
||||
int readLen; // 每次读取的字节长度
|
||||
|
||||
// 4. 强制同步写入磁盘(解决Android 10+ 异步写入导致的文件无效问题)
|
||||
fos.flush();
|
||||
if (fos != null) {
|
||||
try {
|
||||
fos.getFD().sync(); // 确保数据写入物理磁盘,而非缓存
|
||||
} catch (IOException e) {
|
||||
LogUtils.w(TAG, "【选图解析】文件同步到磁盘失败,用flush()兜底:" + e.getMessage());
|
||||
fos.flush();
|
||||
// 3. 流复制(Java7 标准while循环,避免Java8+语法)
|
||||
while ((readLen = is.read(buffer)) != -1) {
|
||||
fos.write(buffer, 0, readLen); // 精准写入读取到的字节,避免空字节填充
|
||||
}
|
||||
|
||||
// 4. 强制同步写入磁盘(解决Android 10+ 异步写入导致的文件无效问题)
|
||||
fos.flush();
|
||||
if (fos != null) {
|
||||
try {
|
||||
fos.getFD().sync(); // 确保数据写入物理磁盘,而非缓存
|
||||
} catch (IOException e) {
|
||||
LogUtils.w(TAG, "【选图解析】文件同步到磁盘失败,用flush()兜底:" + e.getMessage());
|
||||
fos.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 加载图片数据模型数据
|
||||
loadSettings();
|
||||
// 修改预览数据模型
|
||||
previewBackgroundBean.setBackgroundFileName(mCropSourceFile.getName());
|
||||
previewBackgroundBean.setBackgroundFilePath(mCropSourceFile.getAbsolutePath());
|
||||
|
||||
previewBackgroundBean.setBackgroundScaledCompressFileName(mCropResultFile.getName());
|
||||
previewBackgroundBean.setBackgroundScaledCompressFilePath(mCropResultFile.getAbsolutePath());
|
||||
// 保存数据模型数据更改
|
||||
saveSettings();
|
||||
|
||||
|
||||
// 6. 解析成功日志(打印文件信息,便于问题排查)
|
||||
LogUtils.d(TAG, "【选图解析】Uri解析成功!");
|
||||
LogUtils.d(TAG, "→ 原Uri:" + uri.toString());
|
||||
LogUtils.d(TAG, "→ 目标临时文件:" + mCropSourceFile.getAbsolutePath());
|
||||
LogUtils.d(TAG, "→ 目标临时文件大小:" + mCropSourceFile.length() + " bytes");
|
||||
LogUtils.d(TAG, "→ 目标剪裁临时文件:" + mCropResultFile.getAbsolutePath());
|
||||
LogUtils.d(TAG, "→ 目标剪裁临时文件大小:" + mCropResultFile.length() + " bytes");
|
||||
LogUtils.d(TAG, "→ 图片剪裁数据源:" + mCropSourceFile.getAbsolutePath());
|
||||
LogUtils.d(TAG, "→ 图片剪裁数据源文件大小:" + mCropSourceFile.length() + " bytes");
|
||||
LogUtils.d(TAG, "→ 剪裁结果数据文件:" + mCropResultFile.getAbsolutePath());
|
||||
LogUtils.d(TAG, "→ 剪裁结果数据文件大小:" + mCropResultFile.length() + " bytes");
|
||||
return true;
|
||||
|
||||
} catch (Exception e) {
|
||||
@@ -424,7 +439,7 @@ public class BackgroundSourceUtils {
|
||||
* 保存配置(核心:将两份独立Bean实例,分别写入各自的JSON文件)
|
||||
*/
|
||||
public void saveSettings() {
|
||||
if(currentBackgroundBean != null && previewBackgroundBean != null) {
|
||||
if (currentBackgroundBean != null && previewBackgroundBean != null) {
|
||||
BackgroundBean.saveBeanToFile(currentBackgroundBeanFile.getAbsolutePath(), currentBackgroundBean); // 正式Bean→正式JSON
|
||||
BackgroundBean.saveBeanToFile(previewBackgroundBeanFile.getAbsolutePath(), previewBackgroundBean); // 预览Bean→预览JSON
|
||||
LogUtils.d(TAG, "【配置管理】两份配置保存成功:正式JSON=" + currentBackgroundBeanFile.getAbsolutePath() + ",预览JSON=" + previewBackgroundBeanFile.getAbsolutePath());
|
||||
@@ -531,12 +546,12 @@ public class BackgroundSourceUtils {
|
||||
// 更新当前背景文件路径
|
||||
currentBackgroundBean.setBackgroundFilePath(currentFile.getAbsolutePath()); // 原图路径(BackgroundSource)
|
||||
currentBackgroundBean.setBackgroundScaledCompressFilePath(currentCropFile.getAbsolutePath()); // 压缩图路径(BackgroundCrops)
|
||||
|
||||
|
||||
saveSettings(); // 分别保存:正式Bean→currentJSON,预览Bean→previewJSON(两份独立)
|
||||
LogUtils.d(TAG, "【配置管理】预览背景深拷贝到正式Bean:两份实例独立,压缩图统一存储到BackgroundCrops");
|
||||
ToastUtils.show("背景图片应用成功");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将正式背景同步到预览背景(正式Bean → 预览Bean:深拷贝,新建预览Bean实例+逐字段拷贝)
|
||||
* 核心:深拷贝后,修改预览Bean不会影响正式Bean,两份实例完全独立,压缩图路径统一指向BackgroundCrops
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
package cc.winboll.studio.powerbell.utils;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||
* @Date 2025/12/11 01:57
|
||||
* @Describe 单例 Bitmap 缓存工具类(Java 7 兼容)
|
||||
* 功能:内存缓存 Bitmap,支持路径关联缓存、全局获取、缓存清空
|
||||
* 特点:1. 单例模式 2. 压缩加载避免OOM 3. 路径- Bitmap 映射 4. 线程安全
|
||||
*/
|
||||
public class BitmapCacheUtils {
|
||||
private static final String TAG = "BitmapCacheUtils";
|
||||
// 最大图片尺寸(适配1080P屏幕,可根据需求调整)
|
||||
private static final int MAX_WIDTH = 1080;
|
||||
private static final int MAX_HEIGHT = 1920;
|
||||
|
||||
// 单例实例(volatile 保证多线程可见性)
|
||||
private static volatile BitmapCacheUtils sInstance;
|
||||
// 路径-Bitmap 缓存容器(内存缓存)
|
||||
private final Map<String, Bitmap> mBitmapCacheMap;
|
||||
|
||||
// 私有构造器(单例模式)
|
||||
private BitmapCacheUtils() {
|
||||
mBitmapCacheMap = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单例实例(双重校验锁,线程安全)
|
||||
*/
|
||||
public static BitmapCacheUtils getInstance() {
|
||||
if (sInstance == null) {
|
||||
synchronized (BitmapCacheUtils.class) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new BitmapCacheUtils();
|
||||
}
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心接口:根据图片路径缓存 Bitmap 到内存
|
||||
* @param imagePath 图片绝对路径
|
||||
* @return 缓存成功的 Bitmap / null(路径无效/文件不存在)
|
||||
*/
|
||||
public Bitmap cacheBitmap(String imagePath) {
|
||||
if (TextUtils.isEmpty(imagePath)) {
|
||||
LogUtils.e(TAG, "cacheBitmap: 图片路径为空");
|
||||
return null;
|
||||
}
|
||||
|
||||
File imageFile = new File(imagePath);
|
||||
if (!imageFile.exists() || !imageFile.isFile()) {
|
||||
LogUtils.e(TAG, "cacheBitmap: 图片文件不存在 - " + imagePath);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 已缓存则直接返回,避免重复加载
|
||||
if (mBitmapCacheMap.containsKey(imagePath)) {
|
||||
LogUtils.d(TAG, "cacheBitmap: 图片已缓存,直接返回 - " + imagePath);
|
||||
return mBitmapCacheMap.get(imagePath);
|
||||
}
|
||||
|
||||
// 压缩加载 Bitmap(避免OOM)
|
||||
Bitmap bitmap = decodeCompressedBitmap(imagePath);
|
||||
if (bitmap != null) {
|
||||
// 存入缓存容器
|
||||
mBitmapCacheMap.put(imagePath, bitmap);
|
||||
LogUtils.d(TAG, "cacheBitmap: 图片缓存成功 - " + imagePath);
|
||||
} else {
|
||||
LogUtils.e(TAG, "cacheBitmap: 图片解码失败 - " + imagePath);
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心接口:根据路径获取缓存的 Bitmap
|
||||
* @param imagePath 图片绝对路径
|
||||
* @return 缓存的 Bitmap / null
|
||||
*/
|
||||
public Bitmap getCachedBitmap(String imagePath) {
|
||||
if (TextUtils.isEmpty(imagePath)) {
|
||||
return null;
|
||||
}
|
||||
return mBitmapCacheMap.get(imagePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空所有 Bitmap 缓存(释放内存)
|
||||
*/
|
||||
public void clearAllCache() {
|
||||
for (Bitmap bitmap : mBitmapCacheMap.values()) {
|
||||
if (bitmap != null && !bitmap.isRecycled()) {
|
||||
bitmap.recycle(); // 主动回收 Bitmap
|
||||
}
|
||||
}
|
||||
mBitmapCacheMap.clear();
|
||||
LogUtils.d(TAG, "clearAllCache: 所有 Bitmap 缓存已清空");
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除指定路径的 Bitmap 缓存
|
||||
* @param imagePath 图片绝对路径
|
||||
*/
|
||||
public void removeCachedBitmap(String imagePath) {
|
||||
if (TextUtils.isEmpty(imagePath)) {
|
||||
return;
|
||||
}
|
||||
Bitmap bitmap = mBitmapCacheMap.remove(imagePath);
|
||||
if (bitmap != null && !bitmap.isRecycled()) {
|
||||
bitmap.recycle();
|
||||
LogUtils.d(TAG, "removeCachedBitmap: 移除并回收缓存 - " + imagePath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 压缩解码 Bitmap(按最大尺寸缩放,避免OOM)
|
||||
*/
|
||||
private Bitmap decodeCompressedBitmap(String imagePath) {
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
// 第一步:只获取图片尺寸,不加载像素
|
||||
options.inJustDecodeBounds = true;
|
||||
BitmapFactory.decodeFile(imagePath, options);
|
||||
|
||||
// 计算缩放比例
|
||||
int sampleSize = calculateInSampleSize(options, MAX_WIDTH, MAX_HEIGHT);
|
||||
|
||||
// 第二步:加载压缩后的 Bitmap
|
||||
options.inJustDecodeBounds = false;
|
||||
options.inSampleSize = sampleSize;
|
||||
options.inPreferredConfig = Bitmap.Config.RGB_565; // 节省内存(比ARGB_8888少一半内存)
|
||||
options.inPurgeable = true;
|
||||
options.inInputShareable = true;
|
||||
|
||||
return BitmapFactory.decodeFile(imagePath, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算 Bitmap 缩放比例
|
||||
*/
|
||||
private int calculateInSampleSize(BitmapFactory.Options options, int maxWidth, int maxHeight) {
|
||||
int rawWidth = options.outWidth;
|
||||
int rawHeight = options.outHeight;
|
||||
int inSampleSize = 1;
|
||||
|
||||
if (rawWidth > maxWidth || rawHeight > maxHeight) {
|
||||
int halfWidth = rawWidth / 2;
|
||||
int halfHeight = rawHeight / 2;
|
||||
while ((halfWidth / inSampleSize) >= maxWidth && (halfHeight / inSampleSize) >= maxHeight) {
|
||||
inSampleSize *= 2;
|
||||
}
|
||||
}
|
||||
return inSampleSize;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package cc.winboll.studio.powerbell.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||
* @Date 2025/12/08 21:11
|
||||
* @Describe 把 R.drawable 中的图片保存为 File 对象的工具类
|
||||
* 适配 PowerBell 项目:支持指定保存路径、自动创建目录、处理PNG图片压缩
|
||||
*/
|
||||
public class DrawableToFileUtils {
|
||||
private static final String TAG = "DrawableToFileUtils";
|
||||
|
||||
/**
|
||||
* 核心方法:将 R.drawable 图片保存为 File 对象
|
||||
* @param context 上下文(用于获取 Resources)
|
||||
* @param drawableResId 图片资源ID(如 R.drawable.ic_test_png)
|
||||
* @param fileName 保存的文件名(需带 .png 后缀,如 "test_drawable.png")
|
||||
* @return 保存成功返回 File 对象,失败返回 null
|
||||
*/
|
||||
public static File saveDrawableToFile(Context context, int drawableResId, String filePath) {
|
||||
// 1. 校验参数(避免空指针/无效参数)
|
||||
if (context == null || drawableResId == 0 || filePath == null || filePath.isEmpty()) {
|
||||
LogUtils.e(TAG, "【保存失败】参数无效(context为空/资源ID为0/文件名为空)");
|
||||
return null;
|
||||
}
|
||||
if (!filePath.endsWith(".png")) {
|
||||
filePath += ".png"; // 强制添加 .png 后缀,确保图片格式正确
|
||||
LogUtils.d(TAG, "【格式适配】自动添加.png后缀,最终文件名:" + filePath);
|
||||
}
|
||||
|
||||
// 3. 构建目标 File 对象(最终保存的文件路径)
|
||||
File targetFile = new File(filePath);
|
||||
LogUtils.d(TAG, "【保存路径】目标文件路径:" + targetFile.getAbsolutePath());
|
||||
|
||||
// 4. 读取 drawable 资源为 Bitmap(处理高清图/缩放问题)
|
||||
Bitmap bitmap = null;
|
||||
try {
|
||||
// 读取 drawable 资源(适配不同分辨率的图片,避免变形)
|
||||
bitmap = BitmapFactory.decodeResource(context.getResources(), drawableResId);
|
||||
if (bitmap == null) {
|
||||
LogUtils.e(TAG, "【读取失败】无法读取drawable资源(资源ID:" + drawableResId + ")");
|
||||
return null;
|
||||
}
|
||||
LogUtils.d(TAG, "【读取成功】drawable资源转Bitmap成功(宽:" + bitmap.getWidth() + ",高:" + bitmap.getHeight() + ")");
|
||||
|
||||
// 5. 将 Bitmap 写入 File(PNG格式,无损保存)
|
||||
FileOutputStream fos = new FileOutputStream(targetFile);
|
||||
// 压缩参数:PNG格式,质量100(无损),写入输出流
|
||||
boolean isSaved = bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
|
||||
fos.flush(); // 刷新输出流
|
||||
fos.close(); // 关闭输出流
|
||||
|
||||
// 6. 校验保存结果(文件是否存在且有效)
|
||||
if (isSaved && targetFile.exists() && targetFile.length() > 100) {
|
||||
LogUtils.d(TAG, "【保存成功】drawable图片保存为File:" + targetFile.getAbsolutePath());
|
||||
return targetFile; // 保存成功,返回File对象
|
||||
} else {
|
||||
LogUtils.e(TAG, "【保存失败】图片写入文件无效(文件大小:" + (targetFile.exists() ? targetFile.length() : 0) + "字节)");
|
||||
// 保存失败,删除无效文件
|
||||
if (targetFile.exists()) {
|
||||
targetFile.delete();
|
||||
LogUtils.d(TAG, "【清理无效文件】已删除无效文件:" + targetFile.getAbsolutePath());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LogUtils.e(TAG, "【保存异常】写入文件时出错:" + e.getMessage());
|
||||
LogUtils.e(TAG, "【异常堆栈】" + Log.getStackTraceString(e));
|
||||
return null;
|
||||
} finally {
|
||||
// 回收Bitmap资源(避免内存溢出)
|
||||
if (bitmap != null && !bitmap.isRecycled()) {
|
||||
bitmap.recycle();
|
||||
LogUtils.d(TAG, "【资源回收】Bitmap资源已回收");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重载方法:自定义保存路径(灵活适配不同场景)
|
||||
* @param context 上下文
|
||||
* @param drawableResId 图片资源ID
|
||||
* @param saveDirPath 自定义保存目录路径(如 "/storage/emulated/0/PowerBell/custom/")
|
||||
* @param fileName 保存的文件名(带.png后缀)
|
||||
* @return 保存成功返回File对象,失败返回null
|
||||
*/
|
||||
public static File saveDrawableToFile(Context context, int drawableResId, String saveDirPath, String fileName) {
|
||||
File filePath = new File(saveDirPath, fileName);
|
||||
return saveDrawableToFile(context, drawableResId, filePath.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,5 +277,10 @@ public class FileUtils {
|
||||
}
|
||||
return fileSuffix;
|
||||
}
|
||||
|
||||
public static boolean isFileExists(String path) {
|
||||
File file = new File(path);
|
||||
return file.exists();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -103,6 +103,11 @@ public class UriUtil {
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public static Uri getUriForFile(Context context, String filePath) {
|
||||
File file = new File(filePath);
|
||||
return getUriForFile(context, file);
|
||||
}
|
||||
|
||||
public static Uri getUriForFile(Context context, File file) {
|
||||
//Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", file);
|
||||
|
||||
@@ -4,14 +4,16 @@ import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ImageView.ScaleType;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.ToastUtils;
|
||||
import cc.winboll.studio.powerbell.App;
|
||||
import cc.winboll.studio.powerbell.model.BackgroundBean;
|
||||
import java.io.File;
|
||||
|
||||
@@ -22,6 +24,8 @@ import java.io.File;
|
||||
public class BackgroundView extends RelativeLayout {
|
||||
|
||||
public static final String TAG = "BackgroundView";
|
||||
// 新增:记录当前已缓存的图片路径
|
||||
private String mCurrentCachedPath = "";
|
||||
|
||||
private Context mContext;
|
||||
private LinearLayout mLlContainer; // 主容器LinearLayout
|
||||
@@ -55,8 +59,6 @@ public class BackgroundView extends RelativeLayout {
|
||||
LogUtils.d(TAG, "=== initView 启动 ===");
|
||||
// 1. 配置当前控件:全屏+透明
|
||||
setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
|
||||
setBackgroundColor(0x00000000);
|
||||
setBackground(new ColorDrawable(0x00000000));
|
||||
|
||||
// 2. 初始化主容器LinearLayout
|
||||
initLinearLayout();
|
||||
@@ -64,8 +66,9 @@ public class BackgroundView extends RelativeLayout {
|
||||
// 3. 初始化ImageView
|
||||
initImageView();
|
||||
|
||||
// 4. 初始设置透明背景
|
||||
// 初始设置透明背景
|
||||
setDefaultTransparentBackground();
|
||||
|
||||
LogUtils.d(TAG, "=== initView 完成 ===");
|
||||
}
|
||||
|
||||
@@ -100,22 +103,21 @@ public class BackgroundView extends RelativeLayout {
|
||||
LogUtils.d(TAG, "=== initImageView 完成 ===");
|
||||
}
|
||||
|
||||
public void loadBackgroundBean(BackgroundBean bean) {
|
||||
if(!bean.isUseBackgroundFile()) {
|
||||
setDefaultTransparentBackground();
|
||||
return;
|
||||
}
|
||||
if(bean.isUseBackgroundScaledCompressFile()) {
|
||||
loadImage(bean.getBackgroundScaledCompressFilePath());
|
||||
} else {
|
||||
|
||||
loadImage(bean.getBackgroundFilePath());
|
||||
}
|
||||
}
|
||||
public void loadBackgroundBean(BackgroundBean bean) {
|
||||
if (!bean.isUseBackgroundFile()) {
|
||||
setDefaultTransparentBackground();
|
||||
return;
|
||||
}
|
||||
String targetPath = bean.isUseBackgroundScaledCompressFile()
|
||||
? bean.getBackgroundScaledCompressFilePath()
|
||||
: bean.getBackgroundFilePath();
|
||||
// 调用带路径判断的loadImage方法
|
||||
loadImage(targetPath);
|
||||
}
|
||||
|
||||
// ====================================== 对外方法 ======================================
|
||||
/**
|
||||
* 加载图片(保持原图比例,在LinearLayout中居中平铺)
|
||||
* 改造后:添加路径判断,路径更新时同步更新缓存
|
||||
* @param imagePath 图片绝对路径
|
||||
*/
|
||||
public void loadImage(String imagePath) {
|
||||
@@ -132,22 +134,50 @@ public class BackgroundView extends RelativeLayout {
|
||||
return;
|
||||
}
|
||||
|
||||
// 计算原图比例
|
||||
mIvBackground.setVisibility(View.GONE);
|
||||
|
||||
// ======================== 新增:路径判断逻辑 ========================
|
||||
// 1. 路径未变化:直接使用缓存
|
||||
if (imagePath.equals(mCurrentCachedPath)) {
|
||||
//ToastUtils.show("isReload == false");
|
||||
Bitmap cachedBitmap = App._mBitmapCacheUtils.getCachedBitmap(imagePath);
|
||||
if (cachedBitmap != null && !cachedBitmap.isRecycled()) {
|
||||
LogUtils.d(TAG, "loadImage: 路径未变,使用缓存 Bitmap");
|
||||
mImageAspectRatio = (float) cachedBitmap.getWidth() / cachedBitmap.getHeight();
|
||||
mIvBackground.setImageBitmap(cachedBitmap);
|
||||
adjustImageViewSize();
|
||||
mIvBackground.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 路径已更新:移除旧缓存,加载新图片并更新缓存
|
||||
if (!TextUtils.isEmpty(mCurrentCachedPath)) {
|
||||
App._mBitmapCacheUtils.removeCachedBitmap(mCurrentCachedPath);
|
||||
LogUtils.d(TAG, "loadImage: 路径已更新,移除旧缓存 - " + mCurrentCachedPath);
|
||||
}
|
||||
// ======================== 路径判断逻辑结束 ========================
|
||||
|
||||
// 无缓存/路径更新:走原有逻辑加载图片
|
||||
if (!calculateImageAspectRatio(imageFile)) {
|
||||
setDefaultTransparentBackground();
|
||||
return;
|
||||
}
|
||||
|
||||
// 压缩加载Bitmap
|
||||
Bitmap bitmap = decodeBitmapWithCompress(imageFile, 1080, 1920);
|
||||
if (bitmap == null) {
|
||||
setDefaultTransparentBackground();
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置图片
|
||||
// 缓存新图片,并更新当前缓存路径记录
|
||||
App._mBitmapCacheUtils.cacheBitmap(imagePath);
|
||||
mCurrentCachedPath = imagePath;
|
||||
LogUtils.d(TAG, "loadImage: 加载新图片并更新缓存 - " + imagePath);
|
||||
|
||||
mIvBackground.setImageDrawable(new BitmapDrawable(mContext.getResources(), bitmap));
|
||||
adjustImageViewSize(); // 调整尺寸
|
||||
adjustImageViewSize();
|
||||
mIvBackground.setVisibility(View.VISIBLE);
|
||||
LogUtils.d(TAG, "=== loadImage 完成 ===");
|
||||
}
|
||||
|
||||
@@ -195,54 +225,39 @@ public class BackgroundView extends RelativeLayout {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 调整ImageView尺寸(保持原图比例,在LinearLayout中居中平铺)
|
||||
*/
|
||||
private void adjustImageViewSize() {
|
||||
LogUtils.d(TAG, "=== adjustImageViewSize 启动 ===");
|
||||
if (mLlContainer == null || mIvBackground == null) {
|
||||
LogUtils.e(TAG, "控件为空");
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取LinearLayout尺寸
|
||||
int llWidth = mLlContainer.getWidth();
|
||||
int llHeight = mLlContainer.getHeight();
|
||||
if (llWidth == 0 || llHeight == 0) {
|
||||
postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
adjustImageViewSize();
|
||||
}
|
||||
}, 10);
|
||||
return;
|
||||
|
||||
if (llWidth != 0 && llHeight != 0) {
|
||||
int ivWidth, ivHeight;
|
||||
if (mImageAspectRatio >= 1.0f) {
|
||||
ivWidth = Math.min((int) (llHeight * mImageAspectRatio), llWidth);
|
||||
ivHeight = (int) (ivWidth / mImageAspectRatio);
|
||||
} else {
|
||||
ivHeight = Math.min((int) (llWidth / mImageAspectRatio), llHeight);
|
||||
ivWidth = (int) (ivHeight * mImageAspectRatio);
|
||||
}
|
||||
|
||||
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mIvBackground.getLayoutParams();
|
||||
params.width = ivWidth;
|
||||
params.height = ivHeight;
|
||||
mIvBackground.setLayoutParams(params);
|
||||
mIvBackground.setScaleType(ScaleType.FIT_CENTER);
|
||||
mIvBackground.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
// 计算ImageView尺寸(保持比例,不超出LinearLayout)
|
||||
int ivWidth, ivHeight;
|
||||
if (mImageAspectRatio >= 1.0f) {
|
||||
ivWidth = Math.min((int) (llHeight * mImageAspectRatio), llWidth);
|
||||
ivHeight = (int) (ivWidth / mImageAspectRatio);
|
||||
} else {
|
||||
ivHeight = Math.min((int) (llWidth / mImageAspectRatio), llHeight);
|
||||
ivWidth = (int) (ivHeight * mImageAspectRatio);
|
||||
}
|
||||
|
||||
// 应用尺寸
|
||||
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mIvBackground.getLayoutParams();
|
||||
params.width = ivWidth;
|
||||
params.height = ivHeight;
|
||||
mIvBackground.setLayoutParams(params);
|
||||
mIvBackground.setScaleType(ScaleType.FIT_CENTER); // 确保居中平铺
|
||||
|
||||
LogUtils.d(TAG, "ImageView尺寸:" + ivWidth + "x" + ivHeight);
|
||||
LogUtils.d(TAG, "=== adjustImageViewSize 完成 ===");
|
||||
}
|
||||
|
||||
private void setDefaultTransparentBackground() {
|
||||
mIvBackground.setImageBitmap(null);
|
||||
mIvBackground.setBackgroundColor(0x00000000);
|
||||
mImageAspectRatio = 1.0f;
|
||||
// 清空缓存路径记录
|
||||
mCurrentCachedPath = "";
|
||||
}
|
||||
|
||||
// ====================================== 重写方法 ======================================
|
||||
@@ -252,3 +267,4 @@ public class BackgroundView extends RelativeLayout {
|
||||
adjustImageViewSize(); // 尺寸变化时重新调整
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,40 +1,259 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
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:orientation="vertical">
|
||||
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:orientation="vertical">
|
||||
|
||||
<cc.winboll.studio.libaes.views.ASupportToolbar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/toolbar_height"
|
||||
android:id="@+id/toolbar"
|
||||
android:gravity="center_vertical"
|
||||
style="@style/DefaultAToolbar"/>
|
||||
<!-- 顶部Toolbar(首屏核心,同步加载,保留原有ASupportToolbar) -->
|
||||
<cc.winboll.studio.libaes.views.ASupportToolbar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/toolbar_height"
|
||||
android:id="@+id/toolbar"
|
||||
android:gravity="center_vertical"
|
||||
style="@style/DefaultAToolbar"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1.0">
|
||||
<!-- 主内容区(优化层级,减少冗余RelativeLayout) -->
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1.0">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/activitymainRelativeLayout1"/>
|
||||
<!-- 首屏核心容器(合并原冗余RelativeLayout,减少层级) -->
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/activitymainRelativeLayout1">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/activitymainFrameLayout1"/>
|
||||
<!-- 1. 背景视图(首屏核心,同步加载,保留原有) -->
|
||||
<cc.winboll.studio.powerbell.views.BackgroundView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/fragmentmainviewBackgroundView1"/>
|
||||
|
||||
<cc.winboll.studio.libaes.views.ADsBannerView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/adsbanner"
|
||||
android:layout_alignParentBottom="true"/>
|
||||
<!-- 2. 功能控件容器(首屏核心,同步加载,保留原有结构) -->
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
</RelativeLayout>
|
||||
<!-- 服务总开关布局 -->
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/fragmentmainviewLinearLayout3"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_marginTop="10dp">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:background="@drawable/bg_frame">
|
||||
|
||||
<Switch
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/fragmentandroidviewSwitch1"
|
||||
android:padding="10dp"
|
||||
android:layout_weight="1.0"
|
||||
android:textSize="@dimen/text_title_size"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 电量控制核心布局(SeekBar+图标) -->
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1.0"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="10dp">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1.0">
|
||||
|
||||
<!-- 耗电提醒布局 -->
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:id="@+id/fragmentmainviewLinearLayout1">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:background="@drawable/usege"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="10dp"/>
|
||||
|
||||
<CheckBox
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="10dp"
|
||||
android:id="@+id/fragmentmainviewCheckBox2"/>
|
||||
|
||||
<cc.winboll.studio.powerbell.views.VerticalSeekBar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/fragmentandroidviewVerticalSeekBar2"
|
||||
android:progressTint="@color/colorUsege"
|
||||
android:progressBackgroundTint="@color/colorUsege"
|
||||
android:layout_weight="1.0"
|
||||
android:layout_margin="10dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 耗电提醒数值+图标 -->
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="100%"
|
||||
android:textSize="@dimen/text_title_size"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:id="@+id/fragmentandroidviewTextView3"
|
||||
android:gravity="center_horizontal"/>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/fragmentandroidviewImageView2"
|
||||
android:layout_weight="1.0"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 当前电量数值+图标 -->
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1.0">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="100%"
|
||||
android:textSize="@dimen/text_title_size"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:gravity="center_horizontal"
|
||||
android:id="@+id/fragmentandroidviewTextView4"/>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/fragmentandroidviewImageView1"
|
||||
android:layout_weight="1.0"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 充电提醒数值+图标 -->
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="100%"
|
||||
android:textSize="@dimen/text_title_size"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:id="@+id/fragmentandroidviewTextView2"
|
||||
android:gravity="center_horizontal"/>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/fragmentandroidviewImageView3"
|
||||
android:layout_weight="1.0"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 充电提醒布局 -->
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:id="@+id/fragmentmainviewLinearLayout2">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:background="@drawable/charge"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="10dp"/>
|
||||
|
||||
<CheckBox
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="10dp"
|
||||
android:id="@+id/fragmentmainviewCheckBox1"/>
|
||||
|
||||
<cc.winboll.studio.powerbell.views.VerticalSeekBar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/fragmentandroidviewVerticalSeekBar1"
|
||||
android:progressTint="@color/colorCharge"
|
||||
android:progressBackgroundTint="@color/colorCharge"
|
||||
android:layout_weight="1.0"
|
||||
android:layout_margin="10dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Tips文本 -->
|
||||
<LinearLayout
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Tips"
|
||||
android:textSize="@dimen/text_content_size"
|
||||
android:id="@+id/fragmentandroidviewTextView1"
|
||||
android:background="@drawable/bg_frame"
|
||||
android:padding="10dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 3. 广告视图:关键优化→用ViewStub延迟加载(替代原直接加载的ADsBannerView) -->
|
||||
<!-- 首次启动仅占位(1px),不inflate真实广告视图,减少首次耗时 -->
|
||||
<ViewStub
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/stub_ads_banner"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout="@layout/view_ads_banner"/> <!-- 广告视图独立布局文件 -->
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@@ -1,218 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<cc.winboll.studio.powerbell.views.BackgroundView
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#FF7381FF"
|
||||
android:id="@+id/fragmentmainviewBackgroundView1"/>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/fragmentmainviewLinearLayout3"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_marginTop="10dp">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:background="@drawable/bg_frame">
|
||||
|
||||
<Switch
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/fragmentandroidviewSwitch1"
|
||||
android:padding="10dp"
|
||||
android:layout_weight="1.0"
|
||||
android:textSize="@dimen/text_title_size"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1.0"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="10dp">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1.0">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:id="@+id/fragmentmainviewLinearLayout1">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:background="@drawable/usege"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="10dp"/>
|
||||
|
||||
<CheckBox
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="10dp"
|
||||
android:id="@+id/fragmentmainviewCheckBox2"/>
|
||||
|
||||
<cc.winboll.studio.powerbell.views.VerticalSeekBar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/fragmentandroidviewVerticalSeekBar2"
|
||||
android:progressTint="@color/colorUsege"
|
||||
android:progressBackgroundTint="@color/colorUsege"
|
||||
android:layout_weight="1.0"
|
||||
android:layout_margin="10dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="100%"
|
||||
android:textSize="@dimen/text_title_size"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:id="@+id/fragmentandroidviewTextView3"
|
||||
android:gravity="center_horizontal"/>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/fragmentandroidviewImageView2"
|
||||
android:layout_weight="1.0"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1.0">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="100%"
|
||||
android:textSize="@dimen/text_title_size"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:gravity="center_horizontal"
|
||||
android:id="@+id/fragmentandroidviewTextView4"/>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/fragmentandroidviewImageView1"
|
||||
android:layout_weight="1.0"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="100%"
|
||||
android:textSize="@dimen/text_title_size"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:id="@+id/fragmentandroidviewTextView2"
|
||||
android:gravity="center_horizontal"/>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/fragmentandroidviewImageView3"
|
||||
android:layout_weight="1.0"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:id="@+id/fragmentmainviewLinearLayout2">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:background="@drawable/charge"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="10dp"/>
|
||||
|
||||
<CheckBox
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="10dp"
|
||||
android:id="@+id/fragmentmainviewCheckBox1"/>
|
||||
|
||||
<cc.winboll.studio.powerbell.views.VerticalSeekBar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/fragmentandroidviewVerticalSeekBar1"
|
||||
android:progressTint="@color/colorCharge"
|
||||
android:progressBackgroundTint="@color/colorCharge"
|
||||
android:layout_weight="1.0"
|
||||
android:layout_margin="10dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Tips"
|
||||
android:textSize="@dimen/text_content_size"
|
||||
android:id="@+id/fragmentandroidviewTextView1"
|
||||
android:background="@drawable/bg_frame"
|
||||
android:padding="10dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
7
powerbell/src/main/res/layout/view_ads_banner.xml
Normal file
7
powerbell/src/main/res/layout/view_ads_banner.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 广告视图独立布局(供ViewStub延迟加载) -->
|
||||
<cc.winboll.studio.libaes.views.ADsBannerView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/adsbanner"/>
|
||||
Reference in New Issue
Block a user