小项目总体是要实现网页版应用的随意切换,效果类似于浏览器多个标签,可以随意切换标签
描述一下首页采用webview加载各种网页,底部通过一个dialogFragment包裹一个recyclerview来展示缩略图,里面的难点有几个,
1:先获取webview页面的截图,然后再生成缩略图,大体实现如下:
public class ImageUtils {
public Bitmap captureView(View view){
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
// 重新测量一遍View的宽高
view.measure(View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(view.getHeight(), View.MeasureSpec.EXACTLY));
// 确定View的位置
view.layout((int)view.getX(), (int)view.getY(), (int)view.getX() + view.getMeasuredWidth(),
(int)view.getY() + view.getMeasuredHeight());
// 生成View宽高一样的Bitmap
Bitmap mBitmap = Bitmap.createBitmap(view.getDrawingCache(), 0, 0, view.getMeasuredWidth(),
view.getMeasuredHeight());
view.setDrawingCacheEnabled(false);
view.destroyDrawingCache();
return mBitmap;
}
}
生成截图后,面临第二个问题,底部列表直接展示会导致oom,所以要采用时间换空间,先把bitmap转换成其他格式文件保存到本地,然后释放掉bitmap占用的内存,之后再从本地读取,
之后再用glide来加载图片。大体代码如下:
Bitmap mBitmap = mImageUtils.captureView(mWebView);
byte[] mByte = DealBitmap2Byte.getByteFromBitmap(mBitmap);//把bitmap转换成byte
//先保存本地
mmkvUtil.saveArray(codes);
recycleBitmap(mBitmap);//回收bitmap
codes = mmkvUtil.getArray();//从本地获取list
//传递数据,用来之后展示
showDialog.setData(codes, mWebView);
public class DealBitmap2Byte {
public static byte[] getByteFromBitmap(Bitmap bitmap){
try{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.WEBP,30,baos);//这里可以调整生成图片的大小
byte [] bytes = baos.toByteArray();
baos.flush();
baos.close();
return bytes;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
最后用glide加载
public class ListForItemCodesAdapter extends BaseQuickAdapter<ImageItem, BaseViewHolder> {
private final Context mContext;
private final WebView mWebView;
public ListForItemCodesAdapter(int layoutResId, Context context, WebView webView) {
super(layoutResId);
mContext = context;
mWebView = webView;
}
@Override
protected void convert(BaseViewHolder helper, ImageItem item) {
int width = mWebView.getMeasuredWidth();
int height = mWebView.getMeasuredHeight();
int inSimpleSize = 3;
int mWidth = width / inSimpleSize;
int mHeight = height / inSimpleSize;
// BitmapDrawable oldDrawable = item.getmItemBitmap();
byte [] mBitmap = item.getmItemBitmap();
//
// Bitmap mBitmap = ThumbnailUtils.extractThumbnail(oldBitmap, mWidth, mHeight);
// Drawable drawable = new BitmapDrawable(mBitmap);
// byte [] bytes = DealBitmapByte.getByteFromBitmap(mBitmap);
ImageView imageview = helper.getView(R.id.img_web);
// helper.setText(R.id.tv_title,item.getTitle());
Glide
.with(mContext)
.asDrawable()
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.load(mBitmap)
.override(mWidth,mHeight)
.into(imageview);
}
@Override
public void onViewRecycled(@NonNull BaseViewHolder helper) {
super.onViewRecycled(helper);
ImageView img = helper.getView(R.id.img_web);
if (img != null) {
Glide.with(mContext).clear(img);
}
}
}
之后添加新的页面就点击底部的+号来添加
新的页面如下:
实现的难点主要是整体是个列表,然后每个标题下面也是动态的列表,用recyclerview嵌套rcycleview会有很多问题,所以最终用一个recyclerview来实现:
implementation 'com.github.luizgrp:SectionedRecyclerViewAdapter:v3.2.0'//这里用到了第三方的插件
核心代码如下:
final LoadMoviesUseCase loadMoviesUseCase = new LoadMoviesUseCase();
sectionedAdapter.addSection(new MovieSection(getString(R.string.top_rated_movies_topic),
loadMoviesUseCase.execute(this, R.array.top_rated_movies), this));
sectionedAdapter.addSection(new MovieSection(getString(R.string.most_popular_movies_topic),
loadMoviesUseCase.execute(this, R.array.most_popular_movies), this));
sectionedAdapter.addSection(new MovieSection(getString(R.string.most_used),
loadMoviesUseCase.execute(this, R.array.Most_used), this));
//同时recycleview需要这样配置
sectionedAdapter = new SectionedRecyclerViewAdapter();
//recycleview设置
mRecyclerView = binding.child.rvList;
final GridLayoutManager glm = new GridLayoutManager(this, 3);
glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
if (sectionedAdapter.getSectionItemViewType(position) == SectionedRecyclerViewAdapter.VIEW_TYPE_HEADER) {
return 3;
}
return 1;
}
});
mRecyclerView.setLayoutManager(glm);
mRecyclerView.setAdapter(sectionedAdapter);
//设置item的点击事件
@Override
public void onItemRootViewClicked(@NonNull MovieSection section, int itemAdapterPosition) {
int index = sectionedAdapter.getPositionInSection(itemAdapterPosition);
List<Movie> movieList = section.getList();
Movie movie = movieList.get(index);
// Toast.makeText(this, "点击的位置是"+index+movie.url, Toast.LENGTH_SHORT).show();
Intent intent = new Intent(AppSetsActivity.this, MainActivity.class);
intent.putExtra("url",movie.url);
intent.putExtra("name",movie.name);
startActivity(intent);
}
资源链接如下
https://download.csdn.net/download/u013075460/85442143