Android View 体系(2):Android UI布局常见问题

作者:陆金龙    发表时间:2018-03-03 16:56   


2 Android UI布局常见问题

2.0 Android中常用的五种布局:

   FrameLayout(帧布局),LinearLayout (线性布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局),TableLayout(表格布局),每种布局都有自己适合的方式,另外,这五个布局元素可以相互嵌套应用,做出美观的界面。

     FrameLayout

     从屏幕的左上角开始布局,叠加显示,应用:透明的多层布局。   

     LinearLayout

       从外框上可以理解为一个div,他首先是一个一个从上往下罗列在屏幕上。

        每一个LinearLayout里面又可分为垂直布局(android:orientation="vertical")和水平布局(android:orientation="horizontal")。

       当垂直布局时,每一行就只有一个元素,多个元素依次垂直往下;水平布局时,只有一行,每一个元素依次向右排列。

    AbsoluteLayout

      绝对布局犹如div指定了absolute属性,用X,Y坐标来指定元素的位置android:layout_x="20px" android:layout_y="12px"

      指定平板机型的游戏开发中经常用到绝对布局  widget 绝对布局,指定机型的平板游戏开发,机顶盒开发。    

    RelativeLayout

     内部元素以某一个元素为参照物,来定位的布局方式。主要属性有:

     android:layout_below="@id/aaa" 该元素在 id为aaa的下面

     android:layout_toLeftOf="@id/bbb" 改元素的左边是bbb

        相对于父元素的地方

    android:layout_alignParentLeft="true"  在父元素左对齐

    android:layout_alignParentRight="true"在父元素右对齐

   TableLayout

    表格布局类似Html里面的Table。每一个TableLayout里面有表格行TableRow,

    TableRow里面可以具体定义每一个元素,设定他的对齐  方式android:gravity="" 。

2.1 自定义文字居中的标题栏

1. 自定义control_titlebar.xml

control_titlebar.xml的定义如下:

<!--android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" 使返回箭头图标颜色为白色-->

 <!--app:elevation="0dp" 去掉AppBarLayout阴影-->

<android.support.design.widget.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:app="http://schemas.android.com/apk/res-auto"

    android:layout_width="match_parent"

    android:layout_height="wrap_content"

app:elevation="0dp"

android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <!-- app:popupTheme="@style/ThemeOverlay.AppCompat.Light" 使返回箭头图标颜色为白色-->

    <android.support.v7.widget.Toolbar

        android:id="@+id/toolbar"

        android:layout_width="match_parent"

        android:layout_height="@dimen/toolbar_sm_height"

        android:gravity="center_horizontal"

        app:layout_scrollFlags="scroll|enterAlways"

        app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

        <!--单行 限制长度 超长省略显示-->

        <TextView

            android:id="@+id/tv_title"

            android:layout_width="160dp"

            android:layout_height="wrap_content"

            android:layout_gravity="center"

            android:layout_centerInParent="true"

            android:textAlignment="center"

            android:ellipsize="end"

            android:gravity="center"

            android:maxEms="20"

            android:maxLines="1"

            android:text="@string/app_name"

            android:textColor="@android:color/white"

            android:textSize="@dimen/textsize_lg" />

    </android.support.v7.widget.Toolbar>

</android.support.design.widget.AppBarLayout>

2. 在布局文件中使用

 <include layout="@layout/control_titlebar"></include>

3. 在AndroidManifest.xml中声明Activity时,使用NoActionBar主题

 <activity  android:name=".XXXActivity"          android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|"

            android:label="xxx"

            android:screenOrientation="portrait"

            android:theme="@style/AppTheme.NoActionBar" />

  <style name="AppTheme>  

<!--这里为自定义主题的相关项......-->

</style>

    <style name="AppTheme.NoActionBar" >

        <item name="windowActionBar">false</item>

        <item name="windowNoTitle">true</item>

    </style>

4. Activity中设置setSupportActionBar为自定义的toolbar

Toolbar toolbar = (Toolbar )findView(R.id.toolbar);

toolbar.setTitle("");

setSupportActionBar(toolbar);

//去除分割线和阴影,这里同布局中的app:elevation="0dp"

getSupportActionBar().setElevation(0);

//是否显示返回箭头: true 显示,false 不显示

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

 

如果显示返回箭头,为其添加设置事件监听代码:

@Override

    public boolean onOptionsItemSelected(MenuItem item)

    {

        if (item.getItemId() == android.R.id.home)

        {

// todo 退出前的其他处理

// 退出当前Activity

            finish();

            return true;

        }

        return super.onOptionsItemSelected(item);

    }

 

2.2 Activity通过主题设置样式

2.2.1 去除标题栏左侧空白

    <!--ToolBar去除左侧空白-->

    <style name="MyToolbar" parent="Widget.AppCompat.Toolbar">

        <item name="contentInsetStart">0dp</item><!--去除左侧空白-->

</style>

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">

  <item name="colorPrimary">@color/colorPrimary</item>

    <item name="colorPrimaryDark">@color/colorPrimary</item>

    <item name="colorAccent">@color/colorAccent</item>

 

    <item name="android:windowIsTranslucent">true</item>

    <item name="toolbarStyle">@style/MyToolbar</item>

    <item name="overlapAnchor">false</item>  <!--把该属性改为false即可使menu位置位于toolbar之下-->

</style>

2.2.2 设置菜单Menu与标题栏不重叠

如上述在AppTheme样式主题中设置<item name="overlapAnchor">false</item>

parent样式如果有Overflow,如"Widget.AppCompat.ActionBar.Overflow"> 去掉.Overflow

2.2.3 修改MenuItem背景颜色

如果使用类似于微信的黑色主题,主题颜色设为深色后,菜单可能还是白底黑字,希望改为黑底白字。如下在AppTheme中设置菜单样式actionOverflowMenuStyle

<resources>

    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">

        <item name="colorPrimary">@color/dark</item>

        <item name="colorPrimaryDark">@color/dark</item>

        <item name="colorAccent">@color/colorAccent</item>

        <item name="actionOverflowMenuStyle">@style/optionMenu</item>

    </style>

    <style name="optionMenu" parent="Widget.AppCompat.ActionBar.Overflow">

        <item name="android:popupBackground">@color/dark</item>

</style>

</resources>

 

另一种方式:

<android.support.v7.widget.Toolbar style="@style/MyTheme.ToolBar"
                                   app:popupTheme="@style/MyTheme.ToolBar.PopupMenu"
                                   android:id="@+id/toolbar"
                                   android:layout_marginBottom="0dp"
                                   app:navigationIcon="?attr/homeAsUpIndicator"
                                   app:layout_collapseMode="pin">

 

<style name="MyTheme.ToolBar.PopupMenu" parent="@style/ThemeOverlay.AppCompat.Light">
    <!-- 是否覆盖锚点,默认为true,即盖住Toolbar -->
    <item name="overlapAnchor">false</item>
    <item name="android:dropDownWidth">wrap_content</item>
    <item name="android:paddingRight">5dp</item>
    <!-- 弹出层背景颜色 -->
   <item name="android:popupBackground">@color/white</item>

 

    <!-- 设置弹出菜单文字颜色 -->
    <item name="android:textColor">@color/black</item>

        <!-- 弹出层垂直方向上的偏移,即在竖直方向上距离Toolbar的距离,值为负则会盖住Toolbar -->
       <item name="android:dropDownVerticalOffset">1dp</item>
      <!-- 弹出层水平方向上的偏移,即距离屏幕左边的距离,负值会导致右边出现空隙 -->

</style>

 

2.3 Activity代码设置相关样式

2.3.1 设置状态栏、底部导航栏的颜色

/**

 * 设置状态栏、底部导航栏的颜色

 * @param window

 * @param color

 */

 public static void setTitleBarColor(Window window, int color) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

        window.setStatusBarColor(color);

        window.setNavigationBarColor(color);

    }

   else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)

   {

//与标题栏颜色同

      window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);           window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);

   }

   else {

       //android 4.2以下

    }

 }

 

在Activity的Oncreate中,在setContentView()被调用之后调用:

setTitleBarColor(getWindow(), ContextCompat.getColor(this, R.color.colorPrimary));

 

上述方法有一个bug,状态栏被设置成白色后文字图标不显示的问题,解决方法:

在app的build.gradle中dependencies添加依赖项

compile 'com.githang:status-bar-compat:latest.integration'

 

在Activity的Oncreate中,在setContentView()被调用之后调用:

setTitleBarColor(getWindow(), Color.WHITE);

StatusBarCompat.setStatusBarColor(this, Color.WHITE);

 

2.3.2 菜单操作

1. 使菜单资源

在res下的menu目录下定义菜单资源editmenu.xml

<menu 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">

    <item android:id="@+id/action_add"

          android:title="添加"

          android:orderInCategory="1"

          android:icon="@drawable/add"

          app:showAsAction="always"/>

 

    <item android:id="@+id/action_edit"

          android:title="编辑"

          android:orderInCategory="2"

          android:icon="@drawable/edit"

          app:showAsAction="always" />

</menu>

使用菜单资源填充菜单:

  @Override

  public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.editmenu, menu);

        super.onCreateOptionsMenu(menu);

        return true;

}

处理点击事件:

@Override

    public boolean onOptionsItemSelected(MenuItem item)

    {

        if (item.getItemId() == R.id.action_add){

// todo 处理添加业务

            return true;

        }else if(item.getItemId() == R.id.action_edit) {

// todo 处理编辑业务

            return true;

        }

        return super.onOptionsItemSelected(item);

    }

2. 下拉子菜单显示icon

  上述方式,在菜单显示为下拉菜单时,图标不显示。可以改用以下方式定义:

<menu 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">

<item  

           android:orderInCategory="100"  

           android:showAsAction="always"  

           android:title="更多">  

              <menu>  

             <item android:id="@+id/action_add"

                 android:title="添加"

                 android:orderInCategory="1"

                android:icon="@drawable/add"

                app:showAsAction="ifRoom|withText"/>

 

          <item android:id="@+id/action_edit"

                android:title="编辑"

                android:orderInCategory="2"

                android:icon="@drawable/edit"

                app:showAsAction="ifRoom|withText" />

</menu>

</item>

</menu>

 

3. 创建一个只显示文字的菜单

<item   android:title="下一步"  

    android:showAsAction="ifRoom|withText" />  

@Override

  public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.editmenu, menu);

        super.onCreateOptionsMenu(menu);

        return true;

}

 

或者

@Override

  public boolean onCreateOptionsMenu(Menu menu) {

       super.onCreateOptionsMenu(menu);

       MenuItem item=  menu.add(0,1,0,“下一步”);

       item.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM| | MenuItem.SHOW_AS_ACTION_WITH_TEXT);

       return true;

}

说明:

1.alaways:这个值会使菜单项一直显示在ActionBar上。

2.ifRoom:如果有足够的空间,这个值会使菜单显示在ActionBar上。

3.never:这个值菜单永远不会出现在ActionBar是。

4.withText:这个值使菜单和它的图标,菜单文本一起显示