Menu item on bottom of CollapsingToolbarLayout when expanded

前端 未结 3 599
醉酒成梦
醉酒成梦 2020-12-14 12:58

I\'ve been searching for a while as shown on the following images but unfortunately I was not able to find anything similar

edit menu item is moving to

3条回答
  •  旧时难觅i
    2020-12-14 13:44

    From the suggested project i will show you some modified approach to get your desired behaviour.

    Also i added my project in github also Check Here

    Demonstration

    1. Create top_view(which is visible in toolbar) & extended_view(which is visible in collapsing layout).
    2. Create custom class which is common to top_view & extended_view.
    3. Add Coordinatelayout behaviour to extended view.
    4. Update both views visibility,position & size based on AppBar onOffsetchangedListener.

    Both TopView & ExtendedView should be same view which is stayed at top & extended in collapsing.

    Here is the code

    header_view.xml(Extended View)

    
    
    
    
    
    
    
    
    
    
    

    header_view_top.xml(Top View)

    
    
    
    
    
    
    
    
    
    
    

    activity_main.xml

    
    
    
    
    
        
    
        
    
        
    
        
    
        
    
        
    
    
    
    
    
    
    
    
    
    
    
    
    
    

    HeaderView.Java(Custom class)

    import android.annotation.TargetApi;
    import android.content.Context;
    import android.os.Build;
    import android.util.AttributeSet;
    import android.util.TypedValue;
    import android.widget.RelativeLayout;
    import android.widget.TextView;
    import butterknife.BindView;
    import butterknife.ButterKnife;
    
    public class HeaderView extends RelativeLayout {
    
    @BindView(R.id.name)
    TextView tvName;
    
    @BindView(R.id.description)
    TextView tvDescription;
    
    public HeaderView(Context context) {
        super(context);
    }
    
    public HeaderView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    
    public HeaderView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public HeaderView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }
    
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        ButterKnife.bind(this);
    }
    
    public void bindTo(String name, String lastSeen) {
        this.tvName.setText(name);
        this.tvDescription.setText(lastSeen);
    }
    
    public void setTextSize(float size) {
        tvName.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
    }
    
    }
    

    Header_behaviour.java

    public class HeaderBehaviour extends CoordinatorLayout.Behavior {
    
    private Context mContext;
    
    private int mStartMarginLeft;
    private int mEndMarginLeft;
    private int mMarginRight;
    private int mStartMarginBottom;
    private float mTitleStartSize;
    private float mTitleEndSize;
    private boolean isHide;
    
    public HeaderBehaviour(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
    }
    
    public HeaderBehaviour(Context context, AttributeSet attrs, Context mContext) {
        super(context, attrs);
        this.mContext = mContext;
    }
    
    public static int getToolbarHeight(Context context) {
        int result = 0;
        TypedValue tv = new TypedValue();
        if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
            result = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics());
        }
        return result;
    }
    
    @Override
    public boolean layoutDependsOn(@NonNull CoordinatorLayout parent, @NonNull HeaderView child, @NonNull View dependency) {
        return dependency instanceof AppBarLayout;
    }
    
    @Override
    public boolean onDependentViewChanged(@NonNull CoordinatorLayout parent, @NonNull HeaderView child, @NonNull View dependency) {
        shouldInitProperties();
    
        int maxScroll = ((AppBarLayout) dependency).getTotalScrollRange();
        float percentage = Math.abs(dependency.getY()) / (float) maxScroll;
        float childPosition = dependency.getHeight()
                + dependency.getY()
                - child.getHeight()
                - (getToolbarHeight(mContext) - child.getHeight()) * percentage / 2;
    
        childPosition = childPosition - mStartMarginBottom * (1f - percentage);
    
        CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) child.getLayoutParams();
        if (Math.abs(dependency.getY()) >= maxScroll / 2) {
            float layoutPercentage = (Math.abs(dependency.getY()) - (maxScroll / 2)) / Math.abs(maxScroll / 2);
            lp.leftMargin = (int) (layoutPercentage * mEndMarginLeft) + mStartMarginLeft;
            lp.rightMargin = (int) (layoutPercentage * mEndMarginLeft) + mStartMarginLeft;
            child.setTextSize(getTranslationOffset(mTitleStartSize, mTitleEndSize, layoutPercentage));
        } else {
            lp.leftMargin = mStartMarginLeft;
            lp.rightMargin = mStartMarginLeft;
        }
    
        child.setLayoutParams(lp);
        child.setY(childPosition);
    
        if (isHide && percentage < 1) {
            child.setVisibility(View.VISIBLE);
            isHide = false;
        } else if (!isHide && percentage == 1) {
            child.setVisibility(View.GONE);
            isHide = true;
        }
        return true;
    }
    
    private float getTranslationOffset(float expandedOffset, float collapsedOffset, float ratio) {
        return expandedOffset + ratio * (collapsedOffset - expandedOffset);
    }
    
    private void shouldInitProperties() {
        if (mStartMarginLeft == 0) {
            mStartMarginLeft = mContext.getResources().getDimensionPixelOffset(R.dimen.header_view_start_margin_left);
        }
    
        if (mEndMarginLeft == 0) {
            mEndMarginLeft = mContext.getResources().getDimensionPixelOffset(R.dimen.header_view_end_margin_left);
        }
    
        if (mStartMarginBottom == 0) {
            mStartMarginBottom = mContext.getResources().getDimensionPixelOffset(R.dimen.header_view_start_margin_bottom);
        }
    
        if (mMarginRight == 0) {
            mMarginRight = mContext.getResources().getDimensionPixelOffset(R.dimen.header_view_end_margin_right);
        }
    
        if (mTitleStartSize == 0) {
            mTitleEndSize = mContext.getResources().getDimensionPixelSize(R.dimen.header_view_end_text_size);
        }
    
        if (mTitleStartSize == 0) {
            mTitleStartSize = mContext.getResources().getDimensionPixelSize(R.dimen.header_view_start_text_size);
        }
    }
    
    
    }
    

    Mainactivity.java

    public class MainActivity extends AppCompatActivity implements AppBarLayout.OnOffsetChangedListener{
    
    @BindView(R.id.toolbar_header_view)
    protected HeaderView toolbarHeaderView;
    
    @BindView(R.id.float_header_view)
    protected HeaderView floatHeaderView;
    
    @BindView(R.id.appbar)
    protected AppBarLayout appBarLayout;
    
    @BindView(R.id.toolbar)
    protected Toolbar toolbar;
    
    @BindView(R.id.collapsing_toolbar)
    protected CollapsingToolbarLayout collapsingToolbarLayout;
    
    private boolean isHideToolbarView = false;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
    
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setDisplayShowTitleEnabled(false);
    
        initUi();
    
        /*Remove no need to change custom scrim colour */
        Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.photo);
        int color = getDominantColor(icon);
        collapsingToolbarLayout.setContentScrimColor(color);
        collapsingToolbarLayout.setStatusBarScrimColor(color);
        if (Build.VERSION.SDK_INT >= 21) {
            getWindow().setStatusBarColor(darker(color,0.8f));
        }
        /*Remove no need to change custom scrim colour*/
    
    
    }
    
    public static int darker (int color, float factor) {
        int a = Color.alpha( color );
        int r = Color.red( color );
        int g = Color.green( color );
        int b = Color.blue( color );
    
        return Color.argb( a,
                Math.max( (int)(r * factor), 0 ),
                Math.max( (int)(g * factor), 0 ),
                Math.max( (int)(b * factor), 0 ) );
    }
    
    public static int getDominantColor(Bitmap bitmap) {
        Bitmap newBitmap = Bitmap.createScaledBitmap(bitmap, 1, 1, true);
        final int color = newBitmap.getPixel(0, 0);
        newBitmap.recycle();
        return color;
    }
    
    private void initUi() {
        appBarLayout.addOnOffsetChangedListener(this);
    
        toolbarHeaderView.bindTo("Group Name", "Created by Developer");
        floatHeaderView.bindTo("Group Name", "Created by Developer");
    }
    
    @Override
    public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
    
        int maxScroll = appBarLayout.getTotalScrollRange();
        float percentage = (float) Math.abs(verticalOffset) / (float) maxScroll;
    
        if (percentage == 1f && isHideToolbarView) {
            toolbarHeaderView.setVisibility(View.VISIBLE);
            isHideToolbarView = !isHideToolbarView;
    
        } else if (percentage < 1f && !isHideToolbarView) {
            toolbarHeaderView.setVisibility(View.GONE);
            isHideToolbarView = !isHideToolbarView;
        }
    
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
    
        //noinspection SimplifiableIfStatement
        if (id == R.id.action_person_add) {
            return true;
        }
    
        return super.onOptionsItemSelected(item);
    }
    

    }

    OUTPUT

    Hope this will help you.!

提交回复
热议问题