office-已删除的OneNote笔记本在“更多笔记”中依然存在,如何删除?

使用的OneNote版本为ipad版。

解决方法是找到这里记录到底在哪里。

参考了OneNote for Windows 10 已经删除的笔记在“更多笔记本”中依然存在,无法删除记录

  1. 如果你的win10安装了名为Office的应用,打开它,或者,在网页中打开Office的控制面板 “https://www.office.com/?auth=1",登录。
  2. 在“最近”一栏下找到该文件,单击这一行右侧三个点的菜单栏,然后选择最后一项“从列表中删除”
  • 解决了。

android-android利用layout_behavior属性实现上滑屏幕,隐藏底部菜单栏

1
本文主要实现的功能是顶部工具栏和底部菜单栏随用户手势滑动而变化可见状态

底部导航栏的部分参考了android利用layout_behavior属性实现上滑屏幕,隐藏底部菜单栏——上官若枫

新建项目com.example.app

新建一个活动,实例代码的是MainActivity的。

它的布局简单来说就是:

1
2
3
4
5
CoordinatorLayout   //`app:layout_behavior`属性才能生效
AppBarLayout //容纳toobar(actionbar)
Toolbar //工具栏
TextView //代表主要内容
BottomNavigationView //底部导航栏

activity_main.xml的代码:

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
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.MainActivity">

<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<!-- app:layout_scrollFlags="scroll|enterAlways"
这个属性实现随着页面滚动标题栏(toolbar)显示隐藏-->
<androidx.appcompat.widget.Toolbar
android:id="@+id/default_action_bar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:title="工具栏的标题" />

</com.google.android.material.appbar.AppBarLayout>

<!-- app:layout_behavior="@string/appbar_scrolling_view_behavior"
这个属性只有在布局是CoordinatorLayout 时才有,是让控件显示在AppBarLayout之下的-->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="假装这里是内容"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />

<!-- 底部导航栏
需要新建一个菜单`bottom_navigation_menu`
`com.example.app.behavior.BottomNavigationBehavior`就是我们自定义的类
-->
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:labelVisibilityMode="labeled"
app:layout_behavior="com.example.app.behavior.BottomNavigationBehavior"
app:layout_scrollFlags="scroll|enterAlways"
app:menu="@menu/bottom_navigation_menu" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

自定义Behavior类

网上常见的app:layout_behavior的用法是app:layout_behavior="@string/appbar_scrolling_view_behavior"。虽然表面上看是一个字符串,其实在里面调用的也是一个view类。

这次我们通过自定义这个behavior类,实现底部菜单栏的显隐性。

原文章使用的是Java代码,这里贴一段我改写的Kotlin的代码。
我在项目中新建了一个名为behaviorPackage,并在这个Package中新建了文件BottomNavigationBehavior.kt

被注释的部分是被override的函数默认的代码。

BottomNavigationBehavior.kt的代码

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.example.app.behavior

import android.animation.ObjectAnimator
import android.content.Context
import android.util.AttributeSet
import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.ViewCompat

class BottomNavigationBehavior(context: Context, attrs: AttributeSet) :
CoordinatorLayout.Behavior<View>(context, attrs) {
private var outAnimator: ObjectAnimator? = null
private var inAnimator: ObjectAnimator? = null

override fun onStartNestedScroll(
coordinatorLayout: CoordinatorLayout,
child: View,
directTargetChild: View,
target: View,
axes: Int,
type: Int
): Boolean {
// return super.onStartNestedScroll(
// coordinatorLayout,
// child,
// directTargetChild,
// target,
// axes,
// type
// )
/**
* 滚动轴是不是竖直滚动轴。如果是的话,就返回true
*/
return axes == ViewCompat.SCROLL_AXIS_VERTICAL
}

override fun onNestedPreScroll(
coordinatorLayout: CoordinatorLayout,
child: View,
target: View,
dx: Int,
dy: Int,
consumed: IntArray,
type: Int
) {
// super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type)
/**
* 上滑隐藏
*/
if (dy > 0) {
if (outAnimator == null) {
outAnimator =
ObjectAnimator.ofFloat(child, "translationY", 0f, child.height.toFloat())
outAnimator?.duration = 200
}
if (!outAnimator!!.isRunning && child.translationY <= 0) {
outAnimator!!.start()
}

/**
* 下滑显示
*/
} else if (dy < 0) {
if (inAnimator == null) {
inAnimator =
ObjectAnimator.ofFloat(child, "translationY", child.height.toFloat(), 0f)
inAnimator!!.duration = 200
}
if (!inAnimator!!.isRunning && child.translationY >= child.height) {
inAnimator!!.start()
}
}
}
}

onStartNestedScroll
这个方法主要用于监听协调布局(CoordinatorLayout)的子view的滚动事件,当此方法返回true,表示要消耗此动作,继而执行下面的onNestedPreScroll方法,我们的代码中,如果滚动轴是竖直滚动轴,就返回true

onNestedPreScroll
这个方法就比较简单了,当用户上滑的时候,隐藏底部菜单栏,这里使用了ObjectAnimator动画的ObjectAnimator.ofFloat方法,第一个参数是view对象,指的就是bottom_navigation_view,第二个是Y轴的变化,第三个是Y轴变化的多少,接下来设置动画秒数。(注意Kotlin中要将参数转换为浮点数,否则不匹配函数签名,即代码中用了.toFloat0f的原因。)视觉效果为:bottom_navigation_view向Y轴下滑等于自身高度的量,由于其android:layout_gravity="bottom",它将会滑出可视区域。

(完)

Keycloak如何搭配MariaDB

设置步骤

下载Keycloak并解压

从keycloak的官网下载Keycloak后,解压到合适的位置。例如放在C:\keycloak-9.0.2这里。

下载JDK

还需要下载一份jdk才能运行keycloak。我选择的是openjdk 14Windows/x64 Builds,把它解压放在C:\jdk-14.0.1了。

修改standalone.conf.bat,设置JAVA_HOME

该文件在C:\keycloak-9.0.2\bin
因为选择用standalone.bat启动,所以需要修改standalone.conf.bat,打开它然后找到下面的代码:

1
rem set "JAVA_HOME=C:\opt\jdk1.6.0_23"

在它下一行新增一段:

1
set "JAVA_HOME=C:\jdk-14.0.1"

关系型数据库设置

然后参照文档中关系型数据库设置Relational Database Setup这一节进行设置。

下载MariaDB的JDBC驱动并解压

下载MariaDB的JDBC驱动,从MariaDB Connector/J .jar files这里的链接找到mariadb-java-client-2.6.0.jar下载回来,将它放在C:\keycloak-9.0.2\modules\system\layers\keycloak\org\mariadb\main(没有的路径部分需自行新建文件夹补齐)。可以选择右边的清华大学 TUNA 协会 (Tsinghua University TUNA Association)的镜像,在国内会更快。

新建module.xml

在同一个文件夹下新建module.xml,内容如下:

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" ?>
<module xmlns="urn:jboss:module:1.3" name="org.mariadb">
<resources>
<resource-root path="mariadb-java-client-2.6.0.jar"/>
</resources>

<dependencies>
<module name="javax.api"/>
<module name="javax.transaction.api"/>
</dependencies>
</module>

修改standalone.xml

接着修改C:\keycloak-9.0.2\standalone\configuration\standalone.xml

增加<driver>

打开这个文件,搜索下面的代码段

1
2
3
4
5
6
7
8
9
10
<subsystem xmlns="urn:jboss:domain:datasources:5.0">  
<datasources>
...
<drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
</drivers>
</datasources>
</subsystem>

增加几行mariadb的<driver>(其中的org.mariadb.jdbc.MySQLDataSource是坑点):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<subsystem xmlns="urn:jboss:domain:datasources:5.0">  
<datasources>
...
<driver name="mariadb" module="org.mariadb">
<xa-datasource-class>org.mariadb.jdbc.MySQLDataSource</xa-datasource-class>
</driver>

<drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
</drivers>
</datasources>
</subsystem>

增加<datasource>

这个几行<drivers>之上,能找到数个<datasource>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<subsystem xmlns="urn:jboss:domain:datasources:5.0">  
<datasources>
...
<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true" statistics-enabled="${wildfly.datasources.statistics-enabled:${wildfly.statistics-enabled:false}}">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
...
</datasources>
</subsystem>

我们加一个同级的MariaDB的<datasource>

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
<subsystem xmlns="urn:jboss:domain:datasources:5.0">  
<datasources>
...
<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true" statistics-enabled="${wildfly.datasources.statistics-enabled:${wildfly.statistics-enabled:false}}">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>

<datasource jndi-name="java:jboss/datasources/KeycloakDS" pool-name="KeycloakDS" enabled="true" use-java-context="true">
<connection-url>jdbc:postgresql://localhost/keycloak</connection-url>
<driver>postgresql</driver>
<pool>
<max-pool-size>20</max-pool-size>
</pool>
<security>
<user-name>William</user-name>
<password>password</password>
</security>
</datasource>
<datasource jndi-name="java:jboss/datasources/MariadbDS" pool-name="MariadbDS" enabled="true" use-java-context="true">
<connection-url>jdbc:mariadb://localhost:3306/keycloak?useUnicode=yes&amp;characterEncoding=UTF-8&amp;autoReconnect=true</connection-url>
<driver>mariadb</driver>
<pool>
<max-pool-size>20</max-pool-size>
</pool>
<security>
<user-name>wendy</user-name>
<password>HghP201foae413JvitOrVMBo</password>
</security>
<validation>
<check-valid-connection-sql>select 1</check-valid-connection-sql>
<background-validation>true</background-validation>
<background-validation-millis>15000</background-validation-millis>
</validation>
</datasource>
...
</datasources>
</subsystem>

其中的<connection-url>jdbc:mariadb://localhost:3306/keycloak?useUnicode=yes&amp;characterEncoding=UTF-8&amp;autoReconnect=true</connection-url>指的是MariaDB使用默认的3306端口,用UTF-8编码(编码这里也是坑),<user-name>wendy</user-name><password>HghP201foae413JvitOrVMBo</password>是Keycloak访问MariaDB使用的用户名和密码(明文密码)。

修改Keycloak使用的datasource为mariadb

然后在standalone.xml中搜寻connectionsJpa,找到以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
...
<spi name="connectionsJpa">
<provider name="default" enabled="true">
<properties>
<property name="dataSource" value="java:jboss/datasources/KeycloakDS"/>
<property name="initializeEmpty" value="true"/>
<property name="migrationStrategy" value="manual"/>
<property name="migrationExport" value="${jboss.home.dir}/keycloak-database-update.sql"/>
</properties>
</provider>
</spi>
...
</subsystem>

<property name="dataSource" value="java:jboss/datasources/KeycloakDS"/>一行后:

1
2
3
4
5
6
7
8
9
10
11
12
13
<subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
...
<spi name="connectionsJpa">
<provider name="default" enabled="true">
<properties>
<property name="dataSource" value="java:jboss/datasources/MariadbDS"/>
<property name="initializeEmpty" value="true"/>
<property name="migrationStrategy" value="update"/>
<property name="migrationExport" value="${jboss.home.dir}/keycloak-database-update.sql"/>
</properties>
</provider>
...
</subsystem>

运行C:\keycloak-9.0.2\bin\standalone.bat启动Keycloak

在浏览器中打开http://localhost:8080/auth,注册管理员账号后就可以了。

其他没有讲的

  1. 可能需要手动新建一个叫keycloak的数据库
  2. 需要新建一个可以读写该数据库的用户,比如上面的wendy,并授予足够的权限,偷懒可以把keycloak.*都授权给他。

keycloak是……?

从keycloak的官网下载

MariaDB是……?

从MariaDB的官网下载,记得选择适当的版本(Version)和正确的操作系统(OS),例如10.4.12-GAMS Windows (64-bit)

学习CorelDRAW的流水账

用于学习CorelDRAW(以下简称CDR)的书本是学校发的《CorelDRAW X6中文版标准教程》(人民邮电出版社)。这本书可以说非常老了。与比较新版的软件相比,界面有些区别。不过,大部分的操作是相同的。

本文仅用于记录学习的进度。

Read More

随鼠标移动的音符特效

《初音未来:梦幻歌姬》手游停服挺久了,曾经玩过几次。因为有PS4版的(以及后来的NS版),所以非常不喜欢手游过度专注于“刷刷刷”这点。我只想要听她唱歌看她跳舞而已。
非常喜欢手游官网界面上的鼠标特效,所以一直想学习,却又一直偷懒。这次终于把特效偷出来了。然而,真正学习怎么实现,恐怕不知道哪天了。

第一步,假设你需要在index.html中加入这个鼠标特效,在<body>中加入两行后,这个文件的内容是:

1
2
3
4
5
<!DOCTYPE html>
<body>
<script id="mymouse" src="/js/pc_mouse.js"></script>
<script src="/js/jquery-1.11.3.min.js"></script>
</body>

如果JQuery的版本或者路径不同,改这里。

第二步,下载pc_mouse.js

第三步,下载这八个图片:

  • subball1.png
  • subball2.png
  • subball3.png
  • subball4.png
  • subball5.png
  • subball6.png
  • subball7.png
  • subball8.png

第四步,下载一个JQuery,最低需求1.11.3

这几个文件的组织形式是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
- <网站根目录>/
- images/
subball1.png
subball2.png
subball3.png
subball4.png
subball5.png
subball6.png
subball7.png
subball8.png
- js/
pc_mouse.js //如果图片的位置不同,要改这个文件,搜`.png`改两处URL。
jquery-1.11.3.min.js //可以是更高版本
index.html

一般来说,用浏览器打开index.html就能看到效果了。

golang-有用的代码片段

好久没有写文章了呢~
一旦忙于做其他的事或者懒下来,就不想做别的了。
新冠肺炎造成的社会停摆终于结束了。
今年也要加油!!

判断文件或文件夹是否存在

1
2
3
4
5
if _fileInfo_,err:=os.Stat("path/to/file");os.IsNotExist(err){
// file not exist
} else {
// file exist
}

日期的格式化

也许Go语言的开发者肯·汤普逊Ken Thompson比较自恋,所以格式化时间日期时使用的layout字符串也奇葩。
01/02 15:04:05PM 2006 -0700MM/DD HH:mm:SS'PM YYYY 'MST相比,记忆难度差不多。(MST是指北美山区时区标准时间)

参考:golang/Format a time or date [complete guide]

1
2
3
4
5
6
7
8
9
10
const (
layoutISO = "2006-01-02"
layoutUS = "January 2, 2006"
layoutCHINA="2006-01-02 15:04:05" // 年-月-日 时:分:秒 YYYY-MM-DD HH:mm:SS
)
date := "1999-12-31"
t, _ := time.Parse(layoutISO, date)
fmt.Println(t) // 1999-12-31 00:00:00 +0000 UTC
fmt.Println(t.Format(layoutUS)) // December 31, 1999
fmt.Println(t.Format(layoutCHINA)) // 1999-12-31 00:00:00

函数time.Parse解析一个日期字符串;time.Time类型的值可以用Format函数格式化成字符串。

两个函数的签名分别是:

1
func Parse(layout, value string)(Time,error)
1
func (t Time) Format(layout string)string

预定义的layout,例如:time.RFC3339

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ANSIC       = "Mon Jan _2 15:04:05 2006"
UnixDate = "Mon Jan _2 15:04:05 MST 2006"
RubyDate = "Mon Jan 02 15:04:05 -0700 2006"
RFC822 = "02 Jan 06 15:04 MST"
RFC822Z = "02 Jan 06 15:04 -0700"
RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700"
RFC3339 = "2006-01-02T15:04:05Z07:00"
RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
Kitchen = "3:04PM"
// Handy time stamps.
Stamp = "Jan _2 15:04:05"
StampMilli = "Jan _2 15:04:05.000"
StampMicro = "Jan _2 15:04:05.000000"
StampNano = "Jan _2 15:04:05.000000000"

想格式化成自定义格式时使用以下数字、字符进行组合作为layout参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
类型      可选
--------------
年 06 2006
月 01 1 Jan January
日 02 2 _2(宽度2,右对齐)
星期 Mon Monday
-----------------------------
时 03 3 15
分 04 4
秒 05 5
毫秒 .000 .999(后者会移除尾部的零)
微妙 .000000 .999999(后者会移除尾部的零)
纳秒 .000000000 .999999999(后者会移除尾部的零)
-------------------------------------------------------
上午下午 PM pm
时区 MST
时差 -0700 -07 -07:00 Z0700 Z07:00

获取文件修改时间

1
2
fileInfo,_:=os.Stat("path/to/file")
file.ModTime() //文件修改时间

NET/HTTP

跳过HTTPS证书检查

1
2
3
4
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{Transport:tr}

华为物联网平台的证书居然不匹配,说的是这个:https://iotda.cn-north-4.myhuaweicloud.com/。于是测试时出现“Post https://iotda.cn-north-4.myhuaweicloud.com/v5/iot/{project_id}/subscriptions: x509: certificate is valid for *.apigw.cn-north-4.huaweicloud.com, not iotda.cn-north-4.myhuaweicloud.com”的错误


HTTP路由

Go自带的ServeMux路由的能力太薄弱,所以换用第三方开发的吧
更多规则和用法参考:https://github.com/gorilla/mux

1
go get -u github.com/gorilla/mux
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func main() {
r := mux.NewRouter()
r.HandleFunc("/", HomeHandler)
r.HandleFunc("/products", ProductsHandler)
r.HandleFunc("/articles", ArticlesHandler)
// http.Handle("/", r)

// r := mux.NewRouter()
r.HandleFunc("/products/{key}", ProductHandler)
r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler)
r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler)
http.Handle("/", r)

//http.ListenAndServe(...)
}

func ArticlesCategoryHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "Category: %v\n", vars["category"])
}

使用MySQL数据库

首先在项目中安装驱动https://github.com/go-sql-driver/mysql

1
go get -u github.com/go-sql-driver/mysql

然后在需要使用MySQL数据库的文件中导入

1
2
3
4
import "database/sql"
import _ "github.com/go-sql-driver/mysql"

db, err := sql.Open("mysql", "user:password@/dbname")

unity-从hub启动后闪退

Unity整合到UnityHub中后,似乎就有这个与许可证有关的Bug。

BUG的现象是:从UnityHub启动一个已有的项目,显示Unity的启动画面,但是几秒钟后就返回UnityHub的界面了,而Unity没有进入主界面就悄无声息地关闭了。

后来从这个帖子找到了解决方法,按19楼描述的做法做了,就解决了。

具体步骤是打开“设备管理器”,卸载“Xbox Wireless Adapter for Windows”,然后再UnityHub中退还许可证,再激活新的许可证。之后就可以装回“Xbox Wireless Adapter for Windows”了。

不过,下一次是否会再出问题呢?一个手柄驱动就把Unity的技术人员给打趴了。看来是生成许可证的时候把某些设备连接当成生成依据,却产生了Bug。

如何禁止Win10的屏幕键盘

在有外接键盘的情况下,我的笔记本电脑仍然在不恰当的时候弹出触摸键盘,忍不了了。

网上找到两个方法:

  • 第一个是试过但是无效的。启动Win10自带的“服务”,找到Touch keyboard and handwriting service,改为手动并停止。然而它的启动类型是“触发器启动”,即便停止也会被不知道谁再次启动。
  • 第二个方法有效。因为触摸键盘的程序文件是tabtip.exe,在C:\Program Files\Common Files\microsoft shared\ink目录下。将它改名为tabtop.exe.bak,它就再也不会胡来了。如果遇到权限问题,可能要先将它的服务停止,并且改名需要管理员权限。但是,因为有一个叫IOBit Unlocker的软件,解锁+改名,直接搞定了。

学习3ds Max的流水账

学校发的书是《3ds Max 2009基础教程》(清华大学出版社)。
这本书不仅已经落后于时代,而且书中描述操作步骤时经常省略关键细节……
另外,书中非常喜欢用图标表示点击了哪个功能按钮,但是新版软件使用了新图标时,看书就变成猜谜游戏……

以下只是看书的流水账,主要用于记录进度。

Read More