Android自定义View(RollWeekView-炫酷的星期日期选择控件)

版权声明:本文为openXu原创文章【openXu的博客】,未经博主容许不得以任何形式转载android

目录:git


  最近收到一个自定义控件的需求,须要作一个日期选择控件,实现图以下:
     这里写图片描述

  一次展现一个星期的5天,中间放大的为当前选中的;若是点击了其中一个日期,好比星期五,那么总体向左滑动,并将星期五慢慢放大,星期三慢慢缩小,星期六和星期天就展现出来了;若是继续点击星期六,那么照样是总体向左滑动一个单位,星期日右边就须要塞进一个星期一。就是一个无限循环的过程,中间选中的须要展现当天的日期。github

一、分析

  最开始,我想到在LinearLayout中依次排开7个子控件(星期几),当点击以后,把全部的子控件经过动画移动相应的偏移量,可是,若是移动后就会出现空位的状况(周一的左边和周日的右边没有了),因此这种方式但是能够,可是要解决无限循环空位的状况。
  因而就想到能不能多添加几个子控件做为空位替补?这个方法确定能实现,可是究竟须要多少个替补呢?这些替补应该放在什么位置呢?
  当前展现的5个子控件中,若是点击最左边或者最右边,这样的偏移量是最大的,须要便宜两个子控件单位,因此左边和右边最多个须要2个替补就好了,算起来也很少,一共才9个(当前展现5个,左边隐藏替补2个,右边隐藏替补2个)。在点击以前,先将替补位置设置好,当点击以后,全部子控件执行偏移动画(不可能出现空位,最多偏移2位),动画结束以后,再从新为隐藏的4个替补分配位置并绑定数据,绑定什么数据那就看当前中间显示的是星期几了。web

分析图以下:
这里写图片描述ide

  可是新的问题又来了,动画执行完毕以后,怎么判断哪些子控件是当前正在显示的呢(中间五个)?因为正在显示的子控件的位置是能够肯定的,由于要重写onMeasure(),在onMeasure()方法中能够获得单个子控件的宽度(item_width=getMeasureWidth()/5),动画结束以后,遍历这些子控件,若是x==0的那确定就是当前正在展现的第一个子控件,x==item_width则是第二个…,剩余的4个就不用判断了,直接将两个移动到左边,两个移动到右边,而后从新为这四个替补设置数据。svg

二、定义控件布局

组合控件的布局以下:布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:gravity="center_vertical">

    <LinearLayout android:id="@+id/ll_1" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center">
        <LinearLayout android:layout_width="@dimen/week_item_sise" android:layout_height="@dimen/week_item_sise" android:background="@drawable/week_one_bg" android:orientation="vertical" android:gravity="center">
            <TextView android:id="@+id/tv_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="" />
            <TextView android:id="@+id/tv_date1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="" />
        </LinearLayout>
    </LinearLayout>

    <LinearLayout android:id="@+id/ll_2" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center">
        <LinearLayout android:layout_width="@dimen/week_item_sise" android:layout_height="@dimen/week_item_sise" android:background="@drawable/week_one_bg" android:orientation="vertical" android:gravity="center">
            <TextView android:id="@+id/tv_2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="" />
            <TextView android:id="@+id/tv_date2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="" />
        </LinearLayout>
    </LinearLayout>
    <LinearLayout android:id="@+id/ll_3" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center">
        <LinearLayout android:layout_width="@dimen/week_item_sise" android:layout_height="@dimen/week_item_sise" android:background="@drawable/week_one_bg" android:orientation="vertical" android:gravity="center">
            <TextView android:id="@+id/tv_3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="" />
            <TextView android:id="@+id/tv_date3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="" />
        </LinearLayout>
    </LinearLayout>

    <LinearLayout android:id="@+id/ll_4" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center">
        <LinearLayout android:layout_width="@dimen/week_item_sise" android:layout_height="@dimen/week_item_sise" android:background="@drawable/week_one_bg" android:orientation="vertical" android:gravity="center">
            <TextView android:id="@+id/tv_4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="" />
            <TextView android:id="@+id/tv_date4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="" />
        </LinearLayout>
    </LinearLayout>

    <LinearLayout android:id="@+id/ll_5" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center">
        <LinearLayout android:layout_width="@dimen/week_item_sise" android:layout_height="@dimen/week_item_sise" android:background="@drawable/week_one_bg" android:orientation="vertical" android:gravity="center">
            <TextView android:id="@+id/tv_5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="" />
            <TextView android:id="@+id/tv_date5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="" />
        </LinearLayout>
    </LinearLayout>

    <LinearLayout android:id="@+id/ll_6" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center">
        <LinearLayout android:layout_width="@dimen/week_item_sise" android:layout_height="@dimen/week_item_sise" android:background="@drawable/week_one_bg" android:orientation="vertical" android:gravity="center">
            <TextView android:id="@+id/tv_6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="" />
            <TextView android:id="@+id/tv_date6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="" />
        </LinearLayout>
    </LinearLayout>

    <LinearLayout android:id="@+id/ll_7" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center">
        <LinearLayout android:layout_width="@dimen/week_item_sise" android:layout_height="@dimen/week_item_sise" android:background="@drawable/week_one_bg" android:orientation="vertical" android:gravity="center">
            <TextView android:id="@+id/tv_7" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="" />
            <TextView android:id="@+id/tv_date7" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="" />
        </LinearLayout>
    </LinearLayout>

    <LinearLayout android:id="@+id/ll_8" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center">
        <LinearLayout android:layout_width="@dimen/week_item_sise" android:layout_height="@dimen/week_item_sise" android:background="@drawable/week_one_bg" android:orientation="vertical" android:gravity="center">
            <TextView android:id="@+id/tv_8" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="" />
            <TextView android:id="@+id/tv_date8" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="" />
        </LinearLayout>
    </LinearLayout>

    <LinearLayout android:id="@+id/ll_9" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center">
        <LinearLayout android:layout_width="@dimen/week_item_sise" android:layout_height="@dimen/week_item_sise" android:background="@drawable/week_one_bg" android:orientation="vertical" android:gravity="center">
            <TextView android:id="@+id/tv_9" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="" />
            <TextView android:id="@+id/tv_date9" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="" />
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

三、定义CustomWeekView

  布局写完后,接下来应该找一个容器接纳他们,这个容器就是咱们定义的CustomWeekView,让其继承LinearLayout,而后重写构造方法,并初始化子控件;此处自定义属性就再也不赘述,以前的全部自定义控件案例中都讲解过,若是不熟悉请参考 Android自定义View(2、深刻解析自定义属性)动画

public class CustomWeekView extends LinearLayout{
    public CustomWeekView(Context context) {
    this(context, null);
}

    public CustomWeekView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomWeekView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }
    private void init(Context context, AttributeSet attrs) {
        LayoutInflater.from(context).inflate(R.layout.custom_week_layout, this, true);
        ll_1 = (LinearLayout) findViewById(R.id.ll_1);
        ll_2 = (LinearLayout) findViewById(R.id.ll_2);
        ...
        tv_1 = (TextView) findViewById(R.id.tv_1);
        tv_2 = (TextView) findViewById(R.id.tv_2);
        ...
        tv_date1 = (TextView) findViewById(R.id.tv_date1);
        tv_date2 = (TextView) findViewById(R.id.tv_date2);
        ...
        if (attrs != null) {
            TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.LimitScroller);
            limit = 5;
            background = ta.getColor(R.styleable.LimitScroller_android_background, Color.TRANSPARENT);
            textSize = ta.getDimension(R.styleable.LimitScroller_android_textSize, 15f);
            final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
            textSize = textSize / fontScale + 0.5f;
            dateTextSize = ta.getInteger(R.styleable.LimitScroller_dateTextSize, 12);
            textColor = ta.getColor(R.styleable.LimitScroller_android_textColor, Color.BLACK);
            dateTextColor = ta.getColor(R.styleable.LimitScroller_dateTextColor, Color.RED);
            durationTime = ta.getInt(R.styleable.LimitScroller_durationTime, 1000);
            scaleSize = ta.getFloat(R.styleable.LimitScroller_scaleSize, 0);
            ta.recycle();  //注意回收
        }
    }
}

四、重写onMeasure

  因为本控件宽度是填充父窗体,高度是包裹内容,这里不须要咱们手动写代码测量,直接调用super.onMeasure()好了。(onMeasure()详解请移步:Android自定义View(3、深刻解析控件测量onMeasure))。可是咱们须要在测量完毕后,计算子控件的宽度并初次安置每一个子控件的位置,这个宽度就是后面移动的单位,也做为位置判断的依据。因为onMeasure()方法会被调用屡次(后面设置位置、显示隐藏等等操做都会致使onMeasure()触发),因此须要判断一下若是ITEM_WIDTH<=0才须要计算;而后还要为子控件设置初始日期:this

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//        Log.w(TAG, "测量完成,宽度*高度="+getMeasuredWidth()+"*"+getMeasuredHeight());
        if(ITEM_WIDTH<=0) {
            ITEM_WIDTH = getMeasuredWidth()/limit;
//            Log.w(TAG, "每小项尺寸:"+ITEM_WIDTH+"*"+getMeasuredHeight());
            measureInit();
        }
        if(ll_2.getX()>0 && !isFirstSeted) {
            //设置今天的日期在中间
            animalFinish = false;
            Calendar cal = Calendar.getInstance();
            int todayNum = cal.get(Calendar.DAY_OF_WEEK)-1;
            Log.d(TAG, "今天是星期"+WEEK_STR[todayNum]);
            setCenter(getEnumByNum(todayNum));
            animalFinish = true;
            isFirstSeted = true;
        }
    }

/**根据屏幕的宽度和显示的个数,设置item的宽度*/
private void measureInit(){
    LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)ll_1.getLayoutParams();
    lp.width = ITEM_WIDTH;
    ll_1.setLayoutParams(lp);
    lp = (LinearLayout.LayoutParams)ll_2.getLayoutParams();
    lp.width = ITEM_WIDTH;
    ll_2.setLayoutParams(lp);
    lp = (LinearLayout.LayoutParams)ll_3.getLayoutParams();
    lp.width = ITEM_WIDTH;
    ll_3.setLayoutParams(lp);
    lp = (LinearLayout.LayoutParams)ll_4.getLayoutParams();
    lp.width = ITEM_WIDTH;
    ll_4.setLayoutParams(lp);
    lp = (LinearLayout.LayoutParams)ll_5.getLayoutParams();
    lp.width = ITEM_WIDTH;
    ll_5.setLayoutParams(lp);
    lp = (LinearLayout.LayoutParams)ll_6.getLayoutParams();
    lp.width = ITEM_WIDTH;
    ll_6.setLayoutParams(lp);
    lp = (LinearLayout.LayoutParams)ll_7.getLayoutParams();
    lp.width = ITEM_WIDTH;
    ll_7.setLayoutParams(lp);
    lp = (LinearLayout.LayoutParams)ll_8.getLayoutParams();
    lp.width = ITEM_WIDTH;
    ll_8.setLayoutParams(lp);
    lp = (LinearLayout.LayoutParams)ll_9.getLayoutParams();
    lp.width = ITEM_WIDTH;
    ll_9.setLayoutParams(lp);
}

五、点击后执行动画

  上面的步骤完成以后,基本上已经完成的控件的初始设置,接下来就是点击子控件后执行动画了。这里一共须要执行两套动画,一套是缩放动画、一套是移动动画。添加点击事件的代码就不贴出来了,下面是执行动画的方法:spa

private void startAnimation(final WEEKDAY centerWitch, final LinearLayout llClickView) {

        if(centerWitch==centerNow)
            return;
        animalFinish = false;

        LinearLayout innerLL = (LinearLayout)ll3.getChildAt(0);
        TextView tvDate = (TextView)innerLL.getChildAt(1);
        tvDate.setVisibility(View.GONE);
        innerLL = (LinearLayout)llClickView.getChildAt(0);
        tvDate = (TextView)innerLL.getChildAt(1);
        tvDate.setVisibility(View.VISIBLE);

        //根据当前中间位置显示的 和 被点击的日期,获取须要偏移的增量
        int offset = getXOffset(centerWitch);
        Log.d(TAG, "当前中间为"+centerNow+",点击的是"+centerWitch+ "  偏移量:"+offset);

        //当前中间位置的须要缩放到原尺寸
//        Log.v(TAG, "中间item缩放量scaleX="+ll3.getChildAt(0).getScaleX()+" scaleY="+ll3.getChildAt(0).getScaleY());
        ObjectAnimator anim100 = ObjectAnimator.ofFloat(ll3.getChildAt(0), "scaleX", ll3.getChildAt(0).getScaleX(), 1.0f);
        ObjectAnimator anim101 = ObjectAnimator.ofFloat(ll3.getChildAt(0), "scaleY", ll3.getChildAt(0).getScaleY(), 1.0f);
        //被点击的须要放大
        ObjectAnimator anim102 = ObjectAnimator.ofFloat(llClickView.getChildAt(0), "scaleX", 1, scaleSize);
        ObjectAnimator anim103 = ObjectAnimator.ofFloat(llClickView.getChildAt(0), "scaleY", 1, scaleSize);

        //透明度动画
        ObjectAnimator anim104 = ObjectAnimator.ofFloat(llClickView.getChildAt(0), "scaleY", 1, scaleSize);

        //位移动画
        ObjectAnimator anim1 = ObjectAnimator.ofFloat(ll_1, "X", ll_1.getX(), ll_1.getX() + offset);
        ObjectAnimator anim2 = ObjectAnimator.ofFloat(ll_2, "X", ll_2.getX(), ll_2.getX() + offset);
        ObjectAnimator anim3 = ObjectAnimator.ofFloat(ll_3, "X", ll_3.getX(), ll_3.getX() + offset);
        ObjectAnimator anim4 = ObjectAnimator.ofFloat(ll_4, "X", ll_4.getX(), ll_4.getX() + offset);
        ObjectAnimator anim5 = ObjectAnimator.ofFloat(ll_5, "X", ll_5.getX(), ll_5.getX() + offset);
        ObjectAnimator anim6 = ObjectAnimator.ofFloat(ll_6, "X", ll_6.getX(), ll_6.getX() + offset);
        ObjectAnimator anim7 = ObjectAnimator.ofFloat(ll_7, "X", ll_7.getX(), ll_7.getX() + offset);
        ObjectAnimator anim8 = ObjectAnimator.ofFloat(ll_8, "X", ll_8.getX(), ll_8.getX() + offset);
        ObjectAnimator anim9 = ObjectAnimator.ofFloat(ll_9, "X", ll_9.getX(), ll_9.getX() + offset);
        AnimatorSet animSet = new AnimatorSet();
        animSet.setDuration(durationTime);
        animSet.playTogether(anim100, anim101, anim102, anim103, anim1, anim2, anim3, anim4, anim5, anim6, anim7, anim8, anim9);
        animSet.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
            }
            @Override
            public void onAnimationEnd(Animator animation) {

                Log.w(TAG, "动画结束后位置:"+ll_1.getX()+" "+ll_2.getX()+" "+ll_3.getX()+" "
                        +ll_4.getX()+" "+ll_5.getX()+" "+ll_6.getX()
                        +" "+ll_7.getX()+" "+ll_8.getX()+" "+ll_9.getX());

                setCenter(centerWitch);

                animalFinish = true;
            }
            @Override
            public void onAnimationCancel(Animator animation) {
            }
            @Override
            public void onAnimationRepeat(Animator animation) {
            }
        });
        animSet.start();
    }

七、重置预备控件

  动画执行完毕以后,要作两个操做。第一个就是将当前不在显示范围的4个子控件左右各放2个,第二步就是为预备控件绑定新的星期日期。下面的方法是根据各个子控件的坐标来判断是隐藏仍是展现,而后为隐藏的控件从新安排位置;而后绑定数据:

/*这些引用表明当前正在显示的5个条目 和 四个预备条目,
     *因为ll_x系列条目是不断移动的,因此此处须要根据ll_x的位置从新为llx赋值
     * 其中ll1-ll5为当前正在显示的条目, ll六、ll7为右边隐藏的预备条目, ll八、ll9为左边的隐藏预备条目
     */
    private LinearLayout ll1, ll2, ll3, ll4, ll5, ll6, ll7, ll8, ll9;
    /**一、找到正在展现的五个item,并将预备item复位*/
    private void setCenter(WEEKDAY weekDay){
        //记录当前显示在中间的星期X
        centerNow = weekDay;
        //一、找到当前显示的5个条目的位置
        List<LinearLayout> list = new ArrayList<>(llList);
        for(int i = 0; i<5; i++){
            for(int j = 0; j<list.size(); j++){
                LinearLayout ll = list.get(j);
                if(ll.getX()==ITEM_WIDTH*i){
                    list.remove(ll);      //找到以后就remove能够减小后面遍历的次数
//                    Log.d(TAG, "找到"+i+"了"+ll);
                    switch (i) {
                        case 0:
                            ll1 = ll;
                            break;
                        case 1:
                            ll2 = ll;
                            break;
                        case 2:
                            ll3 = ll;
                            //当前中间位置item放大
                            ll3.getChildAt(0).setScaleX(scaleSize);
                            ll3.getChildAt(0).setScaleY(scaleSize);
                            break;
                        case 3:
                            ll4 = ll;
                            break;
                        case 4:
                            ll5 = ll;
                            break;
                    }
                }
            }
        }
        Log.i(TAG, "找完后还剩"+list.size()+"  总:"+llList.size());
        //二、剩余的四个做为预备,归位,左边隐藏两个,右边隐藏两个
        for(int i = 0; i<list.size(); i++){
            LinearLayout ll = list.get(i);
            switch (i){
                case 0:   //左1
                    ll.setX(-ITEM_WIDTH*2);
                    ll8=ll;
                    break;
                case 1:   //左2
                    ll.setX(-ITEM_WIDTH*1);
                    ll9=ll;
                    break;
                case 2:   //右1
                    ll.setX(ITEM_WIDTH*5);
                    ll6=ll;
                    break;
                case 3:   //右2
                    ll.setX(ITEM_WIDTH*6);
                    ll7=ll;
                    break;
            }
        }
        //绑定数据
        reBoundDataByCenter(weekDay);
    }

    /**二、从新绑定数据*/
    private void reBoundDataByCenter(WEEKDAY weekDay){
        if(weekDay == WEEKDAY.wk1){
            /*星期1在中间,依次为四、五、六、七、一、二、三、四、5*/
            setLLText(ll8, 4, false);
            setLLText(ll9, 5, false);
            setLLText(ll1, 6, false);
            setLLText(ll2, 7, false);
            setLLText(ll3, 1, true);
            setLLText(ll4, 2, false);
            setLLText(ll5, 3, false);
            setLLText(ll6, 4, false);
            setLLText(ll7, 5, false);
        }else if(weekDay == WEEKDAY.wk2){
            /*星期2在中间,依次为五、六、七、一、二、三、四、五、6*/
            setLLText(ll8, 5, false);
            setLLText(ll9, 6, false);
            setLLText(ll1, 7, false);
            setLLText(ll2, 1, false);
            setLLText(ll3, 2, true);
            setLLText(ll4, 3, false);
            setLLText(ll5, 4, false);
            setLLText(ll6, 5, false);
            setLLText(ll7, 6, false);
        }else if(weekDay == WEEKDAY.wk3){
            /*星期3在中间,依次为六、七、一、二、三、四、五、六、7*/
            setLLText(ll8, 6, false);
            setLLText(ll9, 7, false);
            setLLText(ll1, 1, false);
            setLLText(ll2, 2, false);
            setLLText(ll3, 3, true);
            setLLText(ll4, 4, false);
            setLLText(ll5, 5, false);
            setLLText(ll6, 6, false);
            setLLText(ll7, 7, false);
        }else if(weekDay == WEEKDAY.wk4){
            /*星期4在中间,依次为七、一、二、三、四、五、六、七、1*/
            setLLText(ll8, 7, false);
            setLLText(ll9, 1, false);
            setLLText(ll1, 2, false);
            setLLText(ll2, 3, false);
            setLLText(ll3, 4, true);
            setLLText(ll4, 5, false);
            setLLText(ll5, 6, false);
            setLLText(ll6, 7, false);
            setLLText(ll7, 1, false);
        }else if(weekDay == WEEKDAY.wk5){
            /*星期5在中间,依次为一、二、三、四、五、六、七、一、2*/
            setLLText(ll8, 1, false);
            setLLText(ll9, 2, false);
            setLLText(ll1, 3, false);
            setLLText(ll2, 4, false);
            setLLText(ll3, 5, true);
            setLLText(ll4, 6, false);
            setLLText(ll5, 7, false);
            setLLText(ll6, 1, false);
            setLLText(ll7, 2, false);
        }else if(weekDay == WEEKDAY.wk6){
            /*星期6在中间,依次为二、三、四、五、六、七、一、二、3*/
            setLLText(ll8, 2, false);
            setLLText(ll9, 3, false);
            setLLText(ll1, 4, false);
            setLLText(ll2, 5, false);
            setLLText(ll3, 6, true);
            setLLText(ll4, 7, false);
            setLLText(ll5, 1, false);
            setLLText(ll6, 2, false);
            setLLText(ll7, 3, false);
        }else if(weekDay == WEEKDAY.wk7){
            /*星期7在中间,依次为三、四、五、六、七、一、二、三、4*/
            setLLText(ll8, 3, false);
            setLLText(ll9, 4, false);
            setLLText(ll1, 5, false);
            setLLText(ll2, 6, false);
            setLLText(ll3, 7, true);
            setLLText(ll4, 1, false);
            setLLText(ll5, 2, false);
            setLLText(ll6, 3, false);
            setLLText(ll7, 4, false);
        }
    }

    private void setLLText(LinearLayout ll, int witchDay, boolean showDate){
        ll.setTag(witchDay);   //便于区分点击事件
        LinearLayout innerLL = (LinearLayout)ll.getChildAt(0);
        TextView tv = (TextView)innerLL.getChildAt(0);
        String text = "星期" + WEEK_STR[witchDay];
        tv.setText(text);

        TextView tvDate = (TextView)innerLL.getChildAt(1);
        text = DATE_STR.get(witchDay);
        tvDate.setText(text);
        if(showDate){
            tvDate.setVisibility(View.VISIBLE);
        }else{
            tvDate.setVisibility(View.GONE);
        }
    }

  当执行完上面的方法后,控件的状态又回到了初始状态,下次点击又会重复上面的步骤。由于动画执行完后,只有被隐藏的子控件须要从新安排位置,因此,不会出现闪跳的现象。

最终效果图以下:

      这里写图片描述

喜欢请点赞,no爱请勿喷~O(∩_∩)O谢谢

##源码下载:

http://download.csdn.net/detail/u010163442/9698848 CSDN下载平台太流氓

https://github.com/openXu/JueAnimation