关于如果自己定义安卓的布局界面的初学研究

来源:互联网 发布:sql timestampdiff 编辑:程序博客网 时间:2024/06/05 14:13
之前看一段外面的开源代码,怎么看也看不懂。


之后苦苦思索了半天,才算是略有体会。


主要的问题在于:在我看的开源代码里面,作者自己定义了一个Layout,而未曾使用系统自带的如LinearLayout的页面布局。


这对于初学者来说,问题就大了,因为完全不明白这其中的道理。


之后便不断的自己尝试和查找资料,虽然脑拙,到现在总算是明显了十之六七。


首先,先要理解一下Android自己原本的布局。


下面这一段是最原始的Android布局的XML代码

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"    android:orientation="vertical">    <Button        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="点我"        android:id="@+id/button" />    </LinearLayout>

这没什么可以多说的,无非就是一个<LinearLayout>的布局,里面再配了一个Button的按钮。这些都是系统自己定好的,我们直接用就可以了。


还有一种就是我们把LinearLayout这套布局全部改掉。


再看一段代码

<com.tantanwen.dantest_01.views.SliderLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"    android:orientation="vertical"    android:id="@+id/root_layout">    <Button            android:text="@string/hello_world"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:background="#aaabbb"            android:id="@+id/textView1" />    <LinearLayout        android:layout_width="match_parent"        android:layout_height="match_parent"        android:background="@drawable/page2">    </LinearLayout></com.tantanwen.dantest_01.views.SliderLayout>


看出有什么区别吗,就是<LinearLayout >这个东西变成了<com.tantanwen.dantest_01.views.SliderLayout>


LinearLayout是系统定的,而com.tantanwen.dantest_01.views.SliderLayout是我自己定的,为什么是这以长这么古怪的名字呢?


因为它要和我们的JAVA类对应起来。也就是说,我起了这个名字,同样的,我必须在包com.tantanwen.dantest_01.views下面新建一个叫SliderLayout的类的方法。


而且这个类方法必须继承一个叫ViewGroup的UI界面类,这是Android中的父类,也就是如果涉及到界面上所有的控件的,都是从这个类继承下来的。(还有一个叫View的父类,不过我还没研究过,现在统一从ViewGroup继承)


继承以后,还必需创建对应的构造方法,以及两个需要重写的指定方法,这是系统规定的,如果不这么做,程序就会出错,无法正常编译或是编译了你看不到界面上有任何东西。


为什么呢?因为有些东西你重定义了,所以就必须全部自己指定。

package com.tantanwen.dantest_01.views;import android.content.Context;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup;import android.widget.Button;/** * Created by dan on 2015/6/25. */public class SliderLayout extends ViewGroup {    public SliderLayout(Context context) {        super(context);    }    public SliderLayout(Context context, AttributeSet attrs) {        super(context, attrs);    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        // 这里是指所有布局下面的所有控件,如button,textView什么的,我现在遍历它们        //为什么要遍历?因为我要给他们重定义坐标        for (int i = 0; i < getChildCount(); i++) {            //得到这个控件的对象            View child = getChildAt(i);            // 取出当前子View长宽            int width   = child.getMeasuredWidth();            int height  = child.getMeasuredHeight();            //上面两个对象我没用,有兴趣可以自己研究一下,我现在主要测试显示。            int mLeft;            int mTop;            if(child instanceof Button) {                mLeft   = 20;                mTop    = 80;                width   = 160;            }else{                mLeft   = 600;                mTop    = 0;            }            /*                调用layout并传递计算过的参数为子view布局                这里有四个值,分别对应什么呢?                从左到右依次:距离控件(你就理解成手机屏幕好了)右边多少距离,距离控件上面多少距离,右边多少距离,下面多少距离。                完成这一步之后,屏幕上才会显示你要的子控件            */             child.layout(mLeft, mTop, mLeft + width, mTop + height);        }    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){        measureChildren(widthMeasureSpec, heightMeasureSpec);        super.onMeasure(widthMeasureSpec,heightMeasureSpec);    }}


SliderLayout两个同名的,就是构造方法,不用管,定好的。


onMeasure方法,好吧……查了下资源,说这个方法主要的作用就是测量布局的高度和宽度,再调用父类方法把数值传过吧。

嗯,其实这段目前也是定死的,直接复制着用就行了,必竟还是初学者,没研究到这么深,而且目前也没有特别要用到的这块的地方,照抄就行了。


最后是layout方法,这个方法是用来重新布局我自定义的界面中所有的控件的。


就如同我在函数中写的那样,

getChildCount这个函数是得到所有的控件的数量
比如我前面定义的XML
    <Button            android:text="@string/hello_world"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:background="#aaabbb"            android:id="@+id/textView1" />    <LinearLayout        android:layout_width="match_parent"        android:layout_height="match_parent"        android:background="@drawable/page2">

有两个控件,一个按钮Button,一个叫LinearLayout的层
所以getChildCount就是2,做两次循环,然后定义上下左右的方向,重新画到手机屏幕上面。
这里用了一段
if(child instanceof Button) {
我主要是判断一下是否是按钮还是层,把两个控件的坐标拉到不同的地方,以免重合在一起。
最后,我现在代码全写完了,可以编译,实际看一下效果了。
嗯?这样就行了?是的,SliderLayout类里的方法你定义好就行了,系统会自己搞定的。
我试着编译了一下。
已经出现了我想要的效果了,这就是我自己定义的布局,按钮在左边靠上,层在右边,层本身是不可见的,不过我给他加了一段背景图,就变成一个导航条的样子了。
不过……感觉还是怪怪的啊,为什么有种没有撑满整个屏幕的感觉?
其实是因为系统默认的我自定义的层与屏幕两边有边距造成的。我再改一下。
到MainActivity的类中加一段代码:
    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);                //找到我自己定义的层,根据ID,这个ID是我赋给自己定义的层的        mSliderLayers = (SliderLayout)findViewById(R.id.root_layout);        //把边距全部调成没有,即0,这也是上下左右四个。        mSliderLayers.setPadding(0,0,0,0);    }


好了,我再运行一下
这次总算是正常了。
总算是满足我现在的要求了,第一阶段结束。

0 0
原创粉丝点击