经过整整一周的学习,总算实现了android中源生背景的修改。效果如下:

分别是修改前的原始界面、选择背景设置界面以及最后的效果图。

之前一直想用ScrollView来实现这个效果,后来发现用Gallery会简单很多。虽然Gallery被谷歌抛弃了,不过在4.0源码中还是有着它的大量身影。

设计思路很简单:布局->事件->处理->保存状态。布局文件参考的源码Launcher中的wallpaperchooer。事件处理则是使用StartActivityForResult来获得图片的ResID。处理是简单的获得背景layout后用获得的ResID来进行填充。保存状态这一步暂时还没有来的及做,所以,一旦手机重启,背景界面就会重置。。。

布局文件如下(我弄懂的地方已注释):

public class BackgroundChooserFragment extends Fragment implements

AdapterView.OnItemSelectedListener, AdapterView.OnItemClickListener{

private ArrayList mThumbs; //下方的小图

private ArrayList mImages; //用做背景的大图

private Bitmap mBitmap = null; //绘图时会用到bitmap

private WallpaperLoader mLoader; //加载图片

private WallpaperDrawable mWallpaperDrawable = new WallpaperDrawable(); //图片的绘制

private Intent intent; //用来向Launcher回传ResID

@Override

public void onCreate(Bundle savedInstanceState) { //系统创建Fragments 时调用,

//可做执行初始化工作或者当程

//序被暂停或停止时用来恢复状态,

//跟Activity 中的onCreate相当。

super.onCreate(savedInstanceState);

}

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,

Bundle savedInstanceState) {// 用于首次绘制用户界面的回调方法,必须返回要创

//建的Fragments 视图UI。假如你不希望提供

//Fragments 用户界面则可以返回NULL。

// TODO Auto-generated method stub

findWallpapers();

View view = inflater.inflate(R.layout.background_dialogchooser, container, false);

//在实际开发中LayoutInflater这个类还是非常有用的,它的作用类似于findViewById()。不同点是

//LayoutInflater是用来找res/layout/下的xml布局文件,并且实例化;而findViewById()是找xml

//布局文件下的具体widget控件(如Button、TextView等)。

view.setBackgroundDrawable(mWallpaperDrawable);//铺设背景图片

final Gallery gallery = (Gallery) view.findViewById(R.id.background_gallery); //获得Gallery

gallery.setCallbackDuringFling(false);

gallery.setOnItemSelectedListener(this);

gallery.setAdapter(new ImageAdapter(getActivity())); //为Gallery添加适配器,左右的拖动就是在这里实现的

View setButton = view.findViewById(R.id.background_set);

setButton.setOnClickListener(new Button.OnClickListener() {

@Override

public void onClick(View v) {

selectWallpaper(gallery.getSelectedItemPosition());

}

});

return view;

}

private void selectWallpaper(int position) {

Activity activity = getActivity(); //这是个fragment,所以必需要先获得父Activity才能使用Intent

intent = new Intent(activity, Launcher.class);

intent.putExtra("background", mImages.get(position));

activity.setResult(Activity.RESULT_OK,intent); //数据的回传在这里

activity.finish(); //调用finish时会马上执行intent

}

private void findWallpapers() { //本方法用来加载图片资源

mThumbs = new ArrayList(24); //最多24张图片

mImages = new ArrayList(24);

final Resources resources = getResources();

final String packageName = resources.getResourcePackageName(R.array.wallpapers);

addWallpapers(resources, packageName, R.array.wallpapers);

addWallpapers(resources, packageName, R.array.extra_wallpapers);

//同一个包下的两个数组文件

}

private void addWallpapers(Resources resources, String packageName, int list) {

final String[] extras = resources.getStringArray(list);

for (String extra : extras) {

//使用getIdentifier()获取资源Id,参数(ID名,文件夹名,包名)

int res = resources.getIdentifier(extra, "drawable", packageName);

if (res != 0) {

final int thumbRes = resources.getIdentifier(extra + "_small",

"drawable", packageName);

if (thumbRes != 0) {

mThumbs.add(thumbRes);

mImages.add(res);

}

}

}

}

private class ImageAdapter extends BaseAdapter implements ListAdapter, SpinnerAdapter {

//适配器,烦恼了我很久的东西

private LayoutInflater mLayoutInflater;

ImageAdapter(Activity activity) {

mLayoutInflater = activity.getLayoutInflater();

}

public int getCount() {

return mThumbs.size();

}

public Object getItem(int position) {

return position;

}

public long getItemId(int position) {

return position;

}

public View getView(int position, View convertView, ViewGroup parent) {

View view;

//先获得小图的布局文件,然后用一个image来填充图。最后返回该布局文件View

if (convertView == null) {

view = mLayoutInflater.inflate(R.layout.wallpaper_item, parent, false);

} else {

view = convertView;

}

ImageView image = (ImageView) view.findViewById(R.id.wallpaper_image);

int thumbRes = mThumbs.get(position);

image.setImageResource(thumbRes);

Drawable thumbDrawable = image.getDrawable();

thumbDrawable.setDither(true); //大幅减少图片的失真

return view;

}

}

class WallpaperLoader extends AsyncTask {

//AsyncTask是抽象类.AsyncTask定义了三种泛型类型 Params,Progress和Result。

//Params 启动任务执行的输入参数,比如HTTP请求的URL。这里是int

//Progress 后台任务执行的百分比。

//Result 后台执行任务最终返回的结果,比如String。这里是Bitmap

//相当于一个小的线程,在背后偷偷运行一点不复杂的东西

BitmapFactory.Options mOptions;

WallpaperLoader() {

mOptions = new BitmapFactory.Options();

mOptions.inDither = false;

mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;

}

@Override

protected Bitmap doInBackground(Integer... params) {

if (isCancelled() || !isAdded()) {

return null;

}

try {

return BitmapFactory.decodeResource(getResources(),

mImages.get(params[0]), mOptions);

} catch (OutOfMemoryError e) {

return null;

}

}

//为后面的Excute定义操作

@Override

protected void onPostExecute(Bitmap b) {

if (b == null) return;

if (!isCancelled() && !mOptions.mCancel) {

// Help the GC

if (mBitmap != null) {

mBitmap.recycle();

}

View v = getView();

if (v != null) {

mBitmap = b;

mWallpaperDrawable.setBitmap(b);

v.postInvalidate();

} else {

mBitmap = null;

mWallpaperDrawable.setBitmap(null);

}

mLoader = null;

} else {

b.recycle();

}

}

void cancel() {

mOptions.requestCancelDecode();

super.cancel(true);

}

}

//该方法实现了在背景区域上的图像绘制

static class WallpaperDrawable extends Drawable {

Bitmap mBitmap;

int mIntrinsicWidth;

int mIntrinsicHeight;

/* package */void setBitmap(Bitmap bitmap) {

mBitmap = bitmap;

if (mBitmap == null)

return;

mIntrinsicWidth = mBitmap.getWidth();

mIntrinsicHeight = mBitmap.getHeight();

}

@Override

public void draw(Canvas canvas) {

if (mBitmap == null) return;

int width = canvas.getWidth();

int height = canvas.getHeight();

int x = (width - mIntrinsicWidth) / 2;

Log.i("bruce","width " + width);

Log.i("bruce","mIntrinsicWidth "+mIntrinsicWidth);

int y = (height - mIntrinsicHeight) / 2;

Log.i("bruce","height "+height);

Log.i("bruce","mIntrinsicHeight "+mIntrinsicHeight);

canvas.drawBitmap(mBitmap, x, y, null);

}

@Override

public int getOpacity() {

return android.graphics.PixelFormat.OPAQUE;

}

@Override

public void setAlpha(int alpha) {

// Ignore

}

@Override

public void setColorFilter(ColorFilter cf) {

// Ignore

}

}

@Override

public void onNothingSelected(AdapterView> parent) {

}

@Override

public void onItemClick(AdapterView> parent, View view, int position, long id) {

selectWallpaper(position);

}

// Selection handler for the embedded Gallery view

@Override

public void onItemSelected(AdapterView> parent, View view, int position, long id) {

if (mLoader != null ) {

mLoader.cancel();

}

mLoader = (WallpaperLoader) new WallpaperLoader().execute(position);

}

@Override

public void onDestroy() {

Log.i("bruce","onDestroy");

super.onDestroy();

if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {

mLoader.cancel(true);

mLoader = null;

}

}

}布局文件中的WallpaperLoader和WallpaperDrawable方法现在暂时还没有细看,等有时间了会继续研究下。

至于事件和处理,他们相比于布局而言简单很多。事件就是一个button的单击。处理需要在Launcher中进行,是简单的布局文件背景设置。这里我就不列源码赘述了。

下一步的工作就是学习savedInstanceState了,将选择的结果存储到savedInstanceState中,然后这个小小的研究就可以宣告一段落了。

日记背景 android,android学习日记:4.0源生背景修改相关推荐

  1. android用IO实现日记的读写,黑马学习日记_IO篇(首先部分)

    ----------------------android开发.java培训.期待与您交流! ---------------------- IO:主要用来处理设备之间的数据传输(如硬盘上的文件,内存中 ...

  2. 安卓开发学习日记第四天番外篇_用Kotlin炒冷饭——越炒越小_莫韵乐的欢乐笔记

    安卓开发学习日记第四天番外篇--用Kotlin炒冷饭--越炒越小 前情提要 安卓开发学习日记第一天_Android Studio3.6安装 安卓开发学习日记第二天_破坏陷阱卡之sync的坑 安卓开发学 ...

  3. Android动画学习笔记

    Android实战经验之图像处理及特效处理的集锦 https://www.oschina.net/question/231733_44154 Android动画学习笔记 3.0以前,android支持 ...

  4. 小白前端学习日记(一)认识前端

    小白前端学习日记系列 小白前端学习日记(二)HTML基础语法与标签 小白前端学习日记(一)认识前端 小白前端学习日记系列 前言 前端是什么 前端所需要掌握的基本能力 结构层--HTML 样式层--CS ...

  5. 学习笔记-零基础学习人工智能(0)

    学习笔记-零基础学习人工智能(0) 背景 规划 背景 作为物理专业的大龄青年,由于兴趣爱好想学习下人工智能.主要感兴趣的方向是对抗样本生成.自己也做了一些了解,但是发现千头万绪,不懂的东西太多.为了梳 ...

  6. android学习日记 RecyclerView的简单使用

    android学习日记 RecyclerView的简单使用 文章目录 android学习日记 RecyclerView的简单使用 一.如何使用RecyclerView? 二.使用步骤 1.首先在bui ...

  7. Android学习日记 Notification 通知

    Android学习日记 Notification 通知 文章目录 Android学习日记 Notification 通知 前言 使用步骤 总结 前言 下拉状态栏显示的通知功能 使用步骤 代码如下: p ...

  8. Android学习日记

    2021.2.27 星期六 // TODO 2/27 // 标识符 字母数字下划线$组成 不能数字开头 区分大小写 // 关键字 // 变量 变量类型 变量名 驼峰法 变量值 // 类 Pascal ...

  9. android学习日记一

    这几天在公司实习,公司主要是做android项目,以前在学校也学习过android,但是就学了点皮毛,在这里我准备把自己当做android一无所知的人,但是java会点的人,来系统的学习一下andro ...

最新文章

  1. 【java基础】map的基本使用与字符串中每个字符出现的次数统计
  2. 张季跃201771010139《面向对象程序设计(java)》第一周学习总结(改)
  3. Jenkins 插件管理与系统设置
  4. 过拟合与模型调优(part2)--重抽样技术
  5. 软件配置管理(五)常用重构技巧
  6. 在阿里云容器服务上创建一个使用Redis的Python应用
  7. 在ISA2006以SSL-TO-HTTP方式发布内部的WEB服务器(一)
  8. 整理一年中使用到的工具和类库,可能正有你需要的!
  9. 大哥你遇到问题,博文在此,连找都懒得找吗?
  10. 吉林大学计算机学院刘,刘华虓-吉林大学计算机科学与技术学院
  11. python分离数字_python从字符串中提取数字_filter
  12. visio2013激活软件,绝对靠谱!!!
  13. 计算机实验小学教导主任,小学教导主任2020年度考核个人总结5篇
  14. 关于阿里云服务器的问题及答案(详细汇总)
  15. 【技术贴】Pdf压缩利器--PDFshrink使用教程
  16. storm the 少儿英语_storm是什么意思_storm在线翻译_英语_读音_用法_例句_海词词典...
  17. 大数据内功修炼到企业实战2.0
  18. 5g网络模式是以什么划分的_5G基础知识及试题
  19. 现在学习软件测试好找工作吗
  20. 杰瑞学Perl之多值比较问题

热门文章

  1. Windows 7 U盘安装系统教程
  2. Shell判断日期是否是月末
  3. 推荐几款优秀的搜素引擎
  4. idc管理系统应该如何去解决IDC行业所遇到的难题
  5. 论文理解【Offline RL】—— 【BAIL】Best-Action Imitation Learning for Batch Deep Reinforcement Learning
  6. 解决虚拟机下Ubuntu cheese黑屏问题
  7. 照片转3d模型_在线搭建3D场景
  8. 易康软件插件ESP2
  9. html 清除文字阴影,CSS3文字阴影text-shadow使用详解
  10. LoRa的远距离通信采用的方法