- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我最近使用我使用媒体查询和媒体存储设计的自定义画廊对显示图片进行了一些测试...效果很好,但我真的需要做一些自定义的事情。
我不希望图片被扫描或在媒体存储中可用,因此我想让我的应用程序扫描目录并创建缩略图并显示这些缩略图。
我发现很难找到任何高质量的例子来做到这一点。
谁能帮忙举个小例子。
这就是我想要做的。
我想我只是需要一点帮助来从目录中获取图片,因为没有存储在 int eh mediastore 中,所以我不能使用查询。另一件让我担心的事情是,我需要为这些图像中的每一个创建缩略图(动态??),因为显示图像但缩小尺寸我怀疑这对性能非常不利。
谁能伸出援手?
提前致谢
最佳答案
我刚才也是这么做的。您必须将图像所在的文件夹名称传递给 setBaseFolder
。此方法依次调用 refresh()
,它使用 FilenameFilter
(未包含代码但很容易实现)获取所有名为 orig_... 的图像。从该文件夹中提取 .jpg
并将其保存在 mFileList
中。然后我们调用 notifyDataSetChanged()
,这反过来会为每个单元格触发 getView()
。
现在,在 getView()
中,我们要么从缓存中获取缩略图位图(如果已经存在),否则我们创建一个灰色占位符并启动 ThumbnailBuilder
以分别创建缩略图从中获取位图。
我认为您必须稍微更改 ThumbnailBuilder
,因为我创建了相当大的“缩略图”(500x500),因为我也需要调整大小的图像用于其他目的。另外,当我处理相机拍摄的照片时,那里有一些东西,根据 exif 信息旋转图像。但基本上,ThumbnailBuilder
只是检查是否已经存在缩略图(我的缩略图放置在同一个文件夹中,但前缀为 small_
而不是 orig_
) - 如果缩略图已经存在,我们将其作为 Bitmap
获取并完成,否则生成图像。最后,在 onPostExecute()
中将位图设置为 ImageView。
public class PhotoAdapter extends BaseAdapter {
private Context mContext;
private int mCellSize;
private File mFolder;
private File[] mFileList;
private Map<Object, Bitmap> mThumbnails = new HashMap<Object, Bitmap>();
private Set<Object> mCreatingTriggered = new HashSet<Object>(); // flag that creating already triggered
public PhotoAdapter(Context context, int cellSize) {
mContext = context;
mCellSize = cellSize;
}
@Override
public int getCount() {
if (mFolder == null) {
return 0; // don't do this
} else {
return mFileList.length;
}
}
@Override
public Object getItem(int position) {
return mFileList[position];
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView view = (ImageView)convertView;
if (view == null) {
view = new ImageView(mContext);
view.setLayoutParams(new GridView.LayoutParams(mCellSize, mCellSize));
view.setScaleType(ImageView.ScaleType.CENTER_CROP);
view.setPadding(8, 8, 8, 8);
view.setBackgroundColor(0xFFC6CCD3);
}
Object item = getItem(position);
Bitmap bm = mThumbnails.get(item);
if (bm == null) {
view.setImageBitmap(null);
if (!mCreatingTriggered.contains(item)) {
mCreatingTriggered.add(item);
new ThumbnailBuilder(view, (File)item).execute();
}
} else {
view.setImageBitmap(bm);
}
return view;
}
public void setBaseFolder(File baseFolder) {
if (baseFolder == null) return;
if (!baseFolder.equals(mFolder)) {
releaseThumbnails();
mFolder = baseFolder;
}
refresh();
}
public void refresh() {
if (mFolder == null) {
return;
}
mFileList = mFolder.listFiles(EtbApplication.origImageFilenameFilter);
if (mFileList == null) mFileList = new File[0];
notifyDataSetChanged();
}
public void releaseThumbnails() {
for (Bitmap bm : mThumbnails.values()) {
bm.recycle();
}
mThumbnails.clear();
}
// ------------------------------------------------------------------------------------ Asynchronous Thumbnail builder
private class ThumbnailBuilder extends AsyncTask<Void, Integer, Bitmap> {
private ImageView mView;
private File mFile;
public ThumbnailBuilder(ImageView view, File file) {
mView = view;
mFile = file;
}
@Override
protected Bitmap doInBackground(Void... params) {
Log.d("adapter", "make small image and thumbnail");
try {
return createThumbnail(mFile.getAbsolutePath());
} catch (Exception e) {
return null;
}
}
@Override
protected void onPostExecute(Bitmap result) {
if (result != null) {
mView.setImageBitmap(result);
mThumbnails.put(mFile, result);
} else {
mView.setImageResource(R.drawable.ic_launcher);
}
}
/**
* Creates Thumbnail (also rotates according to exif-info)
* @param file
* @return
* @throws IOException
*/
private Bitmap createThumbnail(String file) throws IOException {
File thumbnailFile = new File(file.replace("orig_", "small_"));
// If a small image version already exists, just load it and be done.
if (thumbnailFile.exists()) {
return BitmapFactory.decodeFile(thumbnailFile.getAbsolutePath());
}
// Decode image size
BitmapFactory.Options bounds = new BitmapFactory.Options();
bounds.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file, bounds);
if ((bounds.outWidth == -1) || (bounds.outHeight == -1))
return null;
int w, h;
if (bounds.outWidth > bounds.outHeight) { // Querformat
w = 500;
h = 500 * bounds.outHeight / bounds.outWidth;
} else { // Hochformat
h = 500;
w = 500 * bounds.outWidth / bounds.outHeight;
}
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 4; // resample -- kleiner aber noch nicht die 500 Pixel, die kommen dann unten
Bitmap resizedBitmap = BitmapFactory.decodeFile(file, opts);
resizedBitmap = Bitmap.createScaledBitmap(resizedBitmap, w, h, true);
ExifInterface exif = new ExifInterface(file);
String orientString = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
int orientation = orientString != null ? Integer.parseInt(orientString) : ExifInterface.ORIENTATION_NORMAL;
int rotationAngle = 0;
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) rotationAngle = 90;
if (orientation == ExifInterface.ORIENTATION_ROTATE_180) rotationAngle = 180;
if (orientation == ExifInterface.ORIENTATION_ROTATE_270) rotationAngle = 270;
Matrix matrix = new Matrix();
matrix.setRotate(rotationAngle, (float) resizedBitmap.getWidth() / 2, (float) resizedBitmap.getHeight() / 2);
Bitmap rotatedBitmap = Bitmap.createBitmap(resizedBitmap, 0, 0, w, h, matrix, true);
resizedBitmap.recycle();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
thumbnailFile.createNewFile();
FileOutputStream fo = new FileOutputStream(thumbnailFile);
fo.write(bytes.toByteArray());
fo.close();
//new File(file).delete(); // Originalbild löschen
return rotatedBitmap;
}
}
}
关于Android:扫描目录并显示图片(缩略图)(图片不存储在媒体存储中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12190181/
使用 C# (VS2008) 和 WIA - 扫描到 TIFF 格式; 当我在平板或文档进纸器上使用扫描仪扫描 1 页时,该方法执行没有任何问题。当我将多个表单加载到进纸器时,扫描第一页后执行停止(保
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
给定一个列表 :: [(Foo, Bar)] ,我想在 Bar 上执行 scanl1 s,但保留他们的 Foo “标签”。 IE。我想要一个类型为 :: [(a, b)] -> ([b] -> [c]
我有一个 HBase 表,我需要从多个范围获取结果。例如,我可能需要从不同范围获取数据,例如第 1-6 行、100-150..... 我知道对于每次扫描,我可以定义开始行和停止行。但是如果我有 6 个
我看到了这段代码。我是 C 语言的新手,所以请原谅。 while下面的循环将继续循环 if i = SIZE,则 == 是无关紧要的,因为它根本不会被执行。如果 i 小于 SIZE 那么 scanf(
这是一个关于编译过程的相当技术性的问题ABAP代码。 我知道有ABAP解析器和扫描器类实际上调用 C 内核函数来完成实际工作。然后就是代码补全事务的功能,该事务以 ABAP 列表或 XML 的形式返回
给定以下程序: int main(){ float x = non_det_float(); float y = NAN; if (isnan(y) && x == 1.0f){
我在工作中使用由供应商生成的二维码。实际上我需要通过网站手动记录所有这些项目。 QR 码包含所有这些数据,所以我想创建一个自动执行操作的应用。 例如,二维码表示“AAA|BBB|CCC|123”。我想
我有一个像这样的字符串:@"ololo width: 350px jijiji width:440px ... text=12... "我想将@"width: "之后的所有数字替换为280。所以在扫描
我在玩 scanf 时遇到了一个小问题……更具体地说,我想读取整个输入,然后忽略其余部分。让我告诉你我的意思: #include int main(void) { int number_of
我正在使用 matlab/octave 创建扫描/线性调频信号,我的结束信号似乎以错误的频率结束。我该如何修复它,以便信号以正确的频率结束。 PS:我不能在 Octave 音程中使用 chirp 命令
我正在寻找一个可以扫描 WiFi 网络并打印所有 SSID 的程序。我试过 scapy 但我失败了。我正在使用 pyCharm 编辑器。 我试过这段代码: from scapy.all import
概述 Linux 完全是用于大型服务器的最流行和最安全的操作系统之一。尽管它被广泛使用,但它仍然容易受到网络攻击。黑客以服务器为目标,窃取有价值的信息。所以迫切需要开发反黑客方法来应对安全漏洞和恶
如何获取我的 Git 存储库的某种统计信息? 我目前在 BitBucket 中托管 Git 存储库,想查找以下详细信息: 提交总数 使用过的编程语言 每种编程语言的总代码行数 您认为这可以实现吗?还是
我目前正在使用以下代码来扫描作为申请表的一部分上传的文件: $safe_path = escapeshellarg($dir . $file); $command = '/usr/bin/clamsc
我在存储库中有十几个项目。存储库结构如下所示: / ------- + project1 +------- trunk +------- tags +----
我正在使用 Dynamo DB 并想使用过滤器扫描一个表。例如,是否可以使用全局二级索引仅扫描表中的特定行? 最佳答案 这不可能!扫描始终针对基表中的所有行,当您扫描索引表作为响应时,您将仅获得该索引
我正在尝试从这里使用 SOLStumbler:Accessing & Using the MobileWiFi.framework扫描 wifi 网络。我知道苹果不支持这一点,但它是用于教育目的和实验
我知道 iPhone 蓝牙功能在 3.0 之前无法通过 SDK 访问,但是需要多长时间才能找到该区域的设备?它取决于该区域的设备数量吗?如果范围内有大约 5 个设备,扫描发现所有设备是否需要花费 30
我正在使用Elasticsearch 6.2,并且有一些查询可以分析大量文档。我正在对索引内的一个字段进行排序。 Elasticsearch检查10.000个文档(默认配置值),然后将它们分页返回。
我是一名优秀的程序员,十分优秀!