简体   繁体   中英

make same fab Transformation exapnd behavior like shown at material.io

I wanna have same fab transformation behavior as shown in Material Website in Full Screen (or morph) section.

I have tried default FabTransformationScrimBehavior and FabTransformationSheetBehavior . but scrim behavior doesn't do anything and sheet behavior don't animate just like I wanted and also it reduce the elevation of the fab to value 0f . and I haven't found any way to unexpand fab. and I wanna know how to use fab transformation behavior. Actually I didn't find any doc on how to use it. So Please help

Code

This is the code that I used:

this is the code of first activity:-

final FloatingActionButton actionButton = findViewById(R.id.add_fab);
actionButton.setOnClickListener(view -> {
            actionButton.setExpanded(!actionButton.isExpanded());
        });

And this is the xml of first activity:-

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

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

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/list_rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        android:paddingBottom="76dp"    
 app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
    tools:listitem="@layout/media_list_item_card" />

<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:id="@+id/add_fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|end"
    android:layout_margin="16dp"
    android:includeFontPadding="false"
    android:text="Add Media"
    android:textAllCaps="false"
    android:visibility="visible"
    app:srcCompat="@drawable/ic_add_24"/>

<com.google.android.material.circularreveal.CircularRevealFrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:visibility="invisible"
    app:layout_behavior="com.google.android.material.transformation.FabTransformationSheetBehavior"
    >
    <fragment
        android:id="@+id/fab_transformation"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.zimong.ssms.fragments.AddMediaFragment"
        />
</com.google.android.material.circularreveal.CircularRevealFrameLayout>

And the code of AddMediaFragment(second screen):- package com.zimong.ssms.fragments;

import android.app.DatePickerDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.DialogFragment;

import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.zimong.ssms.R;
import com.zimong.ssms.common.model.User;
import com.zimong.ssms.extended.CallbackHandlerImpl;
import com.zimong.ssms.model.Source;
import com.zimong.ssms.model.ZResponse;
import com.zimong.ssms.service.AppService;
import com.zimong.ssms.service.ServiceLoader;
import com.zimong.ssms.util.Constants;
import com.zimong.ssms.util.Util;

import java.util.Calendar;
import java.util.Date;

import retrofit2.Call;
import retrofit2.Response;

public class AddMediaFragment extends DialogFragment {

    private ArrayAdapter<Source> adapter;
    private TextView source;
    private int checkedItem = 0;
    private TextView mediaDate;
    private Date currentSelectedDate;


    public static AddMediaFragment newInstance() {
        AddMediaFragment fragment = new AddMediaFragment();
        Bundle bundle = new Bundle();
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setStyle(DialogFragment.STYLE_NO_FRAME, R.style.AppTheme_Light);
        setHasOptionsMenu(true);
    }

    private void getSources() {
        final User user = Util.getUser(getActivity());
        AppService service = ServiceLoader.createService(AppService.class);
        Call<ZResponse> call = service.mediaGallerySources(Constants.DEFAULT_PLATFORM, user.getToken());
        call.enqueue(new CallbackHandlerImpl<Source[]>(getActivity(), true, true, Source[].class) {
            @Override
            protected void failure(Throwable t) {

            }

            @Override
            protected void failure(Response<ZResponse> response) {

            }

            @Override
            protected void success(Source[] response) {
                if (response.length > 0) {
                    source.setText(response[0].getName());
                }
                adapter = new ArrayAdapter<Source>(getContext(), R.layout.dialog_singlechoice_item, response) {
                    @Override
                    public long getItemId(int position) {
                        return getItem(position).getPk();
                    }
                };


            }

        });
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.activity_add_media, container, false);
        TextView headline = view.findViewById(R.id.media_headline);
        Toolbar toolbar = view.findViewById(R.id.toolbar);
        ((AppCompatActivity) getContext()).setSupportActionBar(toolbar);
        source = view.findViewById(R.id.source);
        mediaDate = view.findViewById(R.id.media_date);
        Calendar fromDateInstance = Calendar.getInstance();
        currentSelectedDate = fromDateInstance.getTime();
        mediaDate.setText(Util.formatDate(fromDateInstance.getTime(), "dd MMM yyyy"));
        final DatePickerDialog fromDatePicker = new DatePickerDialog(getContext(), (datePicker, year, month, date) -> {
            fromDateInstance.set(Calendar.YEAR, year);
            fromDateInstance.set(Calendar.MONTH, month);
            fromDateInstance.set(Calendar.DATE, date);
            currentSelectedDate = fromDateInstance.getTime();
            mediaDate.setText(Util.formatDate(currentSelectedDate, "dd MMM yyyy"));
        }, fromDateInstance.get(Calendar.YEAR), fromDateInstance.get(Calendar.MONTH), fromDateInstance.get(Calendar.DATE));
        mediaDate.setOnClickListener(v -> fromDatePicker.show());
        source.setOnClickListener(v -> alertDialog());
        getSources();
        return view;
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                getActivity().onBackPressed();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void alertDialog() {
        MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getContext());
        builder.setTitle("Source");
        builder.setSingleChoiceItems(adapter, checkedItem, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                source.setText(adapter.getItem(which).getName());
                checkedItem = which;
                dialog.dismiss();
            }
        });
        builder.show();
    }
}

And the xml of Add Media is:-

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.circularreveal.coordinatorlayout.CircularRevealCoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/myCoordinatorLayout"
    android:layout_width="match_parent"
    android:background="@color/white"
    android:layout_height="match_parent"

    android:orientation="vertical">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_behavior="com.google.android.material.appbar.AppBarLayout$Behavior"
        android:theme="@style/AppTheme.AppBarOverlay">

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

    </com.google.android.material.appbar.AppBarLayout>


    <include
        layout="@layout/content_add_media"
        android:layout_width="match_parent"
        app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
        android:layout_height="match_parent"/>

</com.google.android.material.circularreveal.coordinatorlayout.CircularRevealCoordinatorLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
        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"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

    <com.google.android.material.circularreveal.CircularRevealLinearLayout
            android:id="@+id/dial"
            android:layout_height="match_parent"
            android:layout_width="match_parent"
            android:orientation="horizontal"
            android:layout_gravity="bottom|center_horizontal"
            android:visibility="invisible"
            android:layout_marginBottom="16dp"
            app:layout_anchor="@id/fab"
            app:layout_anchorGravity="top|center_horizontal"
            android:background="@color/colorPrimary"
            app:layout_behavior="com.google.android.material.transformation.FabTransformationSheetBehavior">

        <ImageButton
                android:id="@+id/back" 
                android:layout_width="wrap_content" 
                android:layout_height="wrap_content"
                android:src="@drawable/back"/>

    </com.google.android.material.circularreveal.CircularRevealLinearLayout>


    <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="@dimen/fab_margin"
            android:backgroundTint="@color/colorPrimary"
            app:srcCompat="@android:drawable/ic_dialog_email"/>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

For the FabTransformationSheetBehavior to work, you need to change the isExpanded value. on change of this value, expand and collapse animation will be called and visibility of the linearlayout and fab button will be handled automatically. Don't change visibility manually as this would block transformation animation.

Use back button to transform back to FAB.

val fab: FloatingActionButton = findViewById<FloatingActionButton>(R.id.fab)        
fab.setOnClickListener {  fab.isExpanded = !fab.isExpanded } // this sets isExpanded as true

val back = findViewById<ImageButton>(R.id.back)   
back.setOnClickListener{  fab.isExpanded = !fab.isExpanded } // this sets isExpanded as false

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