添加下载图片预览模块(未调试)
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
#Created by .winboll/winboll_app_build.gradle
|
#Created by .winboll/winboll_app_build.gradle
|
||||||
#Wed Nov 19 12:22:35 GMT 2025
|
#Wed Nov 19 13:23:38 GMT 2025
|
||||||
stageCount=4
|
stageCount=4
|
||||||
libraryProject=
|
libraryProject=
|
||||||
baseVersion=15.11
|
baseVersion=15.11
|
||||||
publishVersion=15.11.3
|
publishVersion=15.11.3
|
||||||
buildCount=15
|
buildCount=19
|
||||||
baseBetaVersion=15.11.4
|
baseBetaVersion=15.11.4
|
||||||
|
|||||||
@@ -1,14 +1,21 @@
|
|||||||
package cc.winboll.studio.powerbell.dialogs;
|
package cc.winboll.studio.powerbell.dialogs;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AlertDialog; // AndroidX 对话框
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import cc.winboll.studio.powerbell.R;
|
|
||||||
import cc.winboll.studio.libappbase.LogUtils;
|
import cc.winboll.studio.libappbase.LogUtils;
|
||||||
|
import cc.winboll.studio.libappbase.ToastUtils;
|
||||||
|
import cc.winboll.studio.powerbell.R;
|
||||||
|
import cc.winboll.studio.powerbell.utils.ImageDownloader;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||||
@@ -17,12 +24,18 @@ import cc.winboll.studio.libappbase.LogUtils;
|
|||||||
* 继承 AndroidX AlertDialog,绑定自定义布局 dialog_networkbackground.xml
|
* 继承 AndroidX AlertDialog,绑定自定义布局 dialog_networkbackground.xml
|
||||||
*/
|
*/
|
||||||
public class NetworkBackgroundDialog extends AlertDialog {
|
public class NetworkBackgroundDialog extends AlertDialog {
|
||||||
|
public static final String TAG = "NetworkBackgroundDialog";
|
||||||
|
|
||||||
// 控件引用
|
// 控件引用
|
||||||
private TextView tvTitle;
|
private TextView tvTitle;
|
||||||
private TextView tvContent;
|
private TextView tvContent;
|
||||||
private Button btnCancel;
|
private Button btnCancel;
|
||||||
private Button btnConfirm;
|
private Button btnConfirm;
|
||||||
|
private Button btnPreview;
|
||||||
|
private EditText etURL;
|
||||||
|
//private WebView webViewPreview;
|
||||||
|
ImageView ivBackgroundPreview;
|
||||||
|
Context mContext;
|
||||||
|
|
||||||
// 按钮点击回调接口(Java7 接口实现)
|
// 按钮点击回调接口(Java7 接口实现)
|
||||||
public interface OnDialogClickListener {
|
public interface OnDialogClickListener {
|
||||||
@@ -49,9 +62,10 @@ public class NetworkBackgroundDialog extends AlertDialog {
|
|||||||
* 初始化布局和控件
|
* 初始化布局和控件
|
||||||
*/
|
*/
|
||||||
private void initView() {
|
private void initView() {
|
||||||
|
mContext = this.getContext();
|
||||||
// 加载自定义布局
|
// 加载自定义布局
|
||||||
View dialogView = LayoutInflater.from(getContext())
|
View dialogView = LayoutInflater.from(getContext())
|
||||||
.inflate(R.layout.dialog_networkbackground, null);
|
.inflate(R.layout.dialog_networkbackground, null);
|
||||||
// 设置对话框内容视图
|
// 设置对话框内容视图
|
||||||
setView(dialogView);
|
setView(dialogView);
|
||||||
|
|
||||||
@@ -60,6 +74,10 @@ public class NetworkBackgroundDialog extends AlertDialog {
|
|||||||
tvContent = (TextView) dialogView.findViewById(R.id.tv_dialog_content);
|
tvContent = (TextView) dialogView.findViewById(R.id.tv_dialog_content);
|
||||||
btnCancel = (Button) dialogView.findViewById(R.id.btn_cancel);
|
btnCancel = (Button) dialogView.findViewById(R.id.btn_cancel);
|
||||||
btnConfirm = (Button) dialogView.findViewById(R.id.btn_confirm);
|
btnConfirm = (Button) dialogView.findViewById(R.id.btn_confirm);
|
||||||
|
btnPreview = (Button) dialogView.findViewById(R.id.btn_preview);
|
||||||
|
etURL = (EditText) dialogView.findViewById(R.id.et_url);
|
||||||
|
//webViewPreview = (WebView) dialogView.findViewById(R.id.webview_preview);
|
||||||
|
ivBackgroundPreview = (ImageView) findViewById(R.id.iv_background_preview);
|
||||||
|
|
||||||
// 设置按钮点击事件
|
// 设置按钮点击事件
|
||||||
setButtonClickListeners();
|
setButtonClickListeners();
|
||||||
@@ -71,27 +89,37 @@ public class NetworkBackgroundDialog extends AlertDialog {
|
|||||||
private void setButtonClickListeners() {
|
private void setButtonClickListeners() {
|
||||||
// 取消按钮:关闭对话框 + 回调外部
|
// 取消按钮:关闭对话框 + 回调外部
|
||||||
btnCancel.setOnClickListener(new View.OnClickListener() {
|
btnCancel.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
LogUtils.d("NetworkBackgroundDialog", "取消按钮点击");
|
LogUtils.d("NetworkBackgroundDialog", "取消按钮点击");
|
||||||
dismiss(); // 关闭对话框
|
dismiss(); // 关闭对话框
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
listener.onCancel();
|
listener.onCancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 确认按钮:关闭对话框 + 回调外部
|
// 确认按钮:关闭对话框 + 回调外部
|
||||||
btnConfirm.setOnClickListener(new View.OnClickListener() {
|
btnConfirm.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
LogUtils.d("NetworkBackgroundDialog", "确认按钮点击");
|
LogUtils.d("NetworkBackgroundDialog", "确认按钮点击");
|
||||||
dismiss(); // 关闭对话框
|
dismiss(); // 关闭对话框
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
listener.onConfirm();
|
listener.onConfirm();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 图片预览按钮:预览输入框地址图片
|
||||||
|
btnPreview.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
LogUtils.d("NetworkBackgroundDialog", "确认预览点击");
|
||||||
|
String url = etURL.getText().toString();
|
||||||
|
ImageDownloader.getInstance(mContext).downloadImage(url, mDownloadCallback);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -118,5 +146,50 @@ public class NetworkBackgroundDialog extends AlertDialog {
|
|||||||
public void setOnDialogClickListener(OnDialogClickListener listener) {
|
public void setOnDialogClickListener(OnDialogClickListener listener) {
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImageDownloader.DownloadCallback mDownloadCallback = new ImageDownloader.DownloadCallback(){
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(String filePath) {
|
||||||
|
ToastUtils.show(filePath);
|
||||||
|
LogUtils.d(TAG, filePath);
|
||||||
|
|
||||||
|
String imagePath = "/storage/emulated/0/Android/data/cc.winboll.studio.powerbell.beta/files/mmexport1713182627221.png";
|
||||||
|
//String imagePath = filePath;
|
||||||
|
|
||||||
|
FileInputStream fis = null;
|
||||||
|
try {
|
||||||
|
fis = new FileInputStream(imagePath);
|
||||||
|
Drawable drawable = Drawable.createFromStream(fis, null);
|
||||||
|
// 设置背景
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
|
||||||
|
ivBackgroundPreview.setBackground(drawable);
|
||||||
|
} else {
|
||||||
|
ivBackgroundPreview.setBackgroundDrawable(drawable);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
//ivBackgroundPreview.setBackgroundResource(R.drawable.default_error); // 异常时显示默认图
|
||||||
|
ivBackgroundPreview.setBackgroundResource(R.drawable.ic_launcher); // 异常时显示默认图
|
||||||
|
} finally {
|
||||||
|
// Java7 手动关闭流,避免资源泄漏
|
||||||
|
if (fis != null) {
|
||||||
|
try {
|
||||||
|
fis.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(String errorMsg) {
|
||||||
|
ToastUtils.show(errorMsg);
|
||||||
|
LogUtils.d(TAG, errorMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,294 @@
|
|||||||
|
package cc.winboll.studio.powerbell.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import cc.winboll.studio.libappbase.LogUtils;
|
||||||
|
import okhttp3.Call;
|
||||||
|
import okhttp3.Callback;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.Response;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||||
|
* @Date 2025/11/19 20:52
|
||||||
|
* @Describe 图片下载工具类(单例模式)
|
||||||
|
* 功能:下载网络图片到缓存目录、清理过期文件、获取最新下载文件
|
||||||
|
*/
|
||||||
|
public class ImageDownloader {
|
||||||
|
public static final String TAG = "ImageDownloader";
|
||||||
|
// 单例实例
|
||||||
|
private static ImageDownloader sInstance;
|
||||||
|
// OkHttp 客户端(全局复用,提升性能)
|
||||||
|
private OkHttpClient mOkHttpClient;
|
||||||
|
// 缓存目录:/data/data/应用包名/cache/networkdownload
|
||||||
|
private File mCacheDir;
|
||||||
|
// 过期时间:7天(单位:毫秒),可按需调整
|
||||||
|
private static final long EXPIRE_TIME = 7 * 24 * 3600 * 1000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 私有构造(单例模式禁止外部实例化)
|
||||||
|
* @param context 上下文(用于获取缓存目录)
|
||||||
|
*/
|
||||||
|
private ImageDownloader(Context context) {
|
||||||
|
// 初始化 OkHttp 客户端(设置超时时间)
|
||||||
|
mOkHttpClient = new OkHttpClient.Builder()
|
||||||
|
.connectTimeout(10, TimeUnit.SECONDS)
|
||||||
|
.readTimeout(15, TimeUnit.SECONDS)
|
||||||
|
.writeTimeout(15, TimeUnit.SECONDS)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 初始化缓存目录:networkdownload
|
||||||
|
initCacheDir(context);
|
||||||
|
// 初始化时清理过期文件
|
||||||
|
clearExpiredFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单例获取方法(线程安全)
|
||||||
|
* @param context 上下文(建议使用 Application 上下文避免内存泄漏)
|
||||||
|
* @return 单例实例
|
||||||
|
*/
|
||||||
|
public static synchronized ImageDownloader getInstance(Context context) {
|
||||||
|
if (sInstance == null) {
|
||||||
|
// 使用 Application 上下文,防止 Activity 销毁导致的内存泄漏
|
||||||
|
sInstance = new ImageDownloader(context.getApplicationContext());
|
||||||
|
}
|
||||||
|
return sInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化缓存目录:若不存在则创建
|
||||||
|
*/
|
||||||
|
private void initCacheDir(Context context) {
|
||||||
|
// 获取应用内置缓存目录(无需权限)
|
||||||
|
File cacheRoot = context.getCacheDir();
|
||||||
|
mCacheDir = new File(cacheRoot, "networkdownload");
|
||||||
|
|
||||||
|
// 若目录不存在则创建(包括父目录)
|
||||||
|
if (!mCacheDir.exists()) {
|
||||||
|
boolean isCreated = mCacheDir.mkdirs();
|
||||||
|
if (isCreated) {
|
||||||
|
LogUtils.d("ImageDownloader", "networkdownload 缓存目录创建成功:" + mCacheDir.getAbsolutePath());
|
||||||
|
} else {
|
||||||
|
LogUtils.e("ImageDownloader", "networkdownload 缓存目录创建失败");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LogUtils.d("ImageDownloader", "networkdownload 缓存目录已存在:" + mCacheDir.getAbsolutePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理过期文件(最后修改时间超过 EXPIRE_TIME 的文件)
|
||||||
|
*/
|
||||||
|
private void clearExpiredFiles() {
|
||||||
|
if (mCacheDir == null || !mCacheDir.exists()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File[] files = mCacheDir.listFiles();
|
||||||
|
if (files == null || files.length == 0) {
|
||||||
|
LogUtils.d("ImageDownloader", "缓存目录无文件,无需清理");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
int deleteCount = 0;
|
||||||
|
|
||||||
|
// 遍历所有文件,删除过期文件
|
||||||
|
for (File file : files) {
|
||||||
|
long lastModifyTime = file.lastModified();
|
||||||
|
if (currentTime - lastModifyTime > EXPIRE_TIME) {
|
||||||
|
if (file.delete()) {
|
||||||
|
deleteCount++;
|
||||||
|
LogUtils.d("ImageDownloader", "删除过期文件:" + file.getName());
|
||||||
|
} else {
|
||||||
|
LogUtils.e("ImageDownloader", "删除过期文件失败:" + file.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LogUtils.d("ImageDownloader", "过期文件清理完成,共删除 " + deleteCount + " 个文件");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载网络图片到缓存目录
|
||||||
|
* @param imageUrl 图片网络链接
|
||||||
|
* @param callback 下载结果回调(成功/失败)
|
||||||
|
*/
|
||||||
|
public void downloadImage(final String imageUrl, final DownloadCallback callback) {
|
||||||
|
// 校验参数
|
||||||
|
if (TextUtils.isEmpty(imageUrl)) {
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onFailure("图片链接为空");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCacheDir == null || !mCacheDir.exists()) {
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onFailure("缓存目录不存在");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建 OkHttp 请求
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(imageUrl)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 异步下载(避免阻塞主线程)
|
||||||
|
mOkHttpClient.newCall(request).enqueue(new Callback() {
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call call, IOException e) {
|
||||||
|
// 下载失败,回调主线程
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onFailure("下载失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
LogUtils.e("ImageDownloader", "图片下载失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call call, Response response) throws IOException {
|
||||||
|
if (!response.isSuccessful()) {
|
||||||
|
// 响应失败(如 404、500)
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onFailure("响应失败:" + response.code());
|
||||||
|
}
|
||||||
|
LogUtils.e("ImageDownloader", "图片响应失败,状态码:" + response.code());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 响应成功,写入文件
|
||||||
|
InputStream inputStream = null;
|
||||||
|
FileOutputStream outputStream = null;
|
||||||
|
try {
|
||||||
|
inputStream = response.body().byteStream();
|
||||||
|
// 生成 UUID 唯一文件名(保留原文件后缀)
|
||||||
|
String fileExtension = getFileExtension(imageUrl);
|
||||||
|
String fileName = UUID.randomUUID().toString() + fileExtension;
|
||||||
|
File imageFile = new File(mCacheDir, fileName);
|
||||||
|
|
||||||
|
// 写入文件
|
||||||
|
outputStream = new FileOutputStream(imageFile);
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
int len;
|
||||||
|
while ((len = inputStream.read(buffer)) != -1) {
|
||||||
|
outputStream.write(buffer, 0, len);
|
||||||
|
}
|
||||||
|
outputStream.flush();
|
||||||
|
|
||||||
|
// 下载成功,回调主线程并返回文件路径
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onSuccess(imageFile.getAbsolutePath());
|
||||||
|
}
|
||||||
|
LogUtils.d("ImageDownloader", "图片下载成功:" + imageFile.getAbsolutePath());
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onFailure("文件写入失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
LogUtils.e("ImageDownloader", "图片写入失败:" + e.getMessage());
|
||||||
|
} finally {
|
||||||
|
// 关闭流(Java7 手动关闭,避免资源泄漏)
|
||||||
|
if (inputStream != null) {
|
||||||
|
try {
|
||||||
|
inputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (outputStream != null) {
|
||||||
|
try {
|
||||||
|
outputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 关闭响应体
|
||||||
|
if (response.body() != null) {
|
||||||
|
response.body().close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 networkdownload 目录中最后下载的文件(按修改时间排序)
|
||||||
|
* @return 最后下载的文件路径(null 表示无文件)
|
||||||
|
*/
|
||||||
|
public String getLastDownloadedFile() {
|
||||||
|
if (mCacheDir == null || !mCacheDir.exists()) {
|
||||||
|
LogUtils.e("ImageDownloader", "缓存目录不存在");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
File[] files = mCacheDir.listFiles();
|
||||||
|
if (files == null || files.length == 0) {
|
||||||
|
LogUtils.d("ImageDownloader", "缓存目录无文件");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按最后修改时间降序排序,取第一个即为最新文件
|
||||||
|
File lastFile = files[0];
|
||||||
|
for (File file : files) {
|
||||||
|
if (file.lastModified() > lastFile.lastModified()) {
|
||||||
|
lastFile = file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LogUtils.d("ImageDownloader", "最后下载的文件:" + lastFile.getAbsolutePath());
|
||||||
|
return lastFile.getAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工具方法:从图片链接中提取文件后缀(如 .png、.jpg)
|
||||||
|
* @param imageUrl 图片链接
|
||||||
|
* @return 文件后缀(含点号,若无法提取则返回 .jpg)
|
||||||
|
*/
|
||||||
|
private String getFileExtension(String imageUrl) {
|
||||||
|
if (TextUtils.isEmpty(imageUrl)) {
|
||||||
|
return ".jpg";
|
||||||
|
}
|
||||||
|
|
||||||
|
int lastDotIndex = imageUrl.lastIndexOf(".");
|
||||||
|
int lastSlashIndex = imageUrl.lastIndexOf("/");
|
||||||
|
// 确保后缀在最后一个斜杠之后,且长度合理(1-5 个字符)
|
||||||
|
if (lastDotIndex > lastSlashIndex && lastDotIndex < imageUrl.length() - 1) {
|
||||||
|
String extension = imageUrl.substring(lastDotIndex);
|
||||||
|
if (extension.length() <= 5) {
|
||||||
|
return extension.toLowerCase(); // 统一转为小写
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 无法提取后缀时,默认使用 .jpg
|
||||||
|
return ".jpg";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载结果回调接口(Java7 接口实现)
|
||||||
|
*/
|
||||||
|
public interface DownloadCallback {
|
||||||
|
/**
|
||||||
|
* 下载成功
|
||||||
|
* @param filePath 图片保存路径
|
||||||
|
*/
|
||||||
|
void onSuccess(String filePath);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载失败
|
||||||
|
* @param errorMsg 失败原因
|
||||||
|
*/
|
||||||
|
void onFailure(String errorMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,60 +1,93 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_margin="16dp"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:layout_margin="16dp"
|
||||||
android:background="@android:color/white"
|
android:orientation="vertical"
|
||||||
android:padding="20dp"
|
android:background="@android:color/white"
|
||||||
android:radius="12dp"> <!-- 圆角背景(需Android 5.0+,低版本可改用shapedrawable) -->
|
android:padding="20dp"
|
||||||
|
android:radius="12dp">
|
||||||
|
|
||||||
<!-- 标题 -->
|
<TextView
|
||||||
<TextView
|
android:id="@+id/tv_dialog_title"
|
||||||
android:id="@+id/tv_dialog_title"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:text="网络后台提示"
|
||||||
android:text="网络后台提示"
|
android:textSize="18sp"
|
||||||
android:textSize="18sp"
|
android:textColor="@android:color/black"
|
||||||
android:textColor="@android:color/black"
|
android:textStyle="bold"/>
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<!-- 内容说明 -->
|
<LinearLayout
|
||||||
<TextView
|
android:orientation="horizontal"
|
||||||
android:id="@+id/tv_dialog_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_marginTop="12dp">
|
||||||
android:layout_marginTop="12dp"
|
|
||||||
android:text="应用正在后台使用网络,是否继续允许?"
|
|
||||||
android:textSize="15sp"
|
|
||||||
android:textColor="@android:color/darker_gray" />
|
|
||||||
|
|
||||||
<!-- 按钮容器(水平排列) -->
|
<EditText
|
||||||
<LinearLayout
|
android:layout_width="0dp"
|
||||||
android:layout_width="match_parent"
|
android:ems="10"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="20dp"
|
android:layout_weight="1.0"
|
||||||
android:orientation="horizontal"
|
android:id="@+id/et_url"/>
|
||||||
android:gravity="end">
|
|
||||||
|
|
||||||
<!-- 取消按钮 -->
|
<Button
|
||||||
<Button
|
android:layout_width="wrap_content"
|
||||||
android:id="@+id/btn_cancel"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:text="↻"
|
||||||
android:layout_height="wrap_content"
|
android:id="@+id/btn_preview"/>
|
||||||
android:text="取消"
|
|
||||||
android:textSize="14sp"
|
|
||||||
android:background="@android:drawable/btn_default_small"
|
|
||||||
android:layout_marginRight="8dp" />
|
|
||||||
|
|
||||||
<!-- 确认按钮 -->
|
</LinearLayout>
|
||||||
<Button
|
|
||||||
android:id="@+id/btn_confirm"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="允许"
|
|
||||||
android:textSize="14sp"
|
|
||||||
android:background="@android:drawable/btn_default_small" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="100dp"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:layout_gravity="center_vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:id="@+id/iv_background_preview"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_dialog_content"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:text="应用正在后台使用网络,是否继续允许?"
|
||||||
|
android:textSize="15sp"
|
||||||
|
android:textColor="@android:color/darker_gray"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="end">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn_cancel"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="取消"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:background="@android:drawable/btn_default_small"
|
||||||
|
android:layout_marginRight="8dp"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn_confirm"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="允许"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:background="@android:drawable/btn_default_small"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user