幻灯片动画后,嵌套列表被父列表元素截断

时间:2015-10-29 13:48:25

标签: angularjs nested angularjs-animation

我正在使用嵌套的评论列表构建一个Ionic应用程序。我需要将回复动画为子元素并保留状态。目前我正在使用jQuery slideToggle的简单指令,但这不保留状态(并且不是“Angular方式”)。

Shlomi Assaf的

This example of slide animations是我需要的一个很好的开始,但它不处理嵌套元素。我创建了他的CodePen项目的a nested version来演示这个问题。

我不确定是否应该修改动画功能来处理嵌套元素,或者我的控制器是否应该在动画子元素时(或者在完成子元素之后)在祖先元素上调用动画。

对此表示感谢。以下是使用原生AngularJS指令的HTML的基础:

<button ng-click="slideToggle1=!slideToggle1">Click Me</button>
<div class="slide-toggle" ng-show="slideToggle1"> ... </div>

这是原始动画功能:

app.animation('.slide-toggle', ['$animateCss', function($animateCss) {
    var lastId = 0;
    var _cache = {};

    function getId(el) {
      var id = el[0].getAttribute("data-slide-toggle");
      if (!id) {
        id = ++lastId;
        el[0].setAttribute("data-slide-toggle", id);
      }
      return id;
    }

    function getState(id) {
      var state = _cache[id];
      if (!state) {
        state = {};
        _cache[id] = state;
      }
      return state;
    }

    function generateRunner(closing, state, animator, element, doneFn) {
      return function() {
        state.animating = true;
        state.animator = animator;
        state.doneFn = doneFn;
        animator.start().finally(function() {
          if (closing && state.doneFn === doneFn) {
            element[0].style.height = '';
          }
          state.animating = false;
          state.animator = undefined;
          state.doneFn();
        });
      }
    }

    return {
      addClass: function(element, className, doneFn) {
        if (className == 'ng-hide') {
          var state = getState(getId(element));
          var height = (state.animating && state.height) ?
            state.height : element[0].offsetHeight;

          var animator = $animateCss(element, {
            from: {
              height: height + 'px',
              opacity: 1
            },
            to: {
              height: '0px',
              opacity: 0
            }
          });
          if (animator) {
            if (state.animating) {
              state.doneFn =
                generateRunner(true,
                  state,
                  animator,
                  element,
                  doneFn);
              return state.animator.end();
            } else {
              state.height = height;
              return generateRunner(true,
                state,
                animator,
                element,
                doneFn)();
            }
          }
        }
        doneFn();
      },
      removeClass: function(element, className, doneFn) {
        if (className == 'ng-hide') {
          var state = getState(getId(element));
          var height = (state.animating && state.height) ?
            state.height : element[0].offsetHeight;

          var animator = $animateCss(element, {
            from: {
              height: '0px',
              opacity: 0
            },
            to: {
              height: height + 'px',
              opacity: 1
            }
          });

          if (animator) {
            if (state.animating) {
              state.doneFn = generateRunner(false,
                state,
                animator,
                element,
                doneFn);
              return state.animator.end();
            } else {
              state.height = height;
              return generateRunner(false,
                state,
                animator,
                element,
                doneFn)();
            }
          }
        }
        doneFn();
      }
    };
}]);

3 个答案:

答案 0 :(得分:0)

这是我现在使用的内容。它是将父元素的高度设置为auto的指令,因此当它切换时,它会随子列表高度扩展或收缩。如果切换父列表,则高度将重新计算为其动画的正常值。

app.directive('toggleParent', function () {
    return {
        restrict: 'C',
        compile: function (element, attr) {

            return function (scope, element) {
                element.on('click', function (event) {
                    $(this).closest('.slide-toggle').css('height', 'auto');
                });
            }
        }
    }
});

<强> CodePen demo

我确信可以使用动画实现相同的功能。这就是我真正喜欢的帮助。

答案 1 :(得分:0)

如果你想做多个深度,你可以使用它:

<强>的jQuery

    LayoutParams lParm = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);

    for(int i = 0; i < 10; i++) 
    {
        TextView tvItem = new TextView(this);
        tvItem.setLayoutParams(lParm);
        tvItem.setText("Item #"+i);
        tvItem.setBackgroundColor(0xff66ff66);
        tvItem.setEms(7);
        tvItem.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
        ll.addView(tvItem);

        EditText etPrep = new EditText(this);
        etPrep.setLayoutParams(lParm);
        etPrep.setText("0");
        etPrep.setEms(2);
        ll.addView(etPrep);

        EditText etOpen = new EditText(this);
        etOpen.setLayoutParams(lParm);
        etOpen.setText("0");
        etOpen.setEms(2);
        ll.addView(etOpen);

        EditText etCase = new EditText(this);
        etCase.setLayoutParams(lParm);
        etCase.setText("0");
        etCase.setEms(2);
        ll.addView(etCase);

    }

原生JS

app.directive('toggleParents', function () {
    return {
        compile: function (element, attr) {

            return function (scope, element) {
                element.on('click', function (event) {
                    $(this).parents('.slide-toggle').css('height', 'auto');
                });
            }
        }
    }
});

答案 2 :(得分:0)

您只需在此处添加else语句:

if (closing && state.doneFn === doneFn) {
    element[0].style.height = '';
} else {
    element[0].style.height = 'auto';
}

这样在动画完成后,高度设置为自动,并且可以根据需要解决所有级别的所有内容。