飞飞的AI实验室

用AI放大灵感,把想法变成作品。

直接看代码:

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
package com.xpf.someexamples;

import android.app.Activity;
import android.content.Context;
import android.view.Window;
import android.view.WindowManager;

/**
* Created by xpf on 2017/5/14 :)
* GitHub:xinpengfei520
* Function:设置屏幕亮度及Alpha值
*/

public class BrightnessManager {
/**
* 设置当前activity的屏幕亮度
*
* @param paramFloat 0-1.0f
* @param context 需要调整亮度的activity context
*/
public static void setBrightness(float paramFloat, Context context) {
Activity activity = (Activity) context;
Window localWindow = activity.getWindow();
WindowManager.LayoutParams params = localWindow.getAttributes();
params.screenBrightness = paramFloat;
localWindow.setAttributes(params);
}

/**
* 获取当前activity的屏幕亮度
*
* @param context 当前activity context对象
* @return 亮度值范围为0-0.1f,如果为-1.0,则亮度与全局同步
*/
public static float getBrightness(Context context) {
Activity activity = (Activity) context;
Window localWindow = activity.getWindow();
WindowManager.LayoutParams params = localWindow.getAttributes();
return params.screenBrightness;
}

/**
* 设置手机屏幕透明度0-1.0f
*/
public static void setAlpha(float light, Context context) {
Activity activity = (Activity) context;
Window window = activity.getWindow();
WindowManager.LayoutParams lp = window.getAttributes();
lp.alpha = light;
window.setAttributes(lp);
}

/**
* 设置手机屏幕透明度变暗
*/
public static void lightoff(Context context) {
Activity activity = (Activity) context;
Window window = activity.getWindow();
WindowManager.LayoutParams lp = window.getAttributes();
lp.alpha = 0.3f;
window.setAttributes(lp);
}

/**
* 设置手机屏幕透明度显示正常
*/
public static void lighton(Context context) {
Activity activity = (Activity) context;
Window window = activity.getWindow();
WindowManager.LayoutParams lp = window.getAttributes();
lp.alpha = 1.0f;
window.setAttributes(lp);
}
}
阅读全文 »

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
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
import android.content.Context;
import android.graphics.Bitmap;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;

/**
* Created by xpf on 2017/6/24 :)
* Function:实现高斯模糊工具类
*/

public class BlurBitmapUtil {

// 图片缩放比例(即模糊度)
private static final float BITMAP_SCALE = 0.4f;

/**
* @param context 上下文对象
* @param image 需要模糊的图片
* @return 模糊处理后的Bitmap
*/
public static Bitmap blurBitmap(Context context, Bitmap image, float blurRadius) {
// 计算图片缩小后的长宽
int width = Math.round(image.getWidth() * BITMAP_SCALE);
int height = Math.round(image.getHeight() * BITMAP_SCALE);

// 将缩小后的图片做为预渲染的图片
Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
// 创建一张渲染后的输出图片
Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);

// 创建RenderScript内核对象
RenderScript rs = RenderScript.create(context);
// 创建一个模糊效果的RenderScript的工具对象
ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));

// 由于RenderScript并没有使用VM来分配内存,所以需要使用Allocation类来创建和分配内存空间
// 创建Allocation对象的时候其实内存是空的,需要使用copyTo()将数据填充进去
Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);

// 设置渲染的模糊程度, 25f是最大模糊度
blurScript.setRadius(blurRadius);
// 设置blurScript对象的输入内存
blurScript.setInput(tmpIn);
// 将输出数据保存到输出内存中
blurScript.forEach(tmpOut);

// 将数据填充到Allocation中
tmpOut.copyTo(outputBitmap);

return outputBitmap;
}
}

2.使用示例

1
2
3
4
5
6
7
if (image != null) {
Bitmap blurBitmap = BlurBitmapUtil.blurBitmap(mContext, image, 20);
blurView.setImageBitmap(blurBitmap);
} else {
// 如果image为null就设置一张本地默认的模糊照片
blurView.setImageResource(R.drawable.img_mohu);
}

Thanks all.

Good night~

阅读全文 »

从APP A 中打开B APP ,注意 B APP的包名和MainActivity 的全类名

1
2
3
4
5
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ComponentName cn = new ComponentName("com.xpf.keyboardtest", "com.xpf.keyboardtest.MainActivity");
intent.setComponent(cn);
startActivity(intent);
阅读全文 »

1.自定义LoadingView

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
/**
* Created by xpf on 2017/8/28 :)
* Function:自定义加载中的Dialog
*/

public class LoadingView extends ProgressDialog {

public LoadingView(Context context) {
super(context);
}

public LoadingView(Context context, int theme) {
super(context, theme);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init(getContext());
}

private void init(Context context) {
setCancelable(true);
setCanceledOnTouchOutside(false);
setContentView(R.layout.loading_view);//loading的xml文件
WindowManager.LayoutParams params = getWindow().getAttributes();
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
getWindow().setAttributes(params);
}

@Override
public void show() { // 显示Dialog
super.show();
}

@Override
public void dismiss() { // 关闭Dialog
super.dismiss();
}
}

2.LoadingView的布局文件

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
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerInParent="true"
android:layout_gravity="center_horizontal"
android:background="@drawable/shape_dialog_bg"
android:orientation="vertical">

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp">

<ProgressBar
android:id="@+id/pb_load"
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_centerInParent="true"
android:indeterminateDrawable="@drawable/progressbar" />
</RelativeLayout>

<TextView
android:id="@+id/tv_load_dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="加载中..."
android:textColor="#9a9b98"
android:textSize="24sp" />
</LinearLayout>

3.dialog圆角的shape

1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="16dp" />
<solid android:color="#88000000" />
</shape>

4.定义drawable旋转动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="720">
<shape
android:innerRadiusRatio="3"
android:shape="ring"
android:thicknessRatio="15"
android:useLevel="false">
<gradient
android:centerColor="#c6c6c6"
android:centerY="0.50"
android:endColor="#c6c6c6"
android:startColor="#55c6c6c6"
android:type="sweep"
android:useLevel="false" />
</shape>
</animated-rotate>

5.定义一个Style

1
2
3
4
<style name="CustomDialog" parent="Theme.AppCompat.Dialog">
<item name="android:backgroundDimEnabled">false</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
阅读全文 »

第一种写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Glide.with(mContext).load(R.drawable.open_door_fail)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.listener(new RequestListener<Integer, GlideDrawable>() {
@Override
public boolean onException(Exception e, Integer model, Target<GlideDrawable> target, boolean isFirstResource) {
return false;
}

@Override
public boolean onResourceReady(GlideDrawable resource, Integer model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
int duration = 0;
// 计算动画时长
GifDrawable drawable = (GifDrawable) resource;
GifDecoder decoder = drawable.getDecoder();
for (int i = 0; i < drawable.getFrameCount(); i++) {
duration += decoder.getDelay(i);
}
//发送延时消息,通知动画结束
handler.sendEmptyMessageDelayed(ANIMDISMISS, duration);
return false;
}
})
.into(new GlideDrawableImageViewTarget(ivOpenDoor, 1));
}

另外一种写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Glide.with(mContext).load(R.drawable.loading)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.listener(new RequestListener<Integer, GlideDrawable>() {
@Override
public boolean onException(Exception e, Integer model, Target<GlideDrawable> target, boolean isFirstResource) {
return false;
}

@Override
public boolean onResourceReady(GlideDrawable resource, Integer model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
int duration = 0;
// 计算动画时长
GifDrawable drawable = (GifDrawable) resource;
GifDecoder decoder = drawable.getDecoder();
for (int i = 0; i < drawable.getFrameCount(); i++) {
duration += decoder.getDelay(i);
}
//发送延时消息,通知动画结束
handler.sendEmptyMessageDelayed(3, duration);
return false;
}
})
.into(ivLoading);

Thanks all.

阅读全文 »

##方式一:使用第三开源框架直接在布局文件中加载gif

###1.在工程的build.gradle中添加如下

1
2
3
4
5
6
7
8
9
10
buildscript {
repositories {
mavenCentral()
}
}
allprojects {
repositories {
mavenCentral()
}
}

###2.在app的build.gradle中添加依赖

compile 'pl.droidsonroids.gif:android-gif-drawable:1.2.1'

###3.布局文件中就可以直接写你需要加载的gif图片即可

1
2
3
4
<pl.droidsonroids.gif.GifImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/gif2" />

##方式二:使用Glide加载gif

这种方式就比较简单了,直接看代码↓

###1.添加Glide图片加载框架依赖

阅读全文 »

CSDN:https://blog.csdn.net/xinpengfei521
声明:本文由作者原创,未经授权,不可随意转载!

      最近,我们公司的业务已经拓展到了香港,我们都知道香港使用的是繁体中文,因此,我们的 APP 要可以设置繁体语言,这不我们要紧跟国际的步伐,实现多语言,产品定给我们的需求主要以实现简体中文、繁体中文、英文三种语言切换即可,具体的业务逻辑是:当用户第一次进入 APP 时,App 的语言跟随当前系统语言,当用户设置了某种语言之后就切换为用户设置的语言,不管系统之后设置成哪种语言,都不会影响用户设置的语言,如果用户一直没有设置语言选项,只要系统语言改变时,APP 的语言也要跟随系统语言设置改变。

      说明:本文以实现简体中文、繁体中文和英语为例进行简要讲解。

1.实现思路

      我们可以预先使用SharedPreference 来保存一个语言类型的值,当用户第一次进入 APP 时,我们通过 Key 取出这个值,第一次肯定是取不到的,这时我们将 App 的语言设置为当前系统默认值即可;当用户通设置多语言时,我们将这个语言对应的值通过SharedPreference 保存到本地即可,然后此时重启 APP,设置为用户设置的语言即可,以后每次进入 App 时只需取出保存用户设置的语言设置即可,一般设置语言写在程序的入口 ApplicationonCreate() 方法里。

2.自定义SharedPreference工具类

      作用:用于保存当前设置语言的类型,此文以 SharedPreference 保存为例,当然使用数据库或者其他保存方式也是可以的。

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
/**
* Created by xpf on 2017/03/25 :)
* Function: sp存储的工具类
*/
public class SpUtil {

private static final String APP_SP = "app_sp";
private static final String TAG = SpUtil.class.getSimpleName();

private SpUtil() {
}

private static SpUtil instance = new SpUtil();
private static SharedPreferences mSp = null;

public static SpUtil getInstance() {
if (mSp == null) {
mSp = MyApplication.getContext().getSharedPreferences(APP_SP, Context.MODE_PRIVATE);
}
return instance;
}

/**
* 保存数据
*
* @param key 键
* @param value 值
*/
public void save(String key, Object value) {
if (value == null) {
Log.e(TAG, "value==null保存失败");
return;
}
if (value instanceof String) {
mSp.edit().putString(key, (String) value).commit();
} else if (value instanceof Boolean) {
mSp.edit().putBoolean(key, (Boolean) value).commit();
} else if (value instanceof Integer) {
mSp.edit().putInt(key, (Integer) value).commit();
}
}

/**
* 读取String类型数据
*
* @param key
* @param defValue
* @return
*/
public String getString(String key, String defValue) {
return mSp.getString(key, defValue);
}

/**
* 读取boolean类型数据
*
* @param key
* @param defValue
* @return
*/
public boolean getBoolean(String key, boolean defValue) {
return mSp.getBoolean(key, defValue);
}

/**
* 读取boolean类型数据
*
* @param key
* @param defValue
* @return
*/
public int getInt(String key, int defValue) {
return mSp.getInt(key, defValue);
}

/**
* 清除所有保存的数据(xxx.xml仍然存在,但是内部没有数据)
*/
public void clearAll() {
mSp.edit().clear().commit();
}
}

3.自定义LocaleUtil工具类

      作用:用于设置保存语言及获取当前语言,重启 APP 等操作

阅读全文 »

需求:设计一个图片加载工具类。
要求:职责单一、可扩展性强、实现三级缓存,遵循开闭原则。

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
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
package com.anloq.sdk.imageloader;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.LruCache;
import android.widget.ImageView;

import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* Created by xpf on 2017/10/22 :)
* Function:
*/

public class ImageLoader {

// 图片缓存
LruCache<String, Bitmap> mImageCache;
// 线程池,线程池数量为CPU的数量
ExecutorService mExecutorService = Executors.newFixedThreadPool(
Runtime.getRuntime().availableProcessors());

public ImageLoader() {
initImageCache();
}

/**
* 初始化图片缓存大小
*/
private void initImageCache() {
// 计算可使用的最大内存
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
// 取1/4的可用内存作为缓存
final int cacheSize = maxMemory / 4;
mImageCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight() / 1024;
}
};
}

/**
* 加载显示图片
*
* @param url
* @param imageView
*/
public void displayImage(final String url, final ImageView imageView) {
imageView.setTag(url);
mExecutorService.submit(new Runnable() {
@Override
public void run() {
Bitmap bitmap = downloadImage(url);
if (bitmap == null) return;
if (imageView.getTag().equals(url)) {
imageView.setImageBitmap(bitmap);
}
mImageCache.put(url, bitmap);
}
});

}

/**
* 下载图片
*
* @param imageUrl
* @return
*/
private Bitmap downloadImage(String imageUrl) {
Bitmap bitmap = null;
try {
URL url = new URL(imageUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
bitmap = BitmapFactory.decodeStream(conn.getInputStream());
conn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

2.遵循单一原则将原始类分为加载和缓存两个类(功能)

2.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
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
package com.anloq.sdk.imageloader;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ImageView;

import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* Created by xpf on 2017/10/22 :)
* Function:
*/

public class ImageLoader {

// 图片缓存
ImageCache mImageCache = new ImageCache();
// 线程池,线程池数量为CPU的数量
ExecutorService mExecutorService = Executors.newFixedThreadPool(
Runtime.getRuntime().availableProcessors());

/**
* 加载显示图片
*
* @param url
* @param imageView
*/
public void displayImage(final String url, final ImageView imageView) {
// 优先从缓存中加载
Bitmap bitmap = mImageCache.get(url);
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
return;
}
imageView.setTag(url);
mExecutorService.submit(new Runnable() {
@Override
public void run() {
Bitmap bitmap = downloadImage(url);
if (bitmap == null) return;
if (imageView.getTag().equals(url)) {
imageView.setImageBitmap(bitmap);
}
mImageCache.put(url, bitmap);
}
});
}

/**
* 下载图片
*
* @param imageUrl
* @return
*/
private Bitmap downloadImage(String imageUrl) {
Bitmap bitmap = null;
try {
URL url = new URL(imageUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
bitmap = BitmapFactory.decodeStream(conn.getInputStream());
conn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

2.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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.anloq.sdk.imageloader;

import android.graphics.Bitmap;
import android.util.LruCache;

/**
* Created by xpf on 2017/10/22 :)
* Function:图片缓存类
*/

public class ImageCache {
// 图片LRU缓存
LruCache<String, Bitmap> mImageCache;

public ImageCache() {
initImageCache();
}

/**
* 初始化图片缓存大小
*/
private void initImageCache() {
// 计算可使用的最大内存
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
// 取1/4的可用内存作为缓存
final int cacheSize = maxMemory / 4;
mImageCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight() / 1024;
}
};
}

public void put(String url, Bitmap bitmap) {
mImageCache.put(url, bitmap);
}

public Bitmap get(String url) {
return mImageCache.get(url);
}
}

3.提高扩展性,增加SD卡缓存

以上将代码的功能分开了,逻辑更清晰了,职责也单一了,但是可扩展性还是比较差,接下来进行增加SD卡缓存。

阅读全文 »

实现思路为:使用 Context.MODE_APPEND 属性将每次内容的写入到上次内容的尾部,然后在每次写入内容完成之后写入一个回车换行符**fos.write(“\r\n”.getBytes());**即可。

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
/**
* Created by xpf on 2017/10/31 :)
* Function:
*/

public class FileHelper {

private Context mContext;

public FileHelper(Context mContext) {
this.mContext = mContext;
}

/**
* 定义文件保存的方法,写入到文件中,所以是输出流
*/
public void save(String adNum, String time) {
String content = "广告位编号:" + adNum + ",播放时长:" + time;
FileOutputStream fos = null;
try {
// Context.MODE_PRIVATE私有权限,Context.MODE_APPEND追加写入到已有内容的后面
fos = mContext.openFileOutput(getFileName(), Context.MODE_APPEND);
fos.write(content.getBytes());
fos.write("\r\n".getBytes());//写入换行
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

/**
* 定义文件读取的方法
*/
public String read(String filename) throws IOException {
FileInputStream fis = mContext.openFileInput(filename);
byte[] buff = new byte[1024];
StringBuilder sb = new StringBuilder("");
int len = 0;
while ((len = fis.read(buff)) > 0) {
sb.append(new String(buff, 0, len));
}
fis.close();
return sb.toString();
}

/**
* get file name such as 20171031.txt
*
* @return
*/
private String getFileName() {
return TimeUtil.getCurrentDay() + ".txt";
}
}

转载请注明出处,谢谢!

阅读全文 »

今天闲来无事,想起之前买了一个阿里云 ECS,一直闲置着没用,一时兴起就想搭个自己的 GitLab 玩玩,GitLab 官网也提供了安装教程,很简单,照着步骤一步步基本没什么问题,可能安装的过程中有一些坑需要自己去解决。

1.安装 GitLab

打开 GitLab 官网 https://www.gitlab.com.cn/installation/#centos-7

根据自己的系统选择,我们选择 CentOS7

图1

首先,安装并配置必要的依赖关系,确保打开防火墙的 SSH 和 HTTP 的访问,如果没有,需要您输入下面命令打开

1
2
3
4
5
sudo yum install -y curl policycoreutils-python openssh-server
sudo systemctl enable sshd
sudo systemctl start sshd
sudo firewall-cmd --permanent --add-service=http
sudo systemctl reload firewalld

接下来安装 Postfix 发送邮件通知服务,或者如果您想使用其他方式(SMTP)来发送电子邮件,请跳过此步骤,并在安装了 GitLab 之后配置一个外部SMTP服务器。

1
2
3
sudo yum install postfix
sudo systemctl enable postfix
sudo systemctl start postfix

添加 GitLab 包仓库并安装包

阅读全文 »
0%