当前位置: 移动技术网 > IT编程>移动开发>Android > Android 百分比布局详解及实例代码

Android 百分比布局详解及实例代码

2019年07月24日  | 移动技术网IT编程  | 我要评论

2980邮箱,美术字,高端奶粉品牌

android 百分比布局

1.引入:compile 'com.android.support:percent:24.0.0'

2.点开源码可以看到,主要有两个布局类percentframelayout和percentrelativelayout,一个工具类percentlayouthelper。

3.点开布局类比如percentrelativelayout的源码,可以看到实现的很简单。

public class percentrelativelayout extends relativelayout {
  private final percentlayouthelper mhelper = new percentlayouthelper(this);

  /**省略若干行构造方法之类的代码**/

  @override
  protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {

    //重点在这

    mhelper.adjustchildren(widthmeasurespec, heightmeasurespec);
    super.onmeasure(widthmeasurespec, heightmeasurespec);
    if (mhelper.handlemeasuredstatetoosmall()) {
      super.onmeasure(widthmeasurespec, heightmeasurespec);
    }
  }

  @override
  protected void onlayout(boolean changed, int left, int top, int right, int bottom) {
    super.onlayout(changed, left, top, right, bottom);
    mhelper.restoreoriginalparams();
  }

  public static class layoutparams extends relativelayout.layoutparams
      implements percentlayouthelper.percentlayoutparams {
    private percentlayouthelper.percentlayoutinfo mpercentlayoutinfo;

    public layoutparams(context c, attributeset attrs) {
      super(c, attrs);
      mpercentlayoutinfo = percentlayouthelper.getpercentlayoutinfo(c, attrs);
    }

     /**省略若干行构造方法之类的代码**/

    @override
    public percentlayouthelper.percentlayoutinfo getpercentlayoutinfo() {
      if (mpercentlayoutinfo == null) {
        mpercentlayoutinfo = new percentlayouthelper.percentlayoutinfo();
      }

      return mpercentlayoutinfo;
    }

    @override
    protected void setbaseattributes(typedarray a, int widthattr, int heightattr) {
      percentlayouthelper.fetchwidthandheight(this, a, widthattr, heightattr);
    }
  }
}

就是在onmeasure和onlayout里面调用了percentlayouthelper 的一些方法,另外在里面定义了自己的layoutparams ,而这个layoutparams 也相当简单。

这里关键的一行代码是在onmeasure方法里面,mhelper.adjustchildren(widthmeasurespec, heightmeasurespec);通过percentlayouthelper 的adjustchildren 遍历子view来设置 子view的宽高,宽高在percentlayouthelper 的内部类percentlayoutinfo通过在布局文件中设置的值计算好了。

public void adjustchildren(int widthmeasurespec, int heightmeasurespec) {

    // calculate available space, accounting for host's paddings
    int widthhint = view.measurespec.getsize(widthmeasurespec) - mhost.getpaddingleft()
        - mhost.getpaddingright();
    int heighthint = view.measurespec.getsize(heightmeasurespec) - mhost.getpaddingtop()
        - mhost.getpaddingbottom();
    for (int i = 0, n = mhost.getchildcount(); i < n; i++) {

      //遍历子view来设置 子view的宽高

      view view = mhost.getchildat(i);
      viewgroup.layoutparams params = view.getlayoutparams();
      if (debug) {
        log.d(tag, "should adjust " + view + " " + params);
      }
      if (params instanceof percentlayoutparams) {
        percentlayoutinfo info =
            ((percentlayoutparams) params).getpercentlayoutinfo();

        if (info != null) {
          if (params instanceof viewgroup.marginlayoutparams) {
            info.fillmarginlayoutparams(view, (viewgroup.marginlayoutparams) params,
                widthhint, heighthint);
          } else {
            info.filllayoutparams(params, widthhint, heighthint);
          }
        }
      }
    }
  }

4.布局中的使用方法:以percentrelativelayout为例

<android.support.percent.percentrelativelayout 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="match_parent"
  android:background="@color/background_color"
  >

  <textview
    android:id="@+id/mian_tab_name"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:textcolor="@color/back_green"
    android:textsize="15sp"
    android:text="name"
    />

  <imageview
    app:layout_widthpercent="50%"
    app:layout_heightpercent="50%"
    android:src="@drawable/ic_launcher_icon"
    android:scaletype="fitxy"
    android:layout_below="@+id/mian_tab_name"
    android:background="@color/black"
    />

</android.support.percent.percentrelativelayout>

引入xmlns:app的命名空间,然后app:layout_widthpercent="50%"就可以设置宽高的百分比了。相当简单 。

5.不过在使用的过程中,可能会有一些其他的需求,比如app:layout_widthpercent="50%",app:layout_heightpercent="50%"都是相对于屏幕的宽高的,假如要显示一张正方形的图片,以宽的50%为准呢?这个时候就可以这样写了:

<imageview
    app:layout_widthpercent="50%"
    app:layout_aspectratio="100%"
    android:src="@drawable/ic_launcher_icon"
    android:scaletype="fitxy"
    android:layout_below="@+id/mian_tab_name"
    android:background="@color/cs_black"
    />

使用layout_aspectratio属性,设置app:layout_aspectratio="100%",layout_aspectratio就是宽高比。这个时候就不要设置app:layout_heightpercent属性了。在percentlayouthelper 里面, 源代码如下:

public void filllayoutparams(viewgroup.layoutparams params, int widthhint,
        int heighthint) {
      // preserve the original layout params, so we can restore them after the measure step.
      mpreservedparams.width = params.width;
      mpreservedparams.height = params.height;

      // we assume that width/height set to 0 means that value was unset. this might not
      // necessarily be true, as the user might explicitly set it to 0. however, we use this
      // information only for the aspect ratio. if the user set the aspect ratio attribute,
      // it means they accept or soon discover that it will be disregarded.
      final boolean widthnotset =
          (mpreservedparams.miswidthcomputedfromaspectratio
              || mpreservedparams.width == 0) && (widthpercent < 0);
      final boolean heightnotset =
          (mpreservedparams.misheightcomputedfromaspectratio
              || mpreservedparams.height == 0) && (heightpercent < 0);

      if (widthpercent >= 0) {
        params.width = (int) (widthhint * widthpercent);
      }

      if (heightpercent >= 0) {
        params.height = (int) (heighthint * heightpercent);
      }

      //这一段代码是关键,如果aspectratio >=0,aspectratio是宽高比

      if (aspectratio >= 0) {
        if (widthnotset) {

           //如果宽没有设置,就以高为准

          params.width = (int) (params.height * aspectratio);
          // keep track that we've filled the width based on the height and aspect ratio.
          mpreservedparams.miswidthcomputedfromaspectratio = true;
        }
        if (heightnotset) {

          //如果高没有设置,就以宽为准

          params.height = (int) (params.width / aspectratio);
          // keep track that we've filled the height based on the width and aspect ratio.
          mpreservedparams.misheightcomputedfromaspectratio = true;
        }
      }

      if (debug) {
        log.d(tag, "after filllayoutparams: (" + params.width + ", " + params.height + ")");
      }
    }

6.另外,假如我们要定义自己的percentlinearlayout,基本可以直接改一下名字,继承自linearlayout就好了:public class percentlinearlayout extends linearlayout ,在仿照percentrelativelayout里面的layoutparams定义一个自己的layoutparams就好了。

不过官方为什么没有直接提供一个percentlinearlayout 类,而只提供了两个percentframelayout和percentrelativelayout呢?或许是由于linearlayout 本身就有权重属性,自带百分比效果了。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网