diff --git a/android/playground/app/src/main/java/com/alibaba/weex/extend/component/WXParallax.java b/android/playground/app/src/main/java/com/alibaba/weex/extend/component/WXParallax.java index cf248d3cd9..eae6c01b69 100644 --- a/android/playground/app/src/main/java/com/alibaba/weex/extend/component/WXParallax.java +++ b/android/playground/app/src/main/java/com/alibaba/weex/extend/component/WXParallax.java @@ -20,6 +20,8 @@ import android.graphics.Color; import android.support.annotation.Nullable; +import android.support.v4.view.ViewCompat; +import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.view.View; import android.view.animation.Animation; @@ -41,6 +43,9 @@ import com.taobao.weex.ui.component.WXComponent; import com.taobao.weex.ui.component.WXDiv; import com.taobao.weex.ui.component.WXVContainer; +import com.taobao.weex.ui.component.list.BasicListComponent; +import com.taobao.weex.ui.component.list.template.WXRecyclerTemplateList; +import com.taobao.weex.ui.view.listview.WXRecyclerView; import com.taobao.weex.utils.WXLogUtils; import com.taobao.weex.utils.WXResourceUtils; @@ -62,6 +67,7 @@ public class WXParallax extends WXDiv implements OnWXScrollListener, ICheckBindi ArrayList mTransformPropArrayList = new ArrayList<>(); BackgroundColorCreator mBackgroundColor; String mBindingRef = ""; + WXComponent mBindingComponent; private int mBackGroundColor = 0; private float mOffsetY = 0; @@ -150,8 +156,22 @@ public boolean isNeedScroller(String ref, Object option) { @Override public void onScrolled(View view, int dx, int dy) { - - mOffsetY = mOffsetY + dy; + if(ViewCompat.isInLayout(view)){ + if(mBindingComponent == null && mBindingRef != null){ + mBindingComponent = findComponent(mBindingRef); + } + if(mBindingComponent instanceof BasicListComponent + && view instanceof RecyclerView){ + BasicListComponent listComponent = (BasicListComponent) mBindingComponent; + mOffsetY = Math.abs(listComponent.calcContentOffset((RecyclerView) view)); + }else if(mBindingComponent instanceof WXRecyclerTemplateList + && view instanceof RecyclerView){ + WXRecyclerTemplateList listComponent = (WXRecyclerTemplateList) mBindingComponent; + mOffsetY = Math.abs(listComponent.calcContentOffset((RecyclerView) view)); + } + }else{ + mOffsetY = mOffsetY + dy; + } AnimationSet animationSet = new AnimationSet(true); boolean hasAnimation = false; diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/transition/WXTransition.java b/android/sdk/src/main/java/com/taobao/weex/dom/transition/WXTransition.java index 41fcd12596..b77db98c57 100644 --- a/android/sdk/src/main/java/com/taobao/weex/dom/transition/WXTransition.java +++ b/android/sdk/src/main/java/com/taobao/weex/dom/transition/WXTransition.java @@ -92,6 +92,14 @@ public class WXTransition { LAYOUT_PROPERTIES.add(Constants.Name.MARGIN_BOTTOM); LAYOUT_PROPERTIES.add(Constants.Name.MARGIN_LEFT); LAYOUT_PROPERTIES.add(Constants.Name.MARGIN_RIGHT); + LAYOUT_PROPERTIES.add(Constants.Name.LEFT); + LAYOUT_PROPERTIES.add(Constants.Name.RIGHT); + LAYOUT_PROPERTIES.add(Constants.Name.TOP); + LAYOUT_PROPERTIES.add(Constants.Name.BOTTOM); + LAYOUT_PROPERTIES.add(Constants.Name.PADDING_LEFT); + LAYOUT_PROPERTIES.add(Constants.Name.PADDING_RIGHT); + LAYOUT_PROPERTIES.add(Constants.Name.PADDING_TOP); + LAYOUT_PROPERTIES.add(Constants.Name.PADDING_BOTTOM); } /** @@ -396,12 +404,12 @@ private PropertyValuesHolder createLayoutPropertyValueHolder(String property, Ob switch (property){ case Constants.Name.WIDTH:{ holder = PropertyValuesHolder.ofFloat(Constants.Name.WIDTH, domObject.getLayoutWidth(), - WXViewUtils.getRealPxByWidth(WXUtils.getFloat(value), domObject.getViewPortWidth())); + WXViewUtils.getRealPxByWidth(WXUtils.getFloat(value, 0.0f), domObject.getViewPortWidth())); } break; case Constants.Name.HEIGHT:{ holder = PropertyValuesHolder.ofFloat(Constants.Name.HEIGHT, domObject.getLayoutHeight(), - WXViewUtils.getRealPxByWidth(WXUtils.getFloat(value), domObject.getViewPortWidth())); + WXViewUtils.getRealPxByWidth(WXUtils.getFloat(value, 0.0f), domObject.getViewPortWidth())); } break; case Constants.Name.MARGIN_TOP:{ @@ -424,6 +432,46 @@ private PropertyValuesHolder createLayoutPropertyValueHolder(String property, Ob WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth())); } break; + case Constants.Name.LEFT:{ + holder = PropertyValuesHolder.ofFloat(Constants.Name.LEFT, domObject.getPositionLeft(), + WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth())); + } + break; + case Constants.Name.RIGHT:{ + holder = PropertyValuesHolder.ofFloat(Constants.Name.RIGHT, domObject.getPositionRight(), + WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth())); + } + break; + case Constants.Name.BOTTOM:{ + holder = PropertyValuesHolder.ofFloat(Constants.Name.BOTTOM, domObject.getPositionBottom(), + WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth())); + } + break; + case Constants.Name.TOP:{ + holder = PropertyValuesHolder.ofFloat(Constants.Name.TOP, domObject.getPositionTop(), + WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth())); + } + break; + case Constants.Name.PADDING_TOP:{ + holder = PropertyValuesHolder.ofFloat(Constants.Name.PADDING_TOP, domObject.getPadding().get(Spacing.TOP), + WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth())); + } + break; + case Constants.Name.PADDING_BOTTOM:{ + holder = PropertyValuesHolder.ofFloat(Constants.Name.PADDING_BOTTOM, domObject.getPadding().get(Spacing.BOTTOM), + WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth())); + } + break; + case Constants.Name.PADDING_LEFT:{ + holder = PropertyValuesHolder.ofFloat(Constants.Name.TOP, domObject.getPadding().get(Spacing.LEFT), + WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth())); + } + break; + case Constants.Name.PADDING_RIGHT:{ + holder = PropertyValuesHolder.ofFloat(Constants.Name.TOP, domObject.getPadding().get(Spacing.RIGHT), + WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth())); + } + break; default: break; } @@ -466,6 +514,38 @@ public void onAnimationUpdate(ValueAnimator animation) { domObject.setMargin(Spacing.BOTTOM, (Float) animation.getAnimatedValue(property)); } break; + case Constants.Name.LEFT:{ + domObject.setPositionLeft((Float) animation.getAnimatedValue(property)); + } + break; + case Constants.Name.RIGHT:{ + domObject.setPositionRight((Float) animation.getAnimatedValue(property)); + } + break; + case Constants.Name.BOTTOM:{ + domObject.setPositionBottom((Float) animation.getAnimatedValue(property)); + } + break; + case Constants.Name.TOP:{ + domObject.setPositionTop((Float) animation.getAnimatedValue(property)); + } + break; + case Constants.Name.PADDING_TOP:{ + domObject.setPadding(Spacing.TOP, (Float) animation.getAnimatedValue(property)); + } + break; + case Constants.Name.PADDING_BOTTOM:{ + domObject.setPadding(Spacing.BOTTOM, (Float) animation.getAnimatedValue(property)); + } + break; + case Constants.Name.PADDING_LEFT:{ + domObject.setPadding(Spacing.LEFT, (Float) animation.getAnimatedValue(property)); + } + break; + case Constants.Name.PADDING_RIGHT:{ + domObject.setPadding(Spacing.RIGHT, (Float) animation.getAnimatedValue(property)); + } + break; default: break; } diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java index e8920d39c3..79d916a7a6 100644 --- a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java +++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java @@ -1315,7 +1315,7 @@ private boolean shouldReport(int offsetX, int offsetY) { - private int calcContentOffset(RecyclerView recyclerView) { + public int calcContentOffset(RecyclerView recyclerView) { RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); if (layoutManager instanceof LinearLayoutManager) { int firstVisibleItemPosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition(); diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/WXRecyclerTemplateList.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/WXRecyclerTemplateList.java index a5f61b7663..7671530146 100644 --- a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/WXRecyclerTemplateList.java +++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/WXRecyclerTemplateList.java @@ -1450,7 +1450,7 @@ private int calcContentSize() { return totalHeight; } - private int calcContentOffset(RecyclerView recyclerView) { + public int calcContentOffset(RecyclerView recyclerView) { RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); if (layoutManager instanceof LinearLayoutManager) { int firstVisibleItemPosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition(); diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/view/refresh/core/WXSwipeLayout.java b/android/sdk/src/main/java/com/taobao/weex/ui/view/refresh/core/WXSwipeLayout.java index 5a2050ba60..72a5215b26 100644 --- a/android/sdk/src/main/java/com/taobao/weex/ui/view/refresh/core/WXSwipeLayout.java +++ b/android/sdk/src/main/java/com/taobao/weex/ui/view/refresh/core/WXSwipeLayout.java @@ -396,7 +396,17 @@ public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) { } if (moveSpinner(-spinnerDy)) { - consumed[1] += spinnerDy; + if (!canChildScrollUp() && mPullRefreshEnable + && mTargetView.getTranslationY() > 0 + && dy > 0) { + consumed[1] += dy; + }else if (!canChildScrollDown() && mPullLoadEnable + && mTargetView.getTranslationY() < 0 + && dy < 0){ + consumed[1] += dy; + }else{ + consumed[1] += spinnerDy; + } } } diff --git a/html5/runtime/vdom/Element.js b/html5/runtime/vdom/Element.js index 01e30452b0..712b925503 100644 --- a/html5/runtime/vdom/Element.js +++ b/html5/runtime/vdom/Element.js @@ -30,7 +30,6 @@ import { } from './operation' import { uniqueId } from '../utils' import { getWeexElement, setElement } from './WeexElement' -import { filterDirective } from './directive' const DEFAULT_TAG_NAME = 'div' const BUBBLE_EVENTS = [ @@ -289,7 +288,7 @@ export default class Element extends Node { const taskCenter = getTaskCenter(this.docId) if (!silent && taskCenter) { const result = {} - result[key] = filterDirective(value) + result[key] = value taskCenter.send( 'dom', { action: 'updateAttrs' }, @@ -471,7 +470,7 @@ export default class Element extends Node { const result = { ref: this.ref.toString(), type: this.type, - attr: filterDirective(this.attr), + attr: this.attr, style: this.toStyle() } const event = [] diff --git a/html5/runtime/vdom/directive.js b/html5/runtime/vdom/directive.js deleted file mode 100644 index 4d82fde569..0000000000 --- a/html5/runtime/vdom/directive.js +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { typof } from '../utils' - -// match the binding delimiter -const delimiterRE = /\[\[((?:.|\n)+?)\]\]/g - -export function generateBinding (text) { - if (typof(text) === 'String') { - return { '@binding': text } - } - return text -} - -export function parseString (string) { - const tokens = [] - let lastIndex = delimiterRE.lastIndex = 0 - let match, index - while ((match = delimiterRE.exec(string))) { - index = match.index - if (index > lastIndex) { - tokens.push(string.slice(lastIndex, index)) - } - const binding = generateBinding(match[1].trim()) - tokens.push(binding) - lastIndex = index + match[0].length - } - if (lastIndex < string.length) { - tokens.push(string.slice(lastIndex)) - } - if (tokens.length === 1) { - return tokens[0] - } - return tokens -} - -export function filterDirective (value) { - if (typof(value) === 'String' && delimiterRE.test(value)) { - return parseString(value) - } - if (typof(value) === 'Object') { - const realData = {} - for (const key in value) { - realData[key] = filterDirective(value[key]) - } - return realData - } - if (typof(value) === 'Array') { - return value.map(filterDirective) - } - return value -} diff --git a/html5/test/unit/runtime/vdom/directive.js b/html5/test/unit/runtime/vdom/directive.js deleted file mode 100644 index cafb33d184..0000000000 --- a/html5/test/unit/runtime/vdom/directive.js +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { expect } from 'chai' -import { filterDirective } from '../../../../runtime/vdom/directive' - -describe('filterDirective', () => { - it('other type', () => { - expect(filterDirective(0)).to.be.equal(0) - expect(filterDirective(53)).to.be.equal(53) - expect(filterDirective(null)).to.be.equal(null) - const reg = /\w+/i - expect(filterDirective(reg)).to.be.equal(reg) - }) - - it('normal string', () => { - expect(filterDirective('')).to.be.equal('') - expect(filterDirective('-1')).to.be.equal('-1') - expect(filterDirective('abc')).to.be.equal('abc') - expect(filterDirective(' a bc d')).to.be.equal(' a bc d') - expect(filterDirective(' a {{ bc }}')).to.be.equal(' a {{ bc }}') - }) - - it('binding', () => { - expect(filterDirective('[[abc]]')).to.deep.equal({ '@binding': 'abc' }) - expect(filterDirective('[[ xyz ]]')).to.deep.equal({ '@binding': 'xyz' }) - expect(filterDirective('[[ x y z ]]')).to.deep.equal({ '@binding': 'x y z' }) - }) - - it('binding and normal string', () => { - expect(filterDirective('xyz[[abc]]ttt')).to.deep.equal(['xyz', { '@binding': 'abc' }, 'ttt']) - expect(filterDirective(' x [[ w ]] t ')).to.deep.equal([' x ', { '@binding': 'w' }, ' t ']) - expect(filterDirective('[[ wn]][xx{uur}]')).to.deep.equal([{ '@binding': 'wn' }, '[xx{uur}]']) - }) - - it('multi-binding', () => { - expect(filterDirective('[[abc]][[wpc]]')).to.deep.equal([{ '@binding': 'abc' }, { '@binding': 'wpc' }]) - expect(filterDirective('abcd[[ xyz ]]ef[[w]]gh')).to.deep.equal([ - 'abcd', - { '@binding': 'xyz' }, - 'ef', - { '@binding': 'w' }, - 'gh' - ]) - expect(filterDirective(' a [[ b ]] [[c]] d [[e]][[f]]g')).to.deep.equal([ - ' a ', - { '@binding': 'b' }, - ' ', - { '@binding': 'c' }, - ' d ', - { '@binding': 'e' }, - { '@binding': 'f' }, - 'g' - ]) - }) - - it('parse object', () => { - expect(filterDirective({ key: '[[x]]' })).to.deep.equal({ key: { '@binding': 'x' }}) - expect(filterDirective({ a: '[[A]]', b: '[[B]]' })).to.deep.equal({ - a: { '@binding': 'A' }, - b: { '@binding': 'B' } - }) - expect(filterDirective({ - a: '[[A]]', - x: 'X', - y: { - b: ' - [[B]] - ', - z: { - c: ['[[C]] + [[C]]', 'cc'], - w: 24 - } - } - })).to.deep.equal({ - a: { '@binding': 'A' }, - x: 'X', - y: { - b: [' - ', { '@binding': 'B' }, ' - '], - z: { - c: [[{ '@binding': 'C' }, ' + ', { '@binding': 'C' }], 'cc'], - w: 24 - } - } - }) - }) -})