material design风格的收缩日历

先来看看日历的效果,请自行忽略我截屏时的淡绿色圆圈:


 







在手指上滑或者下滑后,日历将在月视图和周视图之间切换。 主要的原理就是利用margin值,让想隐藏的部分移动到父布局的上方。同时变换父布局的高度。

二话不说贴代码:

public class ZoomCalendarView extends RelativeLayout {

    float mPosX, mPosY, mCurPosX, mCurPosY;

    private int m_marginCountY = 0;
    private Context m_context;
    private PagerAdapter m_monthAdapter;
    private PagerAdapter m_weekAdapter;
    private ViewPager m_monthPager;
    private ViewPager m_weekPager;
    private LinearLayout m_calendarLayout;
    private LinearLayout m_weekLayout;
    private CardView m_calendarCard;
    private RelativeLayout m_cardTitle;
    private int m_orignalHeight = 0;
    private int m_orignalWeekHeight = 0;
    private int m_orignalTitleHeight = 0;
    // 最小滑动距离
    private int m_minMoveSize;
    private int m_minEffectiveSize;
    private int m_minOrignalHeight = 0;


    private boolean isChangeEffect = false;
    AppCompatButton m_yearButton;
    AppCompatButton m_monthButton;

    public ZoomCalendarView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    private void init(Context context) {
        m_context = context;
        LayoutInflater.from(m_context).inflate(R.layout.zoom_calendar_layout, this);
        m_monthPager = (ViewPager) findViewById(R.id.month_viewpager);
        m_weekPager = (ViewPager) findViewById(R.id.week_viewpager);
        m_monthAdapter = new MonthPagerAdapter(m_context);
        m_weekAdapter = new WeekPageAdapter(m_context);
        m_monthPager.setAdapter(m_monthAdapter);
        m_weekPager.setAdapter(m_weekAdapter);
        m_monthPager.setCurrentItem(ValueUtil.DEFAULT_MONTH_ITEM);
        m_weekPager.setCurrentItem(ValueUtil.DEFAULT_WEEK_ITEM);
        m_calendarLayout = (LinearLayout) findViewById(R.id.calendar_linearlayout);
        m_weekLayout = (LinearLayout) findViewById(R.id.weekday_linearlayout);
        m_minMoveSize = getResources().getDimensionPixelSize(R.dimen.min_move_size);
        m_minEffectiveSize = 3 * m_minMoveSize;
        m_calendarCard = (CardView) findViewById(R.id.calendar_card);
        m_cardTitle = (RelativeLayout) findViewById(R.id.calendar_card_title);
        m_yearButton = (AppCompatButton) findViewById(R.id.year_button);
        m_monthButton = (AppCompatButton) findViewById(R.id.month_button);
        setMonthYear(Calendar.getInstance());
        m_monthPager.setCurrentItem(ValueUtil.DEFAULT_MONTH_ITEM);
        m_monthPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.MONTH,position - ValueUtil.DEFAULT_MONTH_ITEM);
                setMonthYear(calendar);
            }

            @Override
            public void onPageSelected(int position) {

            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
        m_weekPager.setCurrentItem(ValueUtil.DEFAULT_WEEK_ITEM);
        m_weekPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.WEEK_OF_YEAR,position - ValueUtil.DEFAULT_WEEK_ITEM);
                setMonthYear(calendar);
            }

            @Override
            public void onPageSelected(int position) {

            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

    private void setMonthYear(Calendar calendar){
        m_yearButton.setText(String.valueOf(calendar.get(Calendar.YEAR)));
        m_monthButton.setText(String.valueOf(calendar.get(Calendar.MONTH ) + 1));
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if (m_orignalHeight == 0)
            m_orignalHeight = m_calendarCard.getHeight();
        if (m_orignalWeekHeight == 0)
            m_orignalWeekHeight = m_weekLayout.getHeight();
        if (m_orignalTitleHeight == 0)
            m_orignalTitleHeight = m_cardTitle.getHeight();
        if(m_minOrignalHeight == 0)
            m_minOrignalHeight = MomentsUtils.dip2px(m_context, 50) + m_orignalWeekHeight + MomentsUtils.dip2px(m_context, 11) + m_orignalTitleHeight;

    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {

            case MotionEvent.ACTION_DOWN:
                mPosX = ev.getX();
                mPosY = ev.getY();
                Log.d("lzy", " ACTION_DOWN----- " + (int) (mPosY));
                break;
            case MotionEvent.ACTION_MOVE:
                mCurPosX = ev.getX();
                mCurPosY = ev.getY();
                m_marginCountY = (int) (mPosY - mCurPosY);
                if (Math.abs(mCurPosX - mPosX) < Math.abs(mCurPosY - mPosY)) {
                    if (m_marginCountY > m_minMoveSize)
                        smoothShrink(m_marginCountY);
                    else if (m_marginCountY < -m_minMoveSize) {
                        Log.d("lzy", "smoothExpand ==== ");
                        smoothExpand(Math.abs(m_marginCountY));
                    }

                }

                break;
            case MotionEvent.ACTION_UP:
                mCurPosX = ev.getX();
                mCurPosY = ev.getY();
                if (Math.abs(mCurPosX - mPosX) >= Math.abs(mCurPosY - mPosY))
                    break;
                if (Math.abs(m_marginCountY) <= m_minMoveSize) {
                    m_marginCountY = 0;
                } else {
                    if (Math.abs(m_marginCountY) > m_minEffectiveSize) {
                        isChangeEffect = true;
                        if (m_marginCountY > 0) {
                            smoothShrinkAuto();
                        } else {
                            smoothExpandAuto();
                        }
                    } else {
                        isChangeEffect = false;
                        if (m_marginCountY < 0) {
                            smoothShrinkAuto();
                        } else {
                            smoothExpandAuto();
                        }

                    }
                    return true;
                }

                Log.d("lzy", "ACTION_UP-------");
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    private void smoothShrinkAuto() {
        if(isChangeEffect)
            setMonthYear(CalendarUtil.getChooseCalendar());
        new Thread() {
            @Override
            public void run() {
                if (isChangeEffect) {
                    while (m_marginCountY < m_orignalHeight) {
                        post(new Runnable() {
                            @Override
                            public void run() {
                                synchronized (m_context) {
                                    m_marginCountY += m_minMoveSize;
                                    smoothShrink(m_marginCountY);
                                }
                            }
                        });

                        try {
                            Thread.sleep(20);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    isChangeEffect = false;
                } else{

                    m_marginCountY= m_orignalHeight - m_calendarCard.getHeight();
                    while (m_marginCountY < m_orignalHeight) {
                        post(new Runnable() {
                            @Override
                            public void run() {
                                synchronized (m_context) {
                                    m_marginCountY += m_minMoveSize;
                                    smoothShrink(m_marginCountY);
                                }
                            }
                        });

                        try {
                            Thread.sleep(20);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }

            }
        }.start();

    }

    private void smoothShrink(int scrollY) {

        if (m_monthPager.getVisibility() == VISIBLE) {
            int chooseHeight = 0;
            int rowHeight = 0;
            for (int i = 0; i < m_monthPager.getChildCount(); i++) {
                MonthCalendar index = (MonthCalendar) m_monthPager.getChildAt(i);
                rowHeight = index.getRowHeight();
                if (index.getChooseHeight() != -1) {
                    chooseHeight = index.getChooseHeight();
                    break;
                }
            }
            if (scrollY < chooseHeight) {
                m_monthPager.scrollTo(m_monthPager.getScrollX(), scrollY);

                Log.d("lzy", "monthCalendar.getChooseHeight() == " + chooseHeight);
            } else {
                m_monthPager.scrollTo(m_monthPager.getScrollX(), chooseHeight);
            }

            Log.d("lzy", "(m_orignalHeight - scrollY) == " + (m_orignalHeight - scrollY) + "monthCalendar.getRowHeight() == " + rowHeight);
            if ((m_orignalHeight - scrollY) > rowHeight + m_orignalWeekHeight + m_orignalTitleHeight) {

                resizeCardHeigt(m_orignalHeight - scrollY);
            } else {
                m_monthPager.setVisibility(GONE);
                m_weekPager.setVisibility(VISIBLE);
                int apartWeek = CalendarUtil.getWeekFromDayToDay(Calendar.getInstance(), CalendarUtil.getChooseCalendar());
                Log.d("lzy", "apartweek ==== " + apartWeek);
                m_weekPager.setCurrentItem(ValueUtil.DEFAULT_WEEK_ITEM + apartWeek, false);
                for (int i = 0; i < m_weekPager.getChildCount(); i++) {
                    WeekCalendar weekCalendar = (WeekCalendar) m_weekPager.getChildAt(i);
                    weekCalendar.reflushSelectDay();
                }
                resizeCardHeigt(m_minOrignalHeight);
            }


            Log.d("lzy", " ACTION_MOVE----- " + (int) (mCurPosY - mPosY));
        }
    }

    private void smoothExpand(int scrollY) {
        scrollY = Math.abs(scrollY);
        int apartMonth = CalendarUtil.getMonthFromDayToDay(Calendar.getInstance(), CalendarUtil.getChooseCalendar());
        m_monthPager.setCurrentItem(ValueUtil.DEFAULT_MONTH_ITEM + apartMonth, false);
        m_monthPager.setVisibility(VISIBLE);
        m_weekPager.setVisibility(GONE);
        int chooseHeight = 0;
        int monthHeigt = 0;
        for (int i = 0; i < m_monthPager.getChildCount(); i++) {
            MonthCalendar monthCalendar = (MonthCalendar) m_monthPager.getChildAt(i);
            if (monthCalendar.getChooseHeight() != -1) {
                chooseHeight = monthCalendar.getChooseHeight();
                monthHeigt = monthCalendar.getHeight();
                break;
            }

        }

        Log.d("lzy", "scrollY + m_minOrignalHeight ==== " + scrollY + m_minOrignalHeight);
        Log.d("lzy", "m_orignalHeight + MomentsUtils.dip2px(m_context,11) === " + m_orignalHeight + MomentsUtils.dip2px(m_context, 11));

        if (monthHeigt - scrollY < chooseHeight)
            m_monthPager.scrollTo(m_monthPager.getScrollX(), monthHeigt - scrollY);
        if (scrollY + m_minOrignalHeight < m_orignalHeight) {
            resizeCardHeigt(m_minOrignalHeight + scrollY);

        } else {
            for (int i = 0; i < m_monthPager.getChildCount(); i++) {
                MonthCalendar monthCalendar = (MonthCalendar) m_monthPager.getChildAt(i);
                monthCalendar.reflushSelectDay();
            }
            resizeCardHeigt(m_orignalHeight);
            m_monthPager.scrollTo(m_monthPager.getScrollX(), 0);
        }
    }

    private void smoothExpandAuto() {
        Log.d("lzy", "smoothExpandAuto start ======");
        if(isChangeEffect)
            setMonthYear(CalendarUtil.getChooseCalendar());
        new Thread() {
            @Override
            public void run() {
                if (isChangeEffect) {
                    while (Math.abs(m_marginCountY) < m_orignalHeight - m_minOrignalHeight) {
                        post(new Runnable() {
                            @Override
                            public void run() {
                                synchronized (m_context) {
                                    m_marginCountY -= m_minMoveSize;
                                    smoothExpand(Math.abs(m_marginCountY));
                                }
                            }
                        });

                        try {
                            Thread.sleep(20);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    isChangeEffect = false;
                } else {
                    m_marginCountY = m_calendarCard.getHeight() - m_minOrignalHeight;
                    while (Math.abs(m_marginCountY) < m_orignalHeight  - m_minOrignalHeight) {
                        int i = 0;
                        post(new Runnable() {
                            @Override
                            public void run() {
                                synchronized (m_context) {
                                    m_marginCountY += m_minMoveSize;
                                    smoothExpand( Math.abs(m_marginCountY));
                                }
                            }
                        });

                        try {
                            Thread.sleep(20);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }

            }
        }.start();

        Log.d("lzy", "smoothExpandAuto end ======");
    }

    private void resizeCardHeigt(int height) {

        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) m_calendarCard.getLayoutParams();

        params.width = m_calendarCard.getWidth();
        params.height = height;
        Log.d("lzy", "params.height === " + params.height);
        m_calendarCard.setLayoutParams(params);
    }

}

当滑动的距离大于有效距离时,缩小或放大日历。否则·日历变为原来的大小。
这里介绍如何收缩:
以smoothexpandauto为例,当滑动距离大于最小滑动距离,那么启动一个线程,调用ViewPager 的scrollTo到选择的日期的位置,同时以相同的速度扩大父布局,当滚动到 选择的日期的位置时,不再scrollto, 直接放大父布局。这里可以优化成先加速后减速,更符合material design。
代码链接: 点击打开链接
代码参考了github上的某个项目,具体找不到 ,如有需要立即删除。 





  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Material Design是谷歌推出的一种设计语言,旨在为移动设备和Web应用提供统一、现代、直观的用户界面设计。它强调了动效、3D效果、触摸反馈等交互体验,同时也提出了一系列设计原则和指导方针,以保证界面的整体美观、一致性和可用性。Material Design通过结合传统的设计元素和现代的数字技术,打造出一种简洁而充满活力的设计风格。 ### 回答2: Material Design 风格是一种由Google推出的设计风格,旨在为移动设备和web应用程序提供一致且有吸引力的用户界面设计。它的设计理念主要基于实物(material)的触感和运动效果,并将这些概念应用到数字界面设计中。 Material Design 风格具有以下特点: 1. 平面化设计:Material Design 风格强调简洁和平面化的界面设计,使用户界面看起来更加清晰和易于理解。 2. 实物模拟:Material Design 风格通过使用阴影、动画和过渡效果等,营造出实物在数字界面上的触感和运动效果,使用户界面更加生动和自然。 3. 定义规范:Material Design 风格为开发者提供了一系列严格的设计规范和指导,包括颜色、字体、图标和布局等,以确保应用程序的一致性和美观性。 4. 多平台适配:Material Design 风格可以在各种平台上使用,包括Android设备、iOS设备以及Web应用程序,实现了跨平台的一致性设计。 5. 响应式布局:Material Design 风格提倡使用响应式设计,使应用程序能够自动适应不同设备的屏幕大小和分辨率,提供更好的用户体验。 总而言之,Material Design 风格以其清晰、简洁和生动的设计风格,以及严格的规范和跨平台适配能力,成为了现代应用程序设计中非常流行的一种设计风格。通过使用Material Design 风格,开发者可以为用户提供更好的用户体验,同时也能够提高应用程序的品质和使用效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值