How to get RelativeLayout working with merge and i

2019-01-10 01:12发布

I have been trying for a few days now to make my layouts more efficient by converting from using several levels of nested LinearLayouts to one RelativeLayout and have come across a few problems that I haven not been able to find a workaround for...

I have searched the Android beginners group and this site and have not been able to find anything that would help me solve the problem.

I read on one of the blogs that you can combine layouts with merge and include tags. So what I have is a main layout file with a RelativeLayout root element. Inside of that I have 5 include tags that reference 5 different xml layout files that each have a merge element for the root (all of my merge files are the same except for the ids in them).

I am running into two problems, which I will explain after posting a simplified version of my layout code:

Sample Main Layout File:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/translucent_gray" >

    <include 
        android:id="@+id/running_gallery_layout_id"
        layout="@layout/running_gallery_layout" />

    <include 
        android:id="@+id/recent_gallery_layout_id" 
        layout="@layout/recent_gallery_layout"
        android:layout_below="@id/running_gallery_layout_id" />

    <include
        android:id="@+id/service_gallery_layout_id"
        layout="@layout/service_gallery_layout"
        android:layout_below="@id/recent_gallery_layout_id" />

    <include
        android:id="@+id/process_gallery_layout_id"
        layout="@layout/process_gallery_layout"
        android:layout_below="@id/service_gallery_layout_id" />

</RelativeLayout>

Sample included merge file:

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView 
        style="@style/TitleText"
        android:id="@+id/service_gallery_title_text_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="left"
        android:text="@string/service_title" />

    <Gallery
        android:id="@+id/service_gallery_id"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:layout_below="@id/service_gallery_title_text_id" />

    <TextView 
        style="@style/SubTitleText"
        android:id="@+id/service_gallery_current_text_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/service_gallery_title_text_id"
        android:layout_above="@id/service_gallery_id" />
</merge>

I am running into two problems:

1) The android:layout_* attributes seem to be ignored when used in the include tag and all of the merged layouts are displayed on top of each other. According to this post (http://developer.android.com/resources/articles/layout-tricks-reuse.html) "any android:layout_* attribute can be used with the <include /> tag"

2) Since I couldn't get this working I decided to try adding an android:layout_below attribute to the first TextView item in each merge layout file, meaning that each merge file would be referencing an id from another merge layout file... For the most part this actually worked and my layout looks fine. However, I get an error on one of the android:layout_below attributes saying that it can't find the id I specified... I have double and triple checked the ids to make sure they were correct. The weirdest part is that I used the AutoFill feature to put the id in the attribute in the first place.

If anyone has any suggestions or workarounds I will be more than happy to try them out. Also, if anyone can think of a way for me to just have one merge xml layout file instead of 5 that would be greatly appreciated. I couldn't find a way to do that because I need to have access to each item in the merge layout files at runtime...

7条回答
叼着烟拽天下
2楼-- · 2019-01-10 01:19

The android:layout_* attributes seem to be ignored when used in the include tag and all of the merged layouts are displayed on top of each other.

My guess is that you cannot reference, from layout rules, android:id attributes that are defined on <include> elements, only ones that are on "real" widgets and containers.

Also, if anyone can think of a way for me to just have one merge xml layout file instead of 5 that would be greatly appreciated.

Simple: put them all in one file.

I couldn't find a way to do that because I need to have access to each item in the merge layout files at runtime

Whether you have one <include> element or 1,000, all of the contents should be accessible at runtime. One exception is if you have duplicated android:id attributes -- you would need to properly scope your findViewById() calls to get the right one, just like you have to when getting widgets from a ListView row.

If you can create a sample project that uses 2+ merge files where you can demonstrate that the contents are not accessible at runtime, let me know.

查看更多
戒情不戒烟
3楼-- · 2019-01-10 01:22

In my case, the layout which I was trying to include starts with <merge tag. When I changed it to a layout, say <RelativeLayout it worked. Below is the illustration.

WORKING

<RelativeLayout xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    tools:showIn="@layout/activity_home">

NOT WORKING

<merge xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    tools:showIn="@layout/activity_home">
查看更多
欢心
4楼-- · 2019-01-10 01:24

Man, this is old, but it seems to come up at the top of searches, so I'm going to comment.

I think the trick here is that the <merge> tag combined with the <include> tag essentially remove any sort of "parent" view group at that level. So then, who exactly are you asking to "layout_below" someone else? No one. There is no view at that level.

The <merge> tag takes the child views and pops them right into the parent of the <include> tag. You must therefore ask the children in the layout you're including to anchor themselves accordingly.

查看更多
兄弟一词,经得起流年.
5楼-- · 2019-01-10 01:32

For positioning to work on RelativeLayout you need to set the layout_* parameters in the include file, not in the main layout file. That way

main_layout.xml

<RelativeLayout
  android:id="@+id/header"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content">
   ....
</RelativeLayout>

<RelativeLayout 
  android:id="@+id/footer"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:layout_alignParentBottom="true">
    .....
</RelativeLayout>

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

content_layout.xml

<merge xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
    android:id="@+id/content"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_above="@id/footer"
    android:layout_below="@id/header" >

    ....
</RelativeLayout>
</merge>

This is obviously not what us developers want, but it's the only solution I've found to avoid duplicating xml

查看更多
走好不送
6楼-- · 2019-01-10 01:33

There is an issue with the include tag. Check: https://issuetracker.google.com/issues/36908001

To fix it, make sure you overwrite BOTH layout_width and layout_height when including, otherwise everything will be ignored.

查看更多
迷人小祖宗
7楼-- · 2019-01-10 01:34

I had the same problem and even defining layout_width and layout_height it didn't work. The problem was that the layout I was including had tags and after removing them, everything worked like a charm. I suppose that merge is not a layout tag and because of that, it cannot receive positioning and size parameters. Since everything you define in is transferred to the inner parent layout, the settings just were throw away.

TL:DR: Just remove the tags, move the xmlns definitions to a real layout viewholder and you should be good.

Before:

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

    <...ui.component.BorderCardView
        android:layout_width="112dp"
        android:layout_height="32dp"
        app:cardCornerRadius="4dp"
        app:cardUseCompatPadding="true">

        <ImageView
            android:layout_width="16dp"
            android:layout_height="16dp"
            android:src="@drawable/ic_logout"
            android:tint="@color/divider" />

    </...ui.component.BorderCardView>
</merge>

Working:

<...ui.component.BorderCardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="112dp"
    android:layout_height="32dp"
    app:cardCornerRadius="4dp"
    app:cardUseCompatPadding="true">

    <ImageView
        android:layout_width="16dp"
        android:layout_height="16dp"
        android:src="@drawable/ic_logout"
        android:tint="@color/divider" />

</...ui.component.BorderCardView>
查看更多
登录 后发表回答