Xinspace


  • 首页

  • 归档

  • 搜索

Android用SurfaceView打造抽奖转盘

发表于 2016-04-26 | 分类于 Android

参考:Android SurfaceView实战 打造抽奖转盘

参考的这篇文章,写的很不错,各种细节和代码注释很到位。可以下载源代码研究一下。

Android开发遇到:IllegalStateException: Can not perform this action after onSaveInstanceState问题

发表于 2016-04-26 | 分类于 Android

参考:

  1. IllegalStateException: Can not perform this action after onSaveInstanceState with ViewPager
  2. Very simple code, but got error “Activity has been destroyed” when use Fragment

之所以有这个问题,是因为FragmentTransaction#commit方法执行时,缺失了一些信息,导致状态异常。而之所以会出现信息缺失,是因为托管Activity还未创建完成,ViewPager或者FragmentTabHost就调用了FragmentTransaction#commit方法。因此,解决方法目前有两种:

1.在Activity创建完成后再调用FragmentTransaction#commit方法

可以在Activity#onPostCreate方法中执行ViewPager或FragmentTabHost的初始化与加载操作。

2.使用FragmentTransaction#commitAllowingStateLoss方法

另外,可以调用上面的方法,而不是FragmentTransaction#commit。上述方法允许信息丢失的情况下提交事务。

其他注意

同时,还需注意,在FragmentManager提交事务之前,必须确保托管Activity没有被销毁,可以用如下代码段做判断:

1
2
3
4
5
6
if (!isFinishing()) {
FragmentTransaction ft = getSupportFragmentManager()
.beginTransaction();
ft.replace(SOME_RES_ID, myFragmentInstance);
ft.commit();
}

使用Retrofit库和OkHttp库示例

发表于 2016-04-26 | 分类于 Android

参考:

  1. Using Retrofit 2.0 as REST client - Tutorial
  2. Using OkHttp

参考1是使用Retrofit库的示例,参考2是使用OkHttp库的示例。现在Retrofit的底层使用的是OkHttp,并且支持RxJava,因此建议网络库用Retrofit。还有更多的特性,详情见官网Retrofit

Android反复运动的动画

发表于 2016-04-25 | 分类于 Android

============================
原创,转载请指明出处。

要实现一个反复移动的动画,其实是在一个View上施加一个TranslationAnimation,设置这个Animation的时间和模式即可。
具体的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class firstActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

//对这个ImageView对象施加位移动画
final ImageView image=(ImageView)findViewById(R.id.imageView1);
//启动动画的按钮
Button btn1=(Button)findViewById(R.id.button1);
Button btn2=(Button)findViewById(R.id.button2);

//创建位移动画,从x轴的0坐标移动到x轴的300坐标,从y轴的0坐标移动到y轴的300坐标
final Animation translateAnimation=new TranslateAnimation(0,300,0,300);

btn1.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
//设置动画持续时间为3秒
translateAnimation.setDuration(3000);
//设置重复次数,可随意,这里是想无限重复
translateAnimation.setRepeatCount(Integer.MAX_VALUE);
//设置动画的重复模式,即反方向运动。当从(0,0)运动到(300,300)后,再从(300,300)运动到(0,0),如此反复
translateAnimation.setRepeatMode(Animation.REVERSE);
//为ImageView设置动画效果
image.setAnimation(translateAnimation);
//启动位移动画
translateAnimation.startNow();
}
});

btn2.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
//取消动画执行
translateAnimation.cancel();
}
});
}
}

Android制作圆形ImageView

发表于 2016-04-25 | 分类于 Android

参考:圆形ImageView

效果图如下:

具体的解释请移步参考文章,这里只保留代码作为备份:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package com.feng.meiya.widget.imageview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;

public class CircleImageView extends ImageView {

//基本的三个构造函数
public CircleImageView(Context context) {
super(context);
}

public CircleImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}

public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}

//自定义View实现过程中很重要的onDraw绘制图形的方法
@Override
protected void onDraw(Canvas canvas) {

Drawable drawable = getDrawable();

//空值判断,必要步骤,避免由于没有设置src导致的异常错误
if (drawable == null) {
return;
}

//必要步骤,避免由于初始化之前导致的异常错误
if (getWidth() == 0 || getHeight() == 0) {
return;
}

if (!(drawable instanceof BitmapDrawable)) {
return;
}
Bitmap b = ((BitmapDrawable) drawable).getBitmap();

if (null == b) {
return;
}

Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);

int w = getWidth();

Bitmap roundBitmap = getCroppedBitmap(bitmap, w);
canvas.drawBitmap(roundBitmap, 0, 0, null);

}

/**
* 初始Bitmap对象的缩放裁剪过程
* @param bmp 初始Bitmap对象
* @param radius 圆形图片直径大小
* @return 返回一个圆形的缩放裁剪过后的Bitmap对象
*/
public static Bitmap getCroppedBitmap(Bitmap bmp, int radius) {
Bitmap sbmp;
//比较初始Bitmap宽高和给定的圆形直径,判断是否需要缩放裁剪Bitmap对象
if (bmp.getWidth() != radius || bmp.getHeight() != radius)
sbmp = Bitmap.createScaledBitmap(bmp, radius, radius, false);
else
sbmp = bmp;
Bitmap output = Bitmap.createBitmap(sbmp.getWidth(), sbmp.getHeight(),
Config.ARGB_8888);
Canvas canvas = new Canvas(output);

final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, sbmp.getWidth(), sbmp.getHeight());

paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#BAB399"));
canvas.drawCircle(sbmp.getWidth() / 2 + 0.7f,
sbmp.getHeight() / 2 + 0.7f, sbmp.getWidth() / 2 + 0.1f, paint);
//核心部分,设置两张图片的相交模式,在这里就是上面绘制的Circle和下面绘制的Bitmap
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(sbmp, rect, rect, paint);

return output;
}

}

Android在ViewPager中使用自定义View,而不是Fragment

发表于 2016-04-25 | 分类于 Android

参考:ViewPager without Fragments

一般来说,系统提供了使用Fragment的Adapter,这样在ViewPager中使用Fragment就比较方便。然而有时候我们需要自定义View,而不是Fragment时,可以参考下面的方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//我只对Adapter进行介绍和备份,其余的布局等可以看参考文章
/**
* 自定义Adapter,作为ViewPager的adapter
**/
public class CustomPagerAdapter extends PagerAdapter {

private Context mContext;

public CustomPagerAdapter(Context context) {
mContext = context;
}

@Override
public Object instantiateItem(ViewGroup collection, int position) {
//在这个回调方法中加载布局、初始化组件,绑定数据等操作
CustomPagerEnum customPagerEnum = CustomPagerEnum.values()[position];
LayoutInflater inflater = LayoutInflater.from(mContext);
ViewGroup layout = (ViewGroup) inflater.inflate(customPagerEnum.getLayoutResId(), collection, false);
collection.addView(layout);
return layout;
}

@Override
public void destroyItem(ViewGroup collection, int position, Object view) {
//在这个回调方法中,移除指定的view
collection.removeView((View) view);
}

@Override
public int getCount() {
//ViewPager一共有多少页
return CustomPagerEnum.values().length;
}

@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}

@Override
public CharSequence getPageTitle(int position) {
//获取页面的标题,在TabHost与ViewPager配合使用时,TabHost会使用该回调返回的字符串设置为当前页面的标题
CustomPagerEnum customPagerEnum = CustomPagerEnum.values()[position];
return mContext.getString(customPagerEnum.getTitleResId());
}

}

Android把图片写入到图库中,用户立即可以看到

发表于 2016-04-25 | 分类于 Android

参考:把图片写入图库中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public static void saveImageToGallery(Context context, Bitmap bmp) {
// 首先保存图片到SD卡的任意目录
File appDir = new File(Environment.getExternalStorageDirectory(), "CustomImages");
if (!appDir.exists()) {
appDir.mkdir();
}
//图片名称可以任意设置,此处设置为当前时间
String fileName = System.currentTimeMillis() + ".jpg";
File file = new File(appDir, fileName);
try {
FileOutputStream fos = new FileOutputStream(file);
bmp.compress(CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

// 其次把保存在SD目录中的文件插入到系统图库中
try {
MediaStore.Images.Media.insertImage(context.getContentResolver(),
file.getAbsolutePath(), fileName, null);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// 最后通知图库更新
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + path)));
}

Java代码按比例缩放图片

发表于 2016-04-25 | 分类于 Programming

参考:Java按比例缩放图片

最近服务端需要对上传的图片进行裁剪,在网上寻找Java代码裁剪图片的例子,找到了这个,并且用在了实际代码中,效果还不错。
摘到此处作为备份。

1.按照固定长宽进行缩放:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* @param src 源文件
* @param dest 缩放后存放的目录
* @param w 缩放后的宽度
* @param h 缩放后的高度
* */
public static void zoomImage(String src, String dest, int w, int h) throws Exception {

double wr=0,hr=0;
File srcFile = new File(src);
File destFile = new File(dest);

BufferedImage bufImg = ImageIO.read(srcFile); //读取图片
Image Itemp = bufImg.getScaledInstance(w, h, bufImg.SCALE_SMOOTH);//设置缩放目标图片模板

wr=w*1.0/bufImg.getWidth(); //获取缩放比例
hr=h*1.0 / bufImg.getHeight();

AffineTransformOp ato = new AffineTransformOp(AffineTransform.getScaleInstance(wr, hr), null);
Itemp = ato.filter(bufImg, null);
try {
ImageIO.write((BufferedImage) Itemp,dest.substring(dest.lastIndexOf(".")+1), destFile); //写入缩减后的图片
} catch (Exception ex) {
ex.printStackTrace();
}
}

我们在实际项目中使用的上述的方法把大图片按照指定的宽和高进行裁剪,效果还可以。

2.按照文件的大小进行裁剪

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* 图片按文件大小
* @param src 原文件
* @param dest 缩放后的存放目录
* @param size 文件的大小
* */
public static void zoomImage(String src, String dest, Integer size) throws Exception {
File srcFile = new File(src);
File destFile = new File(dest);

long fileSize = srcFile.length();
if(fileSize < size * 1024) //文件大于size k时,才进行缩放
return;

Double rate = (size * 1024 * 0.5) / fileSize; // 获取长宽缩放比例

BufferedImage bufImg = ImageIO.read(srcFile);
Image Itemp = bufImg.getScaledInstance(bufImg.getWidth(), bufImg.getHeight(), bufImg.SCALE_SMOOTH);

AffineTransformOp ato = new AffineTransformOp(AffineTransform.getScaleInstance(rate, rate), null);
Itemp = ato.filter(bufImg, null);
try {
ImageIO.write((BufferedImage) Itemp,dest.substring(dest.lastIndexOf(".")+1), destFile);
} catch (Exception ex) {
ex.printStackTrace();
}
}

这个方法有一点问题,就是当图片特别大,而规定的尺寸比较小时,比如原图是1M,而小图规定20K的时候,效果不是特别好,压缩的太小了。

让Android单屏壁纸显示在屏幕中间

发表于 2016-04-25 | 分类于 Android

参考:WallpaperManager zooms image even though the dimension match the screen

在设置Android单屏壁纸时,有些机型会遇到壁纸没有显示在屏幕正中间的问题。上述参考中给出的解决办法能解决一部分问题,但仍然有些机型不能被适配。

阅读全文 »

dp与px互转的方法

发表于 2016-04-13 | 分类于 Android

参考:overstackoverflow

可以把回答中的两个方法放在一个工具类中,整个项目可以直接调用。

1…345…17

Xinspace

Personal blog from xin.

170 日志
6 分类
1 标签
© 2019 Xinspace
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4