blob: cedd86ccd6e1522845d2473c36e790c38da94966 [file] [log] [blame]
/*
* 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.
*/
package com.taobao.weex.ui.component.list;
import android.view.View;
import android.view.ViewGroup;
import com.taobao.weex.WXEnvironment;
import com.taobao.weex.common.WXThread;
import com.taobao.weex.utils.WXLogUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Created by sospartan on 17/03/2017.
*/
public class StickyHeaderHelper {
private final ViewGroup mParent;
private Map<String,View> mHeaderViews = new HashMap<>(); // map for <ref,view>
private Map<String,WXCell> mHeaderComps = new HashMap<>(); // map for <ref,comp>
private String mCurrentStickyRef = null;
public StickyHeaderHelper(ViewGroup parent){
this.mParent = parent;
}
/**
* @param component
*/
public void notifyStickyShow(WXCell component) {
if (component == null)
return;
mHeaderComps.put(component.getRef(),component);
if(mCurrentStickyRef != null){
WXCell cell = mHeaderComps.get(mCurrentStickyRef);
if(cell ==null || component.getScrollPositon() > cell.getScrollPositon()){
mCurrentStickyRef = component.getRef();
}
}else{
mCurrentStickyRef = component.getRef();
}
{
if(mCurrentStickyRef==null){
WXLogUtils.e("Current Sticky ref is null.");
return;
}
WXCell headComponent = mHeaderComps.get(mCurrentStickyRef);
final View headerView = headComponent.getRealView();
if (headerView == null) {
WXLogUtils.e("Sticky header's real view is null.");
return;
}
View header = mHeaderViews.get(headComponent.getRef());
if( header != null){
//already there
header.bringToFront();
}else {
mHeaderViews.put(headComponent.getRef(), headerView);
//record translation, it should not change after transformation
final float translationX = headerView.getTranslationX();
final float translationY = headerView.getTranslationY();
headComponent.removeSticky();
ViewGroup existedParent;
if ((existedParent = (ViewGroup) headerView.getParent()) != null) {
existedParent.removeView(headerView);
}
headerView.setTag(headComponent.getRef());
mParent.addView(headerView);
headerView.setTag(this);
if(headComponent.getStickyOffset() > 0) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) headerView.getLayoutParams();
if(headComponent.getStickyOffset() != params.topMargin) {
params.topMargin = headComponent.getStickyOffset();
}
}
//recover translation, sometimes it will be changed on fling
headerView.setTranslationX(translationX);
headerView.setTranslationY(translationY);
}
changeFrontStickyVisible();
if (headComponent.getDomObject().getEvents().contains("sticky")) {
headComponent.fireEvent("sticky");
}
}
}
public void notifyStickyRemove(WXCell compToRemove) {
if (compToRemove == null)
return;
final WXCell component = mHeaderComps.remove(compToRemove.getRef());
final View headerView = mHeaderViews.remove(compToRemove.getRef());
if(component == null || headerView == null){
if(WXEnvironment.isApkDebugable()) {
}
return;
}
if(mCurrentStickyRef != null && mCurrentStickyRef.equals(compToRemove.getRef())){
mCurrentStickyRef = null;
}
mParent.post(WXThread.secure(new Runnable() {
@Override
public void run() {
mParent.removeView(headerView);
if(headerView.getVisibility() != View.VISIBLE){
headerView.setVisibility(View.VISIBLE);
}
component.recoverySticky();
changeFrontStickyVisible();
}
}));
if (component.getDomObject().getEvents().contains("unsticky")) {
component.fireEvent("unsticky");
}
}
public void updateStickyView(int currentStickyPos) {
Iterator<Map.Entry<String, WXCell>> iterator = mHeaderComps.entrySet().iterator();
List<WXCell> toRemove = new ArrayList<>();
while(iterator.hasNext()){
Map.Entry<String, WXCell> next = iterator.next();
WXCell cell = next.getValue();
int pos = cell.getScrollPositon();
if(pos > currentStickyPos){
toRemove.add(cell);
}else if(pos == currentStickyPos){
mCurrentStickyRef = cell.getRef();
View view = mHeaderViews.get(cell.getRef());
if(view != null){
view.bringToFront();
changeFrontStickyVisible();
}
}
}
for(WXCell cell:toRemove){
notifyStickyRemove(cell);
}
}
private void changeFrontStickyVisible(){
if(mHeaderViews.size() <= 0){
return;
}
boolean fontVisible = false;
for(int i=mParent.getChildCount()-1; i>=0; i--){
View view = mParent.getChildAt(i);
if(fontVisible && view.getTag() instanceof StickyHeaderHelper){
if(view.getVisibility() != View.GONE){
view.setVisibility(View.GONE);
}
}else{
if(view.getTag() instanceof StickyHeaderHelper){
fontVisible = true;
if(view != null && view.getVisibility() != View.VISIBLE){
view.setVisibility(View.VISIBLE);
}
}
}
}
}
}