1.收获
今天开始做小的Android的demo,虽然在早上大部分时间讲的都是理论,虽然这些理论听着是有点枯燥的,但是对于我这种人来说,是非常好的,因为我一个爱去搞明白的人,当我碰到一些难题时,就会去思考他为什么是这样,为什么要这么做,不搞明白不罢休的那种,这些理论的知识就为后面的做demo种下了基础,就不会在讲的去耽误很多的时间。所以我在后面的demo中理解上很轻松。就是有的方法不是太熟悉,不知道怎末用他们,自己害怕忘记了,自己还把他们记下来了。这集训的一个月就这样过去了,自己学到了多少东西,只有自己知道,时间还有,初心还在!加油!
2.技术
(1)界面的布局
(2)scaleType的使用
(3)控件的添加
(4)测量控件的坐标和本身的大小
(5)图案解锁demo(前面小部分)
3.技术的实际应用和实践
(1)界面的布局
在上节课中我们讲了界面布局的方式有6种

这节课可我们讲了怎样去布局,哪些布局方式是常用的,有哪些属性,接下来如下图
线性布局 LinearLayout
LinearLayout: LinearLayout.LayoutParams
Margin:控件边缘和其他控件的间距- 外间距
Padding:控件内部和⾃自⼰己边缘的间距- 内间距

其中的属性

相对布局 RelativeLayout
在MaraginLayout的基础上添加了对齐
(当前这个控件和v1哪边对齐)
Layout_alignRight=”@id/v1”
Layout_alignLeft=”@id/v1”
Layout_alignTop=”@id/v1”
Layout_alignBottom=”@id/v1”
约束布局 ConstraintLayout
添加约束条件(代码):
<View
android:id="@+id/v1"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@color/colorAccent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/v2"
android:layout_marginLeft="50dp"
android:layout_marginTop="50dp"
android:layout_marginRight="50dp"
android:layout_marginBottom="50dp"
/>
<View
android:id="@+id/v2"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@color/colorPrimary"
app:layout_constraintStart_toEndOf="@id/v1"
app:layout_constraintTop_toTopOf="@id/v1"
app:layout_constraintBottom_toBottomOf="@id/v1"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginRight="50dp"
/>
图片:

效果:

(2)scaleType的使用
在设置背景图片时的Android:scaleType=”T”表示什么意思

现在解释如下:

(3)控件的添加
首先我们要确定该容器是什么布局,我们才能知道用什么属性和方法
首先在这里修改布局方式

让后在XML文件中添加控件
添加背景图片(想要添加自己想要的图片要把图片拖到drawble下面)

<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/main_bg"
android:scaleType="fitXY"/>
添加子控件
<ImageView
android:id="@+id/opview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/op_bg"
android:layout_centerInParent="true"
/>
(4)测量控件的坐标和本身的大小
现在有一问题就是我们把控件添加到什么地方,我们就需要坐标,那麽这个坐标我们怎么去获取呢
搞清楚手机的坐标系

然后再来确定控件的坐标和本身的大小
在这里我们需要重写方法onWindowFocusChanged(boolean hasFocus) {}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
//获取屏幕密度
float a=getResources().getDisplayMetrics().density;
//判断是否已经显示
if(hasFocus){
//获取容器
RelativeLayout rl=findViewById(R.id.rootlayout);
//获取背景视图
ImageView iv=findViewById(R.id.opview);
//获取x和y以及本身的长和宽
int x=iv.getLeft();
int y=iv.getTop();
int w=iv.getWidth();
int h=iv.getHeight();
}
安卓 在容器中添加的控件需要被window计算/测量
通常在onCreat,onStart,onResume无法获取控件本身的尺寸
所有的测量都是在另一个线程中操作
如果想要获取控件的尺寸 就得要用重写onWindowFocusChanged(boolean hasFocus){}方法
Android中获取手机屏幕的高度和宽度,我们知道在onCreate方法中获取到的值都是为0的,有人说可以在onClick方法中获取值,这个也是个方法 ,但在onWindowFocusChanged方法中可以直接获取到,而且有的时候场景的需要,就不得不在Activity渲染完成后立马获取值,这时候onWindowFocusChanged()方法就用到实处了,类似的有PopupWindow的显示,如果在onCreate方法中执行的话,会报没有token的异常,就是因为Activity没有渲染成功.
onWindowFocusChanged():当Activity的当前Window获得或失去焦点时会被回调此方法。当回调了这个方法时表示Activity是完全对用户可见的(只是可见,还一片黑呼呼的,有待draw..)。当对话框弹起/消失及Activity新创建及回退等都会调用此方法。
相比之下,onResume()方法更多的是指Activity进入了可见的状态,但只是状态,并不是真正的界面构建完成了。
至此,如果需要获取某个View的宽高,可以在onWindowFocusChanged()处直接获取即可,这比对某个view设置onGlobalLayoutListener的方式来获取方便了许此。又比如,对于需要读取本地文件记录来判断是否是第一次打开界面去提示文本图片的,也可以在此方法中去读取然后再显示在ui上。
(5)图案解锁demo(前面小部分)
在前面的基础上我们需要添加一些东西
//创建横线
for(int i=0;i<3;i++){
for (int j = 0; j < 2; j++) {
//创建一个视图显示线
ImageView lineView=new ImageView(this);
//设置图片
lineView.setBackgroundResource(R.drawable.normal_highlight1);
//创建布局参数
RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
params.leftMargin=(int)(x+46.6*a+99*a*j);
params.topMargin=(int)(y+170*a+99*a*i);
rl.addView(lineView,params);
}
}
```//创建竖线
for(int i=0;i<2;i++){
for (int j = 0; j < 3; j++) {
//创建一个视图显示线
ImageView lineView=new ImageView(this);
//设置图片
lineView.setBackgroundResource(R.drawable.normal_highlight2);
//创建布局参数
RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
params.leftMargin=(int)(x+42*a+99*a*j);
params.topMargin=(int)(y+170*a+99*a*i);
rl.addView(lineView,params);
}
}
//创建右竖线
for(int i=0;i<2;i++){
for (int j = 0; j < 2; j++) {
//创建一个视图显示线
ImageView lineView=new ImageView(this);
//设置图片
lineView.setBackgroundResource(R.drawable.normal_highlight3);
//创建布局参数
RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
params.leftMargin=(int)(x+42*a+99*a*j);
params.topMargin=(int)(y+170*a+99*a*i);
rl.addView(lineView,params);
}
}
//创建左竖线
for(int i=0;i<2;i++){
for (int j = 0; j < 2; j++) {
//创建一个视图显示线
ImageView lineView=new ImageView(this);
//设置图片
lineView.setBackgroundResource(R.drawable.normal_highlight4);
//创建布局参数
RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
params.leftMargin=(int)(x+54*a+99*a*j);
params.topMargin=(int)(y+170*a+99*a*i);
rl.addView(lineView,params);
}
}
//九个点
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//创建用于显示点的视图
ImageView dotView=new ImageView(this);
//隐藏视图
dotView.setVisibility(View.VISIBLE);
//显示对应的图片
dotView.setBackgroundResource(R.drawable.selected_dot);
//创建控件的尺寸
RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.leftMargin=(int)(x+35*a+99*a*i);
params.topMargin=(int)(y+164*a+99*a*j);
//将子控件添加到容器中
rl.addView(dotView,params);
}
}
}
}
效果:
