简体   繁体   中英

Positioning of FAB button in Material design

I've grabbed Google IO app source code and check how they perfectly place the FAB button in the middle of two views (as in the attached screenshot). It's strange that there's no vertical positioning params of the button, there are just height , width , as in the two layout files, scroll to the very bottom of the layout file to see the include part of FAB.

Am I missing anything? Thanks.

<com.google.samples.apps.iosched.ui.widget.ObservableScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:iosched="http://schemas.android.com/apk/res-auto"
    xmlns:plus="http://schemas.android.com/apk/lib/com.google.android.gms.plus"
    android:id="@+id/scroll_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:overScrollMode="never"
    android:fillViewport="true"
    android:background="#fff">

    <FrameLayout
        android:id="@+id/scroll_view_child"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clipChildren="false">

        <!-- Background photo -->
        <FrameLayout android:id="@+id/session_photo_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <ImageView
                android:id="@+id/session_photo"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop" />
        </FrameLayout>

        <LinearLayout android:id="@+id/details_container"
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#fff"
            android:paddingTop="16dp"
            android:paddingRight="@dimen/keyline_1"
            android:paddingBottom="@dimen/session_details_extra_space_bottom"
            android:clipToPadding="false">

            <com.google.samples.apps.iosched.ui.widget.MessageCardView
                android:id="@+id/live_now_card"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                iosched:messageText="@string/session_live_now_message"
                iosched:button1text="@string/no_thanks"
                iosched:button2text="@string/watch_now"
                iosched:button2tag="WATCH_NOW"
                iosched:button2emphasis="true"
                iosched:emphasisColor="@color/theme_accent_2"
                iosched:cardBackgroundColor="#fff"
                android:layout_marginLeft="@dimen/keyline_2_session_detail"
                android:layout_marginBottom="16dp"
                android:visibility="gone"
                />

            <com.google.samples.apps.iosched.ui.widget.MessageCardView
                android:id="@+id/give_feedback_card"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                iosched:messageText="@string/session_give_feedback_message"
                iosched:button1text="@string/no_thanks"
                iosched:button2text="@string/give_feedback"
                iosched:button2tag="GIVE_FEEDBACK"
                iosched:button2emphasis="true"
                iosched:cardBackgroundColor="#fff"
                android:layout_marginLeft="@dimen/keyline_2_session_detail"
                android:layout_marginBottom="16dp"
                android:visibility="gone"
                />

            <TextView android:id="@+id/time_hint"
                android:visibility="gone"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/keyline_2_session_detail"
                android:layout_marginBottom="8dp"
                style="@style/SessionTimeHint" />

            <TextView android:id="@+id/session_abstract"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/keyline_2_session_detail"
                android:layout_marginBottom="16dp"
                style="@style/TextBody"
                />

                <com.google.android.gms.plus.PlusOneButton
                    android:id="@+id/plus_one_button"
                    style="@style/SessionDetailPlusOne"
                    android:clickable="true"
                    android:focusable="true"
                    plus:annotation="inline"
                    plus:size="standard"
                    android:layout_marginLeft="@dimen/keyline_2_session_detail"
                    android:layout_marginBottom="16dp"
                    android:layout_marginRight="16dp"
                    />

            <HorizontalScrollView android:id="@+id/session_tags_container"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/keyline_2_session_detail"
                android:scrollbars="none"
                android:requiresFadingEdge="horizontal"
                android:fadingEdgeLength="16dp"
                android:layout_marginBottom="16dp">

                <LinearLayout android:id="@+id/session_tags"
                    android:orientation="horizontal"
                    android:layout_width="wrap_content"
                    android:layout_height="32dp" />
            </HorizontalScrollView>

            <LinearLayout android:id="@+id/session_speakers_block"
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/element_spacing_normal">

                    <TextView android:layout_width="match_parent"
                        android:id="@+id/session_speakers_header"
                        android:clickable="true"
                        android:focusable="true"
                        android:layout_height="wrap_content"
                        android:text="@string/session_speakers"
                        android:layout_marginLeft="@dimen/keyline_2_session_detail"
                        style="@style/SessionDetailSectionHeader" />
                </LinearLayout>

            <LinearLayout android:id="@+id/session_requirements_block"
                android:orientation="vertical"
                android:layout_marginLeft="@dimen/keyline_2_session_detail"
                android:layout_marginTop="@dimen/element_spacing_normal"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:visibility="gone">

                <TextView android:layout_width="match_parent"
                    android:id="@+id/session_requirements_header"
                    android:layout_height="wrap_content"
                    android:text="@string/session_requirements"
                    style="@style/SessionDetailSectionHeader" />

                <TextView android:id="@+id/session_requirements"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/element_spacing_normal"
                    android:layout_marginBottom="@dimen/element_spacing_normal"
                    style="@style/TextBody" />
            </LinearLayout>

            <LinearLayout android:id="@+id/related_videos_block"
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/element_spacing_normal"
                android:visibility="gone">

                <TextView android:layout_width="match_parent"
                    android:id="@+id/related_videos_header"
                    android:layout_height="wrap_content"
                    android:text="@string/related_videos"
                    android:layout_marginLeft="@dimen/keyline_2_session_detail"
                    style="@style/SessionDetailSectionHeader" />
            </LinearLayout>

                <TextView android:id="@+id/session_links_header"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:clickable="true"
                    android:focusable="true"
                    android:text="@string/session_links"
                    android:layout_marginLeft="@dimen/keyline_2_session_detail"
                    android:layout_marginTop="@dimen/element_spacing_normal"
                    style="@style/SessionDetailSectionHeader"
                    android:visibility="gone"/>

            <LinearLayout android:orientation="vertical"
                android:id="@+id/links_container"
                android:layout_marginLeft="@dimen/keyline_2_session_detail"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

            <TextView style="@style/EmptyText"
                android:id="@android:id/empty"
                android:layout_marginLeft="@dimen/keyline_2_session_detail"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:text="@string/empty_session_detail"
                android:gravity="center"
                android:visibility="gone" />


        </LinearLayout>

        <!-- Title/subtitle bar (floating; position determined at run time as the content view scrolls) -->
        <LinearLayout
            android:id="@+id/header_session"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:clipChildren="false"
            android:clipToPadding="false"
            android:orientation="vertical"
            android:paddingBottom="16dp">

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

            <!-- Session title -->
            <TextView android:layout_height="wrap_content"
                android:layout_width="match_parent"
                android:layout_marginBottom="0dp"
                android:layout_marginLeft="@dimen/keyline_2_session_detail"
                android:layout_marginRight="@dimen/keyline_1"
                android:text="@string/placeholder_session_title"
                android:id="@+id/session_title"
                android:maxLines="4"
                android:ellipsize="end"
                android:textSize="@dimen/text_size_large"
                android:lineSpacingMultiplier="1.1"
                android:textStyle="@integer/font_textStyle_medium"
                android:fontFamily="@string/font_fontFamily_medium"
                android:textColor="@color/body_text_1_inverse"
                android:textAlignment="viewStart" />

            <!-- Session subtitle -->
            <TextView android:layout_height="wrap_content"
                android:layout_width="match_parent"
                android:layout_marginLeft="@dimen/keyline_2_session_detail"
                android:layout_marginRight="@dimen/keyline_1"
                android:text="@string/placeholder_session_subtitle"
                android:id="@+id/session_subtitle"
                android:maxLines="2"
                android:ellipsize="end"
                android:textSize="16sp"
                android:textColor="@color/body_text_2_inverse"
                android:textAlignment="viewStart" />

        </LinearLayout>

        <!-- FAB -->
        <include layout="@layout/include_add_schedule_fab" />

    </FrameLayout>

</com.google.samples.apps.iosched.ui.widget.ObservableScrollView>

The FAB layout:

<com.google.samples.apps.iosched.ui.widget.AddToScheduleFABFrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/add_schedule_button"
    android:layout_width="@dimen/add_to_schedule_button_height_no_padding"
    android:layout_height="@dimen/add_to_schedule_button_height_no_padding"
    android:layout_marginLeft="@dimen/keyline_1"
    android:visibility="invisible"
    android:clickable="true"
    android:focusable="true"
    android:elevation="@dimen/fab_elevation"
    android:background="@drawable/add_schedule_fab_ripple_background_off"
    android:stateListAnimator="@anim/add_schedule_fab_state_list_anim"
    android:contentDescription="@string/add_to_schedule">

    <ImageView android:id="@+id/add_schedule_icon"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="center"
        android:src="@drawable/add_schedule_button_icon_unchecked"
        android:contentDescription="@null"
        android:layout_gravity="center" />

</com.google.samples.apps.iosched.ui.widget.AddToScheduleFABFrameLayout>

在此处输入图片说明

it does have margin left at include_add_schedule_fab

 <com.google.samples.apps.iosched.ui.widget.CheckableFrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/add_schedule_button"
     android:layout_width="@dimen/add_to_schedule_button_height"
     android:layout_height="@dimen/add_to_schedule_button_height"
     android:layout_marginLeft="@dimen/keyline_1_minus_8dp"
     android:visibility="invisible"
     android:clickable="true"
     android:focusable="true"
     android:background="@drawable/add_schedule_fab_background"
     android:contentDescription="@string/add_to_schedule">

      <ImageView android:id="@+id/add_schedule_icon"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:scaleType="center"
         android:src="@drawable/add_schedule_button_icon_unchecked"
         android:contentDescription="@null"
         android:layout_gravity="center" />
 </com.google.samples.apps.iosched.ui.widget.CheckableFrameLayout>

in the SessionDetailActivity you will get the height in the variable mAddScheduleButtonHeightPixels

 ViewTreeObserver vto = mScrollView.getViewTreeObserver();
 if (vto.isAlive()) {
      vto.addOnGlobalLayoutListener(mGlobalLayoutListener);
 }

 private ViewTreeObserver.OnGlobalLayoutListener mGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
      @Override
      public void onGlobalLayout() {
           mAddScheduleButtonHeightPixels = mAddScheduleButton.getHeight();
           recomputePhotoAndScrollingMetrics();
      }
 };

onScrollChanged will set the translation from its initial position

 @Override
 public void onScrollChanged(int deltaX, int deltaY) {
      // Reposition the header bar -- it's normally anchored to the top of the content,
      // but locks to the top of the screen on scroll
      int scrollY = mScrollView.getScrollY();

      float newTop = Math.max(mPhotoHeightPixels, scrollY);
      mHeaderBox.setTranslationY(newTop);
      mAddScheduleButton.setTranslationY(newTop + mHeaderHeightPixels - mAddScheduleButtonHeightPixels / 2);
      ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM