天天看点

android 自定义Layout布局

1.Android提供的五种布局有时候不能满足我们的需求,于是我要根据项目的需要自定义布局Layout;

自定义布局的步骤:

1.写一个布局CustomLayout类继承于Viewgroup类。实现onLayout()方法;

2.把CustomLayout的包名放在一个fragmentview.xml文件中;

3.把fragmentview放到main.xml中

4.在MainActivity中setContentView(R.layout.main);

直接上图:

1.竖屏

android 自定义Layout布局

2.横屏:

android 自定义Layout布局

代码:1.自定义Layout类

public class CustomLayout extends ViewGroup {

    private static final int UNEVEN_GRID_PENALTY_MULTIPLIER = 10;

    private int mMaxChildWidth = 0;

    private int mMaxChildHeight = 0;

public CustomLayout(Context context) {

        super(context, null);

    }

    public CustomLayout(Context context, AttributeSet attrs) {

        super(context, attrs, 0);

    }

    public CustomLayout(Context context, AttributeSet attrs, int defStyle) {

        super(context, attrs, defStyle);

    }

    @Override

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        mMaxChildWidth = 0;

        mMaxChildHeight = 0;

        // Measure once to find the maximum child size.

        int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(

                MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST);

        int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(

                MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST);

        final int count = getChildCount();

        for (int i = 0; i < count; i++) {

            final View child = getChildAt(i);

            if (child.getVisibility() == GONE) {

                continue;

            }

            child.measure(childWidthMeasureSpec, childHeightMeasureSpec);

            mMaxChildWidth = Math.max(mMaxChildWidth, child.getMeasuredWidth());

            mMaxChildHeight = Math.max(mMaxChildHeight, child.getMeasuredHeight());

        }

        // Measure again for each child to be exactly the same size.

        childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(

                mMaxChildWidth, MeasureSpec.EXACTLY);

        childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(

                mMaxChildHeight, MeasureSpec.EXACTLY);

        for (int i = 0; i < count; i++) {

            final View child = getChildAt(i);

            if (child.getVisibility() == GONE) {

                continue;

            }

            child.measure(childWidthMeasureSpec, childHeightMeasureSpec);

        }

        setMeasuredDimension(

                resolveSize(mMaxChildWidth, widthMeasureSpec),

                resolveSize(mMaxChildHeight, heightMeasureSpec));

    }

    @Override

    protected void onLayout(boolean changed, int l, int t, int r, int b) {

        int width = r - l;

        int height = b - t;

        final int count = getChildCount();

        // Calculate the number of visible children.

        int visibleCount = 0;

        for (int i = 0; i < count; i++) {

            final View child = getChildAt(i);

            if (child.getVisibility() == GONE) {

                continue;

            }

            ++visibleCount;

        }

        if (visibleCount == 0) {

            return;

        }

        // Calculate what number of rows and columns will optimize for even horizontal and

        // vertical whitespace between items. Start with a 1 x N grid, then try 2 x N, and so on.

        int bestSpaceDifference = Integer.MAX_VALUE;

        int spaceDifference;

        // Horizontal and vertical space between items

        int hSpace = 0;

        int vSpace = 0;

        int cols = 1;

        int rows;

        while (true) {

            rows = (visibleCount - 1) / cols + 1;

            hSpace = ((width - mMaxChildWidth * cols) / (cols + 1));

            vSpace = ((height - mMaxChildHeight * rows) / (rows + 1));

            spaceDifference = Math.abs(vSpace - hSpace);

            if (rows * cols != visibleCount) {

                spaceDifference *= UNEVEN_GRID_PENALTY_MULTIPLIER;

            }

            if (spaceDifference < bestSpaceDifference) {

                // Found a better whitespace squareness/ratio

                bestSpaceDifference = spaceDifference;

                // If we found a better whitespace squareness and there's only 1 row, this is

                // the best we can do.

                if (rows == 1) {

                    break;

                }

            } else {

                // This is a worse whitespace ratio, use the previous value of cols and exit.

                --cols;

                rows = (visibleCount - 1) / cols + 1;

                hSpace = ((width - mMaxChildWidth * cols) / (cols + 1));

                vSpace = ((height - mMaxChildHeight * rows) / (rows + 1));

                break;

            }

            ++cols;

        }

        // Lay out children based on calculated best-fit number of rows and cols.

        // If we chose a layout that has negative horizontal or vertical space, force it to zero.

        hSpace = Math.max(0, hSpace);

        vSpace = Math.max(0, vSpace);

        // Re-use width/height variables to be child width/height.

        width = (width - hSpace * (cols + 1)) / cols;

        height = (height - vSpace * (rows + 1)) / rows;

        int left, top;

        int col, row;

        int visibleIndex = 0;

        for (int i = 0; i < count; i++) {

            final View child = getChildAt(i);

            if (child.getVisibility() == GONE) {

                continue;

            }

            row = visibleIndex / cols;

            col = visibleIndex % cols;

            left = hSpace * (col + 1) + width * col;

            top = vSpace * (row + 1) + height * row;

            child.layout(left, top,

                    (hSpace == 0 && col == cols - 1) ? r : (left + width),

                    (vSpace == 0 && row == rows - 1) ? b : (top + height));

            ++visibleIndex;

        }

    }

}

2.xml中的引用fragment_layout.xml

<com.androidhive.dashboard.CustomLayout

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

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    android:layout_weight="1"

    android:background="#8B8B7A" >

    <!--  News Feed Button -->

    <Button

        android:id="@+id/btn_news_feed"

        style="@style/DashboardButton"

        android:drawableTop="@drawable/btn_newsfeed"

        android:text="News Feed" />

    <!--  Friends Button -->

    <Button

        android:id="@+id/btn_friends"

        style="@style/DashboardButton"

        android:drawableTop="@drawable/btn_friends"

        android:text="Friends" />

    <!--  Messages Button -->

    <Button

        android:id="@+id/btn_messages"

        style="@style/DashboardButton"

        android:drawableTop="@drawable/btn_messages"

        android:text="Messages" />

    <!--  Places Button -->

    <Button

        android:id="@+id/btn_places"

        style="@style/DashboardButton"

        android:drawableTop="@drawable/btn_places"

        android:text="Places" />

    <!--  Events Button -->

    <Button

        android:id="@+id/btn_events"

        style="@style/DashboardButton"

        android:drawableTop="@drawable/btn_events"

        android:text="Events" />

    <!--  Photos Button -->

    <Button

        android:id="@+id/btn_photos"

        style="@style/DashboardButton"

        android:drawableTop="@drawable/btn_photos"

        android:text="Photos" />

</com.androidhive.dashboard.CustomLayout>

3.添加到MAIN.XML

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:id="@+id/home_root"

    android:orientation="vertical"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent">

        <!--  Include Fragmented dashboard -->   

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

</LinearLayout>

4.在MainActivity中加载

public class MainActivity extends Activity {

 @Override

   public void onCreate(Bundle savedInstanceState) {

       super.onCreate(savedInstanceState);

       setContentView(R.layout.dashboard_layout);

   }

}