乱码三千 – 分享实用IT技术

乱码三千 – 码出一个新世界


  • 首页

  • 归档

  • 搜索

如何在markdown中插入js和css

发表于 2020-05-14

有时候我们可能需要改动markdown 的样式。由于markdown的呈现形式是html,可以直接把以下部分添加到markdown中,即可更改默认的样式

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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

<style>
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote {
margin: 0;
padding: 0;
}
body {
font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", Arial, sans-serif;
font-size: 13px;
line-height: 18px;
color: #737373;
background-color: white;
margin: 10px 13px 10px 13px;
}
table {
margin: 10px 0 15px 0;
border-collapse: collapse;
}
td,th {
border: 1px solid #ddd;
padding: 3px 10px;
}
th {
padding: 5px 10px;
}

a {
color: #0069d6;
}
a:hover {
color: #0050a3;
text-decoration: none;
}
a img {
border: none;
}
p {
margin-bottom: 9px;
}
h1,
h2,
h3,
h4,
h5,
h6 {
color: #404040;
line-height: 36px;
}
h1 {
margin-bottom: 18px;
font-size: 30px;
}
h2 {
font-size: 24px;
}
h3 {
font-size: 18px;
}
h4 {
font-size: 16px;
}
h5 {
font-size: 14px;
}
h6 {
font-size: 13px;
}
hr {
margin: 0 0 19px;
border: 0;
border-bottom: 1px solid #ccc;
}
blockquote {
padding: 13px 13px 21px 15px;
margin-bottom: 18px;
font-family:georgia,serif;
font-style: italic;
}
blockquote:before {
content:"\201C";
font-size:40px;
margin-left:-10px;
font-family:georgia,serif;
color:#eee;
}
blockquote p {
font-size: 14px;
font-weight: 300;
line-height: 18px;
margin-bottom: 0;
font-style: italic;
}
code, pre {
font-family: Monaco, Andale Mono, Courier New, monospace;
}
code {
background-color: #fee9cc;
color: rgba(0, 0, 0, 0.75);
padding: 1px 3px;
font-size: 12px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
pre {
display: block;
padding: 14px;
margin: 0 0 18px;
line-height: 16px;
font-size: 11px;
border: 1px solid #d9d9d9;
white-space: pre-wrap;
word-wrap: break-word;
}
pre code {
background-color: #fff;
color:#737373;
font-size: 11px;
padding: 0;
}
sup {
font-size: 0.83em;
vertical-align: super;
line-height: 0;
}
*{
-webkit-print-color-adjust: exact;
}
@media screen and (min-width: 914px) {
body {
width: 854px;
margin:10px auto;
}
}
@media print {
body,code,pre code,h1,h2,h3,h4,h5,h6 {
color: black;
}
table, pre {
page-break-inside: avoid;
}
}
</style>

直接将以上代码插入文本的上方, 如下:

image-20210831104548134

生成html的结果为:

image-20210831104446641

如何在Hexo发布博客的Md文件中引入JS代码

跟引入css样式一样 直接插入js代码即可 这里有两种方式:

第一种 引用第三方js文件

1
<script type="text/javascript" src="/js/src/echarts.min.js"></script>

第二种 常规写法

1
2
3
4
5
<script>

var bmapChart=echarts.init(document.getElementById("map-wrap"));

</script>

附加

如果使用hexo编译html 如果要将html代码当做普通文本处理 可以添加以下raw标签, 如下:

1
2
3
4
5
{% raw %}

这里是html代码区域, 表示失去html的功能

{% endraw %}

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

如何使用命令行下载更新Android SDK

发表于 2020-05-13

最近需要在服务器上用Jenkins自动打包Android app,从google官网上下载的Linux版本sdk结果发现里面就只有一个tools目录有文件,其他的都没有。。。
无奈,服务器是没有界面的,之前都习惯用IDE去安装更新,现在尝试用命令行下载更新了。

下载Android SDK for Linux

从google的官网下载最新Linux版本SDK,由于dl.google.com域名一直没有被墙,所以才可以直接从官网下了。这点不错~

1
2
3
4
5
6
下载
$ wget https://dl.google.com/android/android-sdk_r24.4.1-linux.tgz
或者
$curl -o https://dl.google.com/android/android-sdk_r24.4.1-linux.tgz
或者
$wget -O https://dl.google.com/android/android-sdk_r24.4.1-linux.tgz
1
2
解压
$ tar zxvf android-sdk_r24.4.1-linux.tgz

更新Android SDK

前面说到了,我们下载的这个包其实只有tools目录下才有东西。既然google给了我们这个,表示这里面肯定有可以更新SDK的工具啦。
其实就是tools/android这个文件

1
$ cd android-sdk-linux/tools

进入后

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
查看当前可安装的SDK版本
$ ./android list sdk -a

Refresh Sources:
Fetching https://dl.google.com/android/repository/addons_list-2.xml
Validate XML
Parse XML
Fetched Add-ons List successfully
Refresh Sources
Fetching URL: https://dl.google.com/android/repository/repository-11.xml
Validate XML: https://dl.google.com/android/repository/repository-11.xml
Parse XML: https://dl.google.com/android/repository/repository-11.xml
Fetching URL: https://dl.google.com/android/repository/addon.xml
Validate XML: https://dl.google.com/android/repository/addon.xml
Parse XML: https://dl.google.com/android/repository/addon.xml
Fetching URL: https://dl.google.com/android/repository/glass/addon.xml
Validate XML: https://dl.google.com/android/repository/glass/addon.xml
Parse XML: https://dl.google.com/android/repository/glass/addon.xml
Fetching URL: https://dl.google.com/android/repository/extras/intel/addon.xml
Validate XML: https://dl.google.com/android/repository/extras/intel/addon.xml
Parse XML: https://dl.google.com/android/repository/extras/intel/addon.xml
Fetching URL: https://dl.google.com/android/repository/sys-img/android/sys-img.xml
Validate XML: https://dl.google.com/android/repository/sys-img/android/sys-img.xml
Parse XML: https://dl.google.com/android/repository/sys-img/android/sys-img.xml
Fetching URL: https://dl.google.com/android/repository/sys-img/android-wear/sys-img.xml
Validate XML: https://dl.google.com/android/repository/sys-img/android-wear/sys-img.xml
Parse XML: https://dl.google.com/android/repository/sys-img/android-wear/sys-img.xml
Fetching URL: https://dl.google.com/android/repository/sys-img/android-tv/sys-img.xml
Validate XML: https://dl.google.com/android/repository/sys-img/android-tv/sys-img.xml
Parse XML: https://dl.google.com/android/repository/sys-img/android-tv/sys-img.xml
Fetching URL: https://dl.google.com/android/repository/sys-img/google_apis/sys-img.xml
Validate XML: https://dl.google.com/android/repository/sys-img/google_apis/sys-img.xml
Parse XML: https://dl.google.com/android/repository/sys-img/google_apis/sys-img.xml

Packages available for installation or update: 41
1- Android SDK Tools, revision 25.2.2
2- Android SDK Platform-tools, revision 24.0.4
3- Android SDK Build-tools, revision 24.0.3
4- Documentation for Android SDK, API 24, revision 1
5- SDK Platform Android 7.0, API 24, revision 2
6- SDK Platform Android 6.0, API 23, revision 3

因为是首次安装,所有有非常多的版本可下载。
我们可以有2个选择:

  1. 安装所有版本的SDK

    1
    $ ./android update sdk -u
  1. 只安装我们需要SDK版本

    1
    2
    3
    4
    5
    6
    只安装指定序号的版本
    $ ./android update sdk -u -t 序号
    如:安装Build-tools, revision 24.0.3

    $ ./android update sdk -u -t 3
    需要同意license,输入 y 回车即可

因为是在服务器上,建议直接安装所有版本的吧,不然后续可能有些app需要这个版本,又有的需要那个版本。还不如一开始就全部安装好。

安装后可跳转到上一级目录查看是否已经有了。

1
2
3
4
5
6
$ cd ..
$ ls
add-ons build-tools platforms SDK Readme.txt temp tools
$ cd build-tools
$ ls
24.0.3

可以看到安装成功了。

总结

通过这些我们也可以推测出其实那些IDE图形界面底层调用的也是这些命令吧

附加可能会使用到的linux指令

1
2
查看当前目录的实际路径
$pwd
1
2
全局搜索指定文件 包括文件夹和文件
$find . -name "文件名"
1
2
不区分大小写查找
$find -iname "*SaleContractFromDc*"
1
2
从/开始查找以.log结尾的文件
$find / -name "*.log"
1
2
下载文件到指定路径 这将只有在路径存在时下载。下载将保留远程文件名。下载后,将返回原始位置
$cd target/path && { curl -O URL ; cd -; }
1
2
查看系统整体空间剩余情况
$df -h
1
2
查看每个文件夹的占用情况
$du -sh
1
2
删除非空目录
$rm -rf 目录
1
2
3
4
查看 或 编辑 环境变量的配置
$vim /etc/profile
或者直接使用
$export
1
2
3
4
配置环境变量
export ANDROID_SDK_HOME=/root/Android/sdk/android-sdk-linux
export PATH=$PATH:${ANDROID_SDK_HOME}/tools
export PATH=$PATH:${ANDROID_SDK_HOME}/platform-tools
1
2
移动文件夹下所有东西到zone中
$mv /usr/lib/* /zone

本帖附件

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Android Android 获取应用签名证书的SHA1值和MD5值几种方法

发表于 2020-04-13

第一种 只有APK文件的情况下

  1. 首先将你的项目打包,一定要使用签名文件打包成release版本的apk文件。

  2. 将你的apk文件后缀修改成rar文件,解压。

  3. 在解压后的文件中找到META-INF文件,该目录下会存在CERT.RSA文件。

  4. 在META-INF目录下打开cmd(按住Shift,点击鼠标右键),输入命令 :keytool -printcert -file CERT.RSA,就可以在CMD命令窗口中看到签名文件的信息了,其中包括了SHA1值和MD5值。

第二种 你已经有了签名文件 并且知道密码

在jks签名文件目录下打开cmd(按住Shift,点击鼠标右键),输入命令 :keytool -list -v -keystore xxx.jks,就可以在CMD命令窗口中看到签名文件的信息了,其中包括了SHA1值和MD5值。

第三种 通过代码获取

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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

/**
* 获取签名工具类
*/
public class AppSigning {
public final static String MD5 = "MD5";
public final static String SHA1 = "SHA1";
public final static String SHA256 = "SHA256";
private static HashMap<String, ArrayList<String>> mSignMap = new HashMap<>();

/**
* 返回一个签名的对应类型的字符串
*
* @param context
* @param type
* @return 因为一个安装包可以被多个签名文件签名,所以返回一个签名信息的list
*/
public static ArrayList<String> getSignInfo(Context context, String type) {
if (context == null || type == null) {
return null;
}
String packageName = context.getPackageName();
if (packageName == null) {
return null;
}
if (mSignMap.get(type) != null) {
return mSignMap.get(type);
}
ArrayList<String> mList = new ArrayList<String>();
try {
Signature[] signs = getSignatures(context, packageName);
for (Signature sig : signs) {
String tmp = "error!";
if (MD5.equals(type)) {
tmp = getSignatureByteString(sig, MD5);
} else if (SHA1.equals(type)) {
tmp = getSignatureByteString(sig, SHA1);
} else if (SHA256.equals(type)) {
tmp = getSignatureByteString(sig, SHA256);
}
mList.add(tmp);
}
} catch (Exception e) {
LogUtil.e(e.toString());
}
mSignMap.put(type, mList);
return mList;
}

/**
* 获取签名sha1值
*
* @param context
* @return
*/
public static String getSha1(Context context) {
String res = "";
ArrayList<String> mlist = getSignInfo(context, SHA1);
if (mlist != null && mlist.size() != 0) {
res = mlist.get(0);
}
return res;
}

/**
* 获取签名MD5值
*
* @param context
* @return
*/
public static String getMD5(Context context) {
String res = "";
ArrayList<String> mlist = getSignInfo(context, MD5);
if (mlist != null && mlist.size() != 0) {
res = mlist.get(0);
}
return res;
}

/**
* 获取签名SHA256值
*
* @param context
* @return
*/
public static String getSHA256(Context context) {
String res = "";
ArrayList<String> mlist = getSignInfo(context, SHA256);
if (mlist != null && mlist.size() != 0) {
res = mlist.get(0);
}
return res;
}

/**
* 返回对应包的签名信息
*
* @param context
* @param packageName
* @return
*/
private static Signature[] getSignatures(Context context, String packageName) {
PackageInfo packageInfo = null;
try {
packageInfo = context.getPackageManager().getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
return packageInfo.signatures;
} catch (Exception e) {
LogUtil.e(e.toString());
}
return null;
}

/**
* 获取相应的类型的字符串(把签名的byte[]信息转换成16进制)
*
* @param sig
* @param type
* @return
*/
private static String getSignatureString(Signature sig, String type) {
byte[] hexBytes = sig.toByteArray();
String fingerprint = "error!";
try {
MessageDigest digest = MessageDigest.getInstance(type);
if (digest != null) {
byte[] digestBytes = digest.digest(hexBytes);
StringBuilder sb = new StringBuilder();
for (byte digestByte : digestBytes) {
sb.append((Integer.toHexString((digestByte & 0xFF) | 0x100)).substring(1, 3));
}
fingerprint = sb.toString();
}
} catch (Exception e) {
LogUtil.e(e.toString());
}

return fingerprint;
}

/**
* 获取相应的类型的字符串(把签名的byte[]信息转换成 95:F4:D4:FG 这样的字符串形式)
*
* @param sig
* @param type
* @return
*/
private static String getSignatureByteString(Signature sig, String type) {
byte[] hexBytes = sig.toByteArray();
String fingerprint = "error!";
try {
MessageDigest digest = MessageDigest.getInstance(type);
if (digest != null) {
byte[] digestBytes = digest.digest(hexBytes);
StringBuilder sb = new StringBuilder();
for (byte digestByte : digestBytes) {
sb.append(((Integer.toHexString((digestByte & 0xFF) | 0x100)).substring(1, 3)).toUpperCase());
sb.append(":");
}
fingerprint = sb.substring(0, sb.length() - 1).toString();
}
} catch (Exception e) {
LogUtil.e(e.toString());
}

return fingerprint;
}
}

第四种 使用Gradle Tasks

这种方法适合有源码的情况, 操作非常的简单

本帖附件

点击下载

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Android 设置TextView Drawable大小的几种方法

发表于 2020-04-10

第一种 使用 layer-list

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!--设置图片的大小 -->
<item
android:width="45dp"
android:height="45dp">
<bitmap android:src="@drawable/icon_profit" />
</item>


</layer-list>

第二种 使用自定义控件

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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128

/**
* 可自定义设置drawable宽高的TextView
*/
public class DrawableTextView extends AppCompatTextView {
private Drawable drawableLeft;
private Drawable drawableRight;
private Drawable drawableTop;
private int leftWidth;
private int rightWidth;
private int topWidth;
private int leftHeight;
private int rightHeight;
private int topHeight;
private Context mContext;

public DrawableTextView(Context context) {
super(context);
this.mContext = context;
init(context, null);
}

public DrawableTextView(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
init(context, attrs);
}

public DrawableTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
init(context, attrs);
}

private void init(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DrawableTextView);
drawableLeft = typedArray.getDrawable(R.styleable.DrawableTextView_leftDrawable);
drawableRight = typedArray.getDrawable(R.styleable.DrawableTextView_rightDrawable);
drawableTop = typedArray.getDrawable(R.styleable.DrawableTextView_topDrawable);
if (drawableLeft != null) {
leftWidth = typedArray.getDimensionPixelOffset(R.styleable.DrawableTextView_leftDrawableWidth, dip2px(context, 20));
leftHeight = typedArray.getDimensionPixelOffset(R.styleable.DrawableTextView_leftDrawableHeight, dip2px(context, 20));
}
if (drawableRight != null) {
rightWidth = typedArray.getDimensionPixelOffset(R.styleable.DrawableTextView_rightDrawableWidth, dip2px(context, 20));
rightHeight = typedArray.getDimensionPixelOffset(R.styleable.DrawableTextView_rightDrawableHeight, dip2px(context, 20));
}
if (drawableTop != null) {
topWidth = typedArray.getDimensionPixelOffset(R.styleable.DrawableTextView_topDrawableWidth, dip2px(context, 20));
topHeight = typedArray.getDimensionPixelOffset(R.styleable.DrawableTextView_topDrawableHeight, dip2px(context, 20));
}
}


public int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (drawableLeft != null) {
drawableLeft.setBounds(0, 0, leftWidth, leftHeight);
}
if (drawableRight != null) {
drawableRight.setBounds(0, 0, rightWidth, rightHeight);
}
if (drawableTop != null) {
drawableTop.setBounds(0, 0, topWidth, topHeight);
}
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
this.setCompoundDrawables(drawableLeft, drawableTop, drawableRight, null);

}

/**
* 设置左侧图片并重绘
*/
public void setDrawableLeft(Drawable drawableLeft) {
this.drawableLeft = drawableLeft;
invalidate();
}

/**
* 设置左侧图片并重绘
*/
public void setDrawableLeft(int drawableLeftRes) {
this.drawableLeft = mContext.getResources().getDrawable(drawableLeftRes);
invalidate();
}

/**
* 设置右侧图片并重绘
*/
public void setDrawableRight(Drawable drawableRight) {
this.drawableRight = drawableLeft;
invalidate();
}

/**
* 设置右侧图片并重绘
*/
public void setDrawableRight(int drawableRightRes) {
this.drawableRight = mContext.getResources().getDrawable(drawableRightRes);
invalidate();
}

/**
* 设置上部图片并重绘
*/
public void setDrawable(Drawable drawableTop) {
this.drawableTop = drawableTop;
invalidate();
}

/**
* 设置右侧图片并重绘
*/
public void setDrawableTop(int drawableTopRes) {
this.drawableTop = mContext.getResources().getDrawable(drawableTopRes);
invalidate();
}
}

本帖附件

点击下载

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Android 图片实现阴影效果的若干种方法

发表于 2020-04-10

第一种 使用 layer-list

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<!--底层的左边距离上层左边3dp, 底层的顶部,距离上层的顶部6dp,如果不做这个控制,底层和上层的左侧和上侧会重合在一起-->
<item android:left="3dp"
android:top="6dp">
<shape>
<solid android:color="#b4b5b6"/>
</shape>
</item>

<!--上层的右边距离底层的右边3dp, 上层的底部距离底层的底部6dp-->
<item android:bottom="6dp"
android:right="3dp">
<shape>
<solid android:color="#fff"/>
</shape>
</item>

</layer-list>

第二种 使用 shadow属性

shadowDX、shadowDy、shadowRadius,分别指的是阴影的横、纵坐标偏移,以及阴影的半径,

如果是TextView可以直接在布局中设置:

1
2
3
4
5
6
7
8
9
10
11
12
13
<TextView 
android:id="@+id/test_shadow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="60sp"
android:textColor="#cc000000"
android:text="Test Shadow"
android:layout_gravity="center"
android:shadowColor="#aa22ff22"
android:shadowRadius="10"
android:shadowDx="0"
android:shadowDy="0"
/>

第三种 使用android:elevation属性

<TextView
android:id="@+id/btn_test_performance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="5dp"
android:text="@string/hello"
android:background="@drawable/shape_round_white"
android:padding="20dp"
android:layout_marginTop="10dp"
android:layout_gravity="center"/>

这种方式有个局限性, 那就是api25以上才能显示出来

第四种 使用第三方控件

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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/**
* ShadowLayout.java
* <p>
* Created by lijiankun on 17/8/11.
*/

public class ShadowLayout extends RelativeLayout {

public static final int ALL = 0x1111;

public static final int LEFT = 0x0001;

public static final int TOP = 0x0010;

public static final int RIGHT = 0x0100;

public static final int BOTTOM = 0x1000;

private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

private RectF mRectF = new RectF();

/**
* 阴影的颜色
*/
private int mShadowColor = Color.TRANSPARENT;

/**
* 阴影的大小范围
*/
private float mShadowRadius = 0;

/**
* 阴影 x 轴的偏移量
*/
private float mShadowDx = 0;

/**
* 阴影 y 轴的偏移量
*/
private float mShadowDy = 0;

/**
* 阴影显示的边界
*/
private int mShadowSide = ALL;

public ShadowLayout(Context context) {
this(context, null);
}

public ShadowLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public ShadowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}

/**
* 获取绘制阴影的位置,并为 ShadowLayout 设置 Padding 以为显示阴影留出空间
*/
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);

float effect = mShadowRadius + dip2px(5);
float rectLeft = 0;
float rectTop = 0;
float rectRight = this.getWidth();
float rectBottom = this.getHeight();
int paddingLeft = 0;
int paddingTop = 0;
int paddingRight = 0;
int paddingBottom = 0;

if (((mShadowSide & LEFT) == LEFT)) {
rectLeft = effect;
paddingLeft = (int) effect;
}
if (((mShadowSide & TOP) == TOP)) {
rectTop = effect;
paddingTop = (int) effect;
}
if (((mShadowSide & RIGHT) == RIGHT)) {
rectRight = this.getWidth() - effect;
paddingRight = (int) effect;
}
if (((mShadowSide & BOTTOM) == BOTTOM)) {
rectBottom = this.getHeight() - effect;
paddingBottom = (int) effect;
}
if (mShadowDy != 0.0f) {
rectBottom = rectBottom - mShadowDy;
paddingBottom = paddingBottom + (int) mShadowDy;
}
if (mShadowDx != 0.0f) {
rectRight = rectRight - mShadowDx;
paddingRight = paddingRight + (int) mShadowDx;
}
mRectF.left = rectLeft;
mRectF.top = rectTop;
mRectF.right = rectRight;
mRectF.bottom = rectBottom;
this.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
}

/**
* 真正绘制阴影的方法
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(mRectF, mPaint);
}

/**
* 读取设置的阴影的属性
*
* @param attrs 从其中获取设置的值
*/
private void init(AttributeSet attrs) {
setLayerType(View.LAYER_TYPE_SOFTWARE, null); // 关闭硬件加速
this.setWillNotDraw(false); // 调用此方法后,才会执行 onDraw(Canvas) 方法

TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.ShadowLayout);
if (typedArray != null) {
mShadowColor = typedArray.getColor(R.styleable.ShadowLayout_shadowColor,
ContextCompat.getColor(getContext(), android.R.color.black));
mShadowRadius = typedArray.getDimension(R.styleable.ShadowLayout_shadowRadius, dip2px(0));
mShadowDx = typedArray.getDimension(R.styleable.ShadowLayout_shadowDx, dip2px(0));
mShadowDy = typedArray.getDimension(R.styleable.ShadowLayout_shadowDy, dip2px(0));
mShadowSide = typedArray.getInt(R.styleable.ShadowLayout_shadowSide, ALL);
typedArray.recycle();
}
mPaint.setAntiAlias(true);
mPaint.setColor(Color.TRANSPARENT);
mPaint.setShadowLayer(mShadowRadius, mShadowDx, mShadowDy, mShadowColor);
}

/**
* dip2px dp 值转 px 值
*
* @param dpValue dp 值
* @return px 值
*/
private float dip2px(float dpValue) {
DisplayMetrics dm = getContext().getResources().getDisplayMetrics();
float scale = dm.density;
return (dpValue * scale + 0.5F);
}
}

属性文件:

1
2
3
4
5
6
7
<declare-styleable name="ShadowLayout">
<attr name="shadowColor" format="color"/>
<attr name="shadowRadius" format="dimension"/>
<attr name="shadowDx" format="dimension"/>
<attr name="shadowDy" format="dimension"/>
<attr name="shadowSide" format="integer"/>
</declare-styleable>

第五种 使用9patch图片(强烈推荐)

该种方式定制性强, 兼容性好, 需要注意的是避免将9patch宽高设置过大 小图可以拉大 大图不方便缩小

链接地址:http://inloop.github.io/shadow4android/

本帖附件

点击下载

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

同一个局域网内远程控制电脑桌面的若干种方法

发表于 2020-02-11

本文持续更新中

  • 第三方软件
  • 局域网ip+3389端口

本帖附件

点击下载

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

外网电脑远程控制内网电脑桌面的若干种方法

发表于 2020-02-10

本文持续更新中

  • 第三方软件(如:QQ、TeamViewer、向日葵、anydesk、Splashtop….)
  • 路由器端口映射
  • frp

咱们接下来挨个介绍, 首先

第三方软件

如果你是小白, 追求实用性, 并且想快速上手远程控制, 那么第三方软件无疑是最好的选择, 如果你想用, 那么TeamViewer绝对是首选,个人版免费, 而且可设置无人值守, 只需一个ID和密码就能立马控制远程主机, 速度非常可观

官网地址: https://www.teamviewer.cn/cn/

路由器端口映射

如果你不情愿在电脑上装一堆软件, 或者想设置备用控制方案, 那么我建议你使用端口映射的方案, 将公网ip转发到内网需要控制的电脑ip上

frp

如果你有IT技术功底, 喜欢折腾, 并且有一颗耐操的脑袋, 同时不差钱, 那么我会建议你采用frp方案

详见《使用内网云进行内网穿透实现外网访问局域网中的服务器》

VNC桌面共享

linux可参考:https://www.jianshu.com/p/3488968c81cb

本帖附件

点击下载

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Linux环境下docker常用指令集合

发表于 2020-01-21

使用前提

需要先安装docker, 可参考《ubuntu安装docker详细步骤》

Docker容器基础指令

  1. 启动docker

    1
    sudo systemctl start docker
  2. 停止docker

    1
    sudo systemctl stop docker
  3. 查看docker状态

    1
    sudo systemctl status docker
  4. 重启docker

    1
    sudo systemctl restart docker
  5. 设置开启启动docker

    1
    sudo systemctl enable docker

常用Docker镜像指令

  1. 查看本地镜像

    1
    sudo docker images
  2. 拉取最新镜像

    1
    sudo docker pull [镜像名]:latest
  3. 创建并后台运行容器

    1
    sudo docker run -itd --name=[名称] [镜像名]:版本名
  4. 查看当前所有运行的容器信息

    1
    2
    3
    sudo docker ps
    另外
    sudo docker ps -a //查看所有容器
  5. 运行容器 并设置在后台一直运行

    1
    sudo docker run -itd --name [名称]  -d [镜像名]
  6. 查看镜像可用版本

    1
    sudo docker search [镜像名]
  7. 进入指定容器

    1
    sudo docker exec -it [镜像名] /bin/bash
  8. 创建容器 并将本地 8080 端口映射到容器内部的 80 端口

    1
    sudo docker run --name [镜像名] -p 8080:80
  9. 创建容器 并将主机中当前目录下的 test 挂载到容器的指定目录

    1
    sudo docker run --name [镜像名]  -v $PWD/test:[容器目录]
  10. 创建容器 并指定工作目录

    1
    sudo docker run --name [镜像名]  -w [工作目录]
  11. 停止运行容器

    1
    docker stop [容器id]

    或者

    1
    docker stop [容器名]
  12. 创建容器 并设置需要密码才能访问容器服务

    1
    sudo docker run --name [镜像名]  --auth
  13. 查看容器内的标准输出

    1
    2
    3
    sudo docker logs [容器名]
    另外
    sudo docker logs -f [容器名] //停留在尾部
  14. 删除容器

    1
    sudo docker rm -f [容器id] [容器id2] //多个容器以空格隔开-f表示强制删除
  15. 重启容器

    1
    sudo docker restart [容器id]
  16. 导出容器

    1
    sudo docker export [容器id] > [目标文件]
  17. 查看容器内部运行的进程

    1
    sudo docker top [容器名]
  18. 查看容器的配置和状态信息

    1
    sudo docker inspect  [容器名]
  19. 查询最后一次创建的容器

    1
    sudo docker ps -l
  20. 为镜像添加一个新的标签

    1
    sudo docker tag [镜像名]
  21. 查询镜像在什么位置

    1
    which [镜像名]
  22. 查看容器资源占用情况

    1
    sudo docker stats
  23. 删除所有容器

    1
    sudo docker rm $(docker ps -aq)
  24. 暂停指定容器

    1
    sudo docker pause [容器名]
  25. 查看具体指令的使用方法

    1
    sudo docker help [具体指令]
  26. 查看当前已有的网络

    1
    sudo docker network ls
  27. 创建自定义网络

    1
    docker network create [网络名]
  28. 后台运行容器 并指定容器想要连接的网络

    1
    docker run -dit --name [容器名] --network [网络名] alpine
  29. 将指定容器连接到指定网络上

    1
    docker network connect [网络名] [容器名]
  30. 删除指定网络

    1
    docker network rm [网络名]
  31. 查看某时间段日志

    1
    docker logs -t --since="2019-10-24T13:23:37" --until "2019-10-25T12:23:37" [容器名]
  32. 查看某时间之后的日志

    1
    docker logs -t --since="2019-10-24T13:23:37" [容器名]
  33. 查看最近30分钟的日志

    1
    docker logs --since 30m [容器名]
  34. 只打印最后50行日志

    1
    docker logs --tail=50 [容器名]
  35. 查看指定时间后的日志,只显示最后100行

    1
    docker logs -f -t --since="2019-10-24" --tail=100 CONTAINER_ID
  36. 设置开机自动启动docker服务

    1
    sudo systemctl enable docker
  37. 禁止自启

    1
    sudo systemctl disable docker
  38. 查看docker版本

    1
    docker version
  39. 创建数据卷容器

    1
    docker run -it --name=data -v /volume ubuntu:latest /bin/bash
  40. 其他容器挂载数据卷容器

    1
    docker run -it --name=c1 --volumes-from data ubuntu:latest /bin/bash
  41. 启动已经停止的容器

    1
    docker start [容器名]
  42. 强制停止正在运行的容器

    1
    docker kill [容器名]
  43. 查看所有容器id, 包括已经停止的容器

    1
    docker ps -aq
  44. 查看所有已启动容器id

    1
    docker ps -q
  45. 查看容器内部的进程

    1
    docker top 容器名
  46. 容器配置更新

    1
    docker update xxx

    比如 更新是否自启动:

    1
    docker update --restart=always

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

markdown导出带目录PDF的三种方法

发表于 2020-01-21

将文档导出PDF, 内容一旦比较多, 如果没有目录跳转的话找起来特别费劲, 以下是解决方案

第一种 使用CSDN

1. 编辑好文章后 点击导出, 选择导出为HTML

2. 选择导出的模板

3. 使用HTML转PDF工具进行格式转换

软件下载链接:https://wkhtmltopdf.org/downloads.html
使用方法:
wkhtmltopdf --disable-smart-shrinking html文件路径 导出的pdf文件路径 //html路径可使用网络路径

4. 如果嫌下载软件麻烦, 也可以直接使用浏览器导出

第二种 使用i5ting_toc工具

此法需要nodejs环境

使用方法:

第一步.安装i5ting_toc

npm install i5ting_toc -g

第二步 使用转换指令 先将md转成html

i5ting_toc -f [需要转换文件名].md

第三步 预览转换后的文件

i5ting_toc -o //默认在同级目录生成preview文件夹

第四步 用浏览器或者将HTML转成PDF即可
效果如下:

第三种 使用vscode插件 Markdown Preview Enhanced

使用方法:

第一步: 安装插件

第二步:打开需要转换的.md文件,右键选择打开同步预览

第三步 将光标放置想要生成目录的输出位置 右键打开命令面板 并输入Markdown Preview Enhanced: Create Toc

​

第四步 点击保存 文档将自动生成目录

第五步 导出你需要的格式 建议导出HTML 然后进行相应的转换即可

最终效果如下:

本帖附件

点击下载

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

新型冠状病毒肺炎安全防范手册健康宝典口罩选购佩戴正确洗手方式

发表于 2020-01-21

基本知识

对于新型冠状病毒肺炎你需要了解一些基本知识:

  一、病毒对外界环境耐受情况:对热敏感,56℃ 30分钟、75%酒精、含氯消毒剂(比如84消毒液)、过氧化氢消毒液(家庭很少用),氯仿等脂溶剂均可有效灭活病毒

  二、传播途径:飞沫传播—打喷嚏;近距离面对面;接触传播。

  三、感染后初期症状:发热(不一定高热,很多病例最初是低热),乏力,呼吸道症状以干咳为主,并逐渐出现呼吸困难,严重者急性呼吸窘迫综合征、脓毒症休克、难以纠正的代谢性酸中毒和出凝血功能障碍。部分患者起病症状轻微,可无发热。

  四、化验检查:发病早期白细胞总数正常或减低,淋巴细胞计数减少。

  多数患者C反应蛋白和血沉升高,降钙素原正常。

  五、痊愈标准:体温恢复正常3天以上、呼吸道症状明显好转,连续两次呼吸道病原核酸检测阴性(间隔至少1天),可解除隔离出院或根据病情转至相应科室治疗其他疾病

  提醒广大职工、研究生及离退休同志:

  一、减少外出,减少接触他人的机会

  二、有接触疑似或者确诊病人史,或者接触过来自疫区人员,从疫区返回人员,应自行居家隔离14天

  三、减少去生鲜市场,避免传染风险

  四、外出戴好口罩,最好N95口罩,压好密封条

  五、勤洗手

  六、饮食清淡,穿衣适中,增强自身免疫力

​ 七、避免在未加防护的情况下接触野生或养殖动物

​ 八、少吃野味

  九、假如出现类似症状,请您戴好口罩及时到发热门诊排查。

口罩分类与选购

药店里五花八门的口罩该如何选择?出门是不是一定要佩戴“网红”N95口罩?

市面上常见的口罩可以分为三类:

1.医用外科口罩

2.医用防护口罩(N95口罩)

3.普通棉纱口罩

其中医用外科口罩可以阻挡70%的细菌,N95口罩可以阻挡95%的细菌,而棉纱口罩只能阻挡36%的细菌,因此我们应该选择前两种口罩。

口罩正确佩戴方法

1.医用外科口罩

医用外科口罩有三层,从外到内分别是防水层、过滤层、舒适层,舒适层是一层纱布,佩戴时白色的纱布朝内,蓝色的防水层朝外,有金属片的一边朝上,不要戴反,橡皮筋挂上双耳后捏紧金属片和鼻子贴合,抚平两颊,使口罩和面部之间尽量不留缝隙。

具体佩戴步骤

第一步 将口罩罩住鼻、口及下巴,橡皮筋系在双耳后

*第二步. 将双手指尖放在鼻夹上,从中间位置开始,用手指向内按压,并逐步向两侧移动,根据鼻梁形状塑造鼻夹, 调整系带的松紧度 *

img

2. 医用防护口罩(N95口罩)

常用的N95口罩实际上分为两种,

  • 一种是防生物口罩(蓝绿色),型号1860或9132;

  • 一种是防尘口罩(白色),型号8210。

市民在购买时应选择防生物的医用防护口罩。佩戴防生物医用防护口罩时,将口罩罩在面部,先将下面的一根橡皮筋固定在脖子上,再将上面一根橡皮筋固定在头上,捏紧金属片,让口罩和面部贴合,不留缝隙。

具体佩戴步骤

第一步. 一手托住防护口罩,有鼻夹的一面背向外

第二步. 将防护口罩罩住鼻、口及下巴,鼻夹部位向上紧贴面部

img

第三步. 用另一只手将下方系带拉过头顶,放在颈后双耳下

img

第四步. 再将上方系带拉至头顶中部

img

第五步. 将双手指尖放在金属鼻夹上,从中间位置开始,用手指向内按鼻夹,并分别向两侧移动和按压,根据鼻梁的形状塑造鼻夹

img

如果还是不太明白怎么佩戴口罩 以下有相关视频 点击即可跳转播放

正确洗手法

洗手应该在流动水下进行,取适量洗手液(肥皂),均匀涂抹至整个手掌,认真搓揉双手至少15秒,清洗所有皮肤和指缝,具体步骤有七步:

1. 掌心相对,手指并拢相互揉搓

2. 手心对手背沿指缝互相揉搓,交替进行

3. 掌心相对,双手交叉指缝相互揉搓

4.双手指相扣互搓

5. 弯曲各手指关节在另一只手掌心旋转揉搓,交换进行

6. 一手握另一手大拇指旋转揉搓,交换进行

7. 将五个手指尖并拢放在另一手掌心旋转揉搓,交换进行

最后,在流动水下冲净双手,擦干,擦干宜使用纸巾。

家庭预防图解

本帖附件

点击下载

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

1…424344…50

乱码三千

android程序员一枚,擅长java,kotlin,python,金融投资,欢迎交流~

493 日志
143 标签
RSS
© 2025 乱码三千
本站总访问量次
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4
0%