布局阶段

作者: sakurajiang | 来源:发表于2016-09-21 11:41 被阅读76次

    这一阶段是对于布局的设置,因为对于一般的软件而言,当你点击进去某个activity时,往往这个activity与之前的activity有一些地方的显示
    是相同的,比如,头部和尾部,那么这时为了减少工作量,我们可以使用include标签,对于include标签的使用,在这里提一下需要注意的地方,
    如果你要在include标签中重新指定布局参数(android:layout_*属性),,就必须覆盖android:layout_height和android:layout_width。因为这
    样才会生效,不然会提示错误。如果你是想指定过一个id,那么重新指定的id会覆盖原来的id。同时这里需要提一下很重要的一点,如果你想在
    代码中为include标签重新指定内容,那么如果你直接通过id找到这个include标签,然后将view添加到这个标签中,这样是得不到的,可能就是
    你通过id的确找到了这个标签,但是这个并不是真正的viewgroup,所以你无法将自己的view添加到上面,代码如下:

    public void setActivityTitle(int RLayoutId,int account){  
    //找到include标签  
     LinearLayout linearLayout1= (LinearLayout) findViewById(R.id.include1);  
    //找到要附在include标签上的view  
     LinearLayout linearLayout= (LinearLayout) LayoutInflater.from(this).inflate(RLayoutId, null);  
     TextView textView= (TextView) linearLayout.findViewById(R.id.usertitlt_tv);  
     textView.setText(getString(R.string.useractivitytitle_name) + "(" + account + ")");  
    //附在include标签上  
     linearLayout1.addView(linearLayout);  
     }  
    

    这样是得不到的,那么我们应该怎么做呢?代码如下:

     public void setActivityTitle(int RLayoutId,int account){  
     //找到include标签  
        LinearLayout linearLayout1= (LinearLayout) findViewById(R.id.include1);  
      //将这个标签设置为不可见,注意这里设置为不可见,而不是GONE,因为如果是GONE就意味着这个include标签不存在,那么可能会影响整个布局  
        linearLayout1.setVisibility(View.INVISIBLE);  
    //找到这个include标签在的那个整个布局,之所以这里通过id来找,而不是通过inflate来生成,是因为生成之后你还需要再setcontextview()。  
        RelativeLayout relativeLayout= (RelativeLayout) findViewById(R.id.mainRelativeLayout);  
        LinearLayout linearLayout= (LinearLayout) LayoutInflater.from(this).inflate(RLayoutId, null);  
        TextView textView= (TextView) linearLayout.findViewById(R.id.usertitlt_tv);  
        textView.setText(getString(R.string.useractivitytitle_name) + "(" + account + ")");    
     //将要附加的view附加在整个布局上。    
        relativeLayout.addView(linearLayout);    
    }
    

    这就是使用include标签需要注意的一些地方。
    在这里也需要说一下布局的各个属性问题,由于篇幅问题,这里就提一个,就是layout_marginpadding的区别,layout_margin是控件在布局显
    示的样子,padding则是控件的内容在控件中的位置,同时,Layout_grivatygrivaty这两者与之相似,layout_grivatylayout_margin对应,
    grivatypadding对应,那么,layout_margn与layout_grivaty有什么区别呢?grivaty与padding又有什么区别呢?layout_grivaty与grivaty
    的值都是给定的,我们只能在这些给定的属性中选择,而layout_margn与padding的值我们可以任意给,相对于layout_grivaty和grivaty更灵活,
    我们根据需要选择合适的属性。
    总之有layout的就是跟控件在布局中显示有关,没有的则是控制控件的内容的位置。

    今天在设置布局时,因为我们想将所有的title去掉,那么如果我们去每一个activity中找,并且去掉,这样是非常不合理的,因此我们需要在
    一个activity中管理一下,因此我定义了一个activityFrame继承了activity,这样我真正的activity都可以继承自定义的activity,这样管理
    起来就很方便,那么我们可以requestWindowFeature(Window.FEATURE_NO_TITLE);来让它没有标题,同时因为我们需要动态的添加布局,我们可以这么办,步骤可以分为三步:
    1.先找到我们需要插入的位置的布局,如我要插入到下面布局中的relativeLayout布局中

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.jdk.myaa.MainActivity">
    <include layout="@layout/title_layout" android:id="@+id/include1"></include>
    <include layout="@layout/buttom_layout" android:id="@+id/include2"></include>
    <RelativeLayout
    android:id="@+id/main_bodyRelativeLayout"
    android:layout_below="@id/include1"
    android:layout_above="@id/include2"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    </RelativeLayout>
    </RelativeLayout>
    

    我们如何找到这个布局呢?通过代码: RelativeLayout relativeLayout= (RelativeLayout) findViewById(R.id.main_bodyRelativeLayout);
    这样就找到了这个布局。
    2.找到我们需要插入的布局,如我要插入如下布局:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <GridView
        android:id="@+id/gv"
        android:paddingLeft="20dp"
        android:paddingRight="20dp"
        android:paddingTop="130dp"
        android:horizontalSpacing="10dp"
        android:verticalSpacing="100dp"
        android:numColumns="3"
        android:layout_width="wrap_content"
        android:layout_height="200dp"
        android:listSelector="@drawable/myselector"
        ></GridView>
    </LinearLayout>
    

    这个如何寻找呢?通过下面代码:
    ViewGroup v= (ViewGroup) LayoutInflater.from(this).inflate(R.layout.main_bodylayout, null);其中R.layout.main_bodylayout是上面
    布局的名字。
    3.将这个布局添加到对应的位置的布局中:
    relativeLayout.addView(v);
    这样就完成了动态添加,当然所添加的布局的属性会与你需要插入的布局属性相同,也就是跟第二步骤的布局相同,但是你也可以自己设置,设置的代码如下:

    RelativeLayout.LayoutParams layoutParams=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.MATCH_PARENT);
    relativeLayout.addView(v,layoutParams);
    

    这样就行了。 上面是添加一个布局到对应位置中去,那么如何添加一个控件到对应的位置中去呢?
    这个步骤与上述类似
    1.与上面一致
    2.找到我们需要插入的控件,比如我想插入这个布局中的GridView控件,如下:

     <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <GridView
        android:id="@+id/gv"
        android:paddingLeft="20dp"
        android:paddingRight="20dp"
        android:paddingTop="130dp"
        android:horizontalSpacing="10dp"
        android:verticalSpacing="100dp"
        android:numColumns="3"
        android:layout_width="wrap_content"
        android:layout_height="200dp"
        android:listSelector="@drawable/myselector"
        ></GridView>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="hahaha"/>
    </LinearLayout>
    

    那么我们该如何找到呢?代码如下:

    ViewGroup v= (ViewGroup) LayoutInflater.from(this).inflate(LayoutId, null);
    GridView g= (GridView) v.findViewById(R.id.gv);
    v.removeView(g);
    

    这里说一下第三行代码的作用,如果你没有这行代码,那么就会报错:
    The specified child already has a parent. You must call removeView() on the child's parent first.
    也就是说这个控件已经有一个parent了,我们要使用这个控件,就必须使用这个parent,如果你要强制使用这个
    控件,那么你就需要让这个控件与这个parent脱离父子关系,也就是用这行代码,要理解这个,我们先理一下
    activitywindowview的关系其实我们可以这么理解,假设activity是一个工人,他做了一个window,而这个
    window需要玻璃,玻璃就是这个view,更准确是viewgroup,也就是根视图,然后我们需要打扮这个窗户,也就是
    往窗户上贴窗花,假设我们的窗花是需要贴在纸上,然后让纸贴在玻璃上,因为这样我们以后要清除的时候,只要
    把纸撕了就行,也就是说方便管理,然后这个窗花就是控件,纸就是view,也就是各种子视图,然后我们这里的情
    况是要在这张纸上贴别的纸上的窗花,我们当然得把它撕下来先,也就是去掉父子关系,这就是第三行代码的作用
    。不知道这么说你们是不是理解了呢?这里再加一些内容,其中的窗户实际上是phonewindow,而玻璃是viewgroup,
    那么这个玻璃是怎么创建的呢?是通过activity方法中的attach()方法创建的,通过源代码你也可以看的到这是一个
    phonewindow对象,那么什么时候调用的attach()方法呢?是在ActivityThreadperformLaunchActivity中调用了,
    那么这里的纸是怎么创建的呢?是通过LayoutInflaterinflate()方法创建的,原料就是那些layout布局文件,而
    这里的窗花就是控件,这个是在layout中写出来的或者用代码动态生成。将窗花贴在纸上是通过addview()方法,将
    纸贴在玻璃上,是通过setcontentview()方法。那么玻璃(viewgroup)怎么生成的呢?实际上是通过installDecor();
    方法得到的,这里的viewgroup更准确的说是DecorView,而installDecor();方法是生成DecorView,并且根据窗口属
    性加载顶级视图布局、获取mContentParent、设置一些基本属性等。接下来还是放一张图片来说一下:

    1
    一、DecorView为整个Window界面的最顶层View。
    二、DecorView只有一个子元素为LinearLayout。代表整个Window界面,包含通知栏,标题栏,内容显示栏三块区域。
    三、LinearLayout里有两个FrameLayout子元素。
    (20)为标题栏显示界面。只有一个TextView显示应用的名称。也可以自定义标题栏,载入后的自定义标题栏View将加入FrameLayout中。
    (21)为内容栏显示界面。就是setContentView()方法载入的布局界面,加入其中。
    这样是不是清晰点了。
    3.与上面一样。
    relativeLayout.addView(g);至于这里为什么事g而不是v应该理解吧。

    这里还需要说一下,setcontentview()方法的作用,作用其实就是将纸贴在玻璃上,但是这里需要提一下:
    activity 调用 setContentView() 时,Android 才会去绘制 layout 上的各个元素,并为其分配内存。
    只有分配了内存以后,才能继续执行findViewById(); 才能得到引用,不然得到空引用。空引用意味着,
    后面使用相应变量时就会发生访问的对象不存在的问题。当Activity重新setContentView()以后,那些之前
    绘制的控件,内存都被灭掉了。这也就是说,你需要先setcontentview,然后再将布局动态添加上去。不然
    就白费了。

    相关文章

      网友评论

        本文标题:布局阶段

        本文链接:https://www.haomeiwen.com/subject/wakaettx.html