package com.example.administrator.cookman.ui.component.magicindicator.buildins.commonnavigator;
import android.content.Context;
import android.database.DataSetObserver;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import com.example.administrator.cookman.R;
import com.example.administrator.cookman.ui.component.magicindicator.NavigatorHelper;
import com.example.administrator.cookman.ui.component.magicindicator.ScrollState;
import com.example.administrator.cookman.ui.component.magicindicator.abs.IPagerNavigator;
import com.example.administrator.cookman.ui.component.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter;
import com.example.administrator.cookman.ui.component.magicindicator.buildins.commonnavigator.abs.IMeasurablePagerTitleView;
import com.example.administrator.cookman.ui.component.magicindicator.buildins.commonnavigator.abs.IPagerIndicator;
import com.example.administrator.cookman.ui.component.magicindicator.buildins.commonnavigator.abs.IPagerTitleView;
import com.example.administrator.cookman.ui.component.magicindicator.buildins.commonnavigator.model.PositionData;
import java.util.ArrayList;
import java.util.List;
/**
* 通用的ViewPager指示器,包含PagerTitle和PagerIndicator
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public class CommonNavigator extends FrameLayout implements IPagerNavigator, NavigatorHelper.OnNavigatorScrollListener {
private HorizontalScrollView mScrollView;
private LinearLayout mTitleContainer;
private LinearLayout mIndicatorContainer;
private IPagerIndicator mIndicator;
private CommonNavigatorAdapter mAdapter;
private NavigatorHelper mNavigatorHelper;
/**
* 提供给外部的参数配置
*/
/****************************************************/
private boolean mAdjustMode; // 自适应模式,适用于数目固定的、少量的title
private boolean mEnablePivotScroll; // 启动中心点滚动
private float mScrollPivotX = 0.5f; // 滚动中心点 0.0f - 1.0f
private boolean mSmoothScroll = true; // 是否平滑滚动,适用于 !mAdjustMode && !mFollowTouch
private boolean mFollowTouch = true; // 是否手指跟随滚动
private int mRightPadding;
private int mLeftPadding;
private boolean mIndicatorOnTop; // 指示器是否在title上方,默认为下方
private boolean mSkimOver; // 跨多页切换时,中间页是否显示 "掠过" 效果
private boolean mReselectWhenLayout = true; // PositionData准备好时,是否重新选中当前页,为true可保证在极端情况下指示器状态正确
/****************************************************/
// 保存每个title的位置信息,为扩展indicator提供保障
private List<PositionData> mPositionDataList = new ArrayList<PositionData>();
private DataSetObserver mObserver = new DataSetObserver() {
@Override
public void onChanged() {
mNavigatorHelper.setTotalCount(mAdapter.getCount()); // 如果使用helper,应始终保证helper中的totalCount为最新
init();
}
@Override
public void onInvalidated() {
// 没什么用,暂不做处理
}
};
public CommonNavigator(Context context) {
super(context);
mNavigatorHelper = new NavigatorHelper();
mNavigatorHelper.setNavigatorScrollListener(this);
}
@Override
public void notifyDataSetChanged() {
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
}
public boolean isAdjustMode() {
return mAdjustMode;
}
public void setAdjustMode(boolean is) {
mAdjustMode = is;
}
public CommonNavigatorAdapter getAdapter() {
return mAdapter;
}
public void setAdapter(CommonNavigatorAdapter adapter) {
if (mAdapter == adapter) {
return;
}
if (mAdapter != null) {
mAdapter.unregisterDataSetObserver(mObserver);
}
mAdapter = adapter;
if (mAdapter != null) {
mAdapter.registerDataSetObserver(mObserver);
mAdapter.notifyDataSetChanged(); // adapter改变时,应该重新init
} else {
mNavigatorHelper.setTotalCount(0);
init();
}
}
private void init() {
removeAllViews();
View root;
if (mAdjustMode) {
root = LayoutInflater.from(getContext()).inflate(R.layout.pager_navigator_layout_no_scroll, this);
} else {
root = LayoutInflater.from(getContext()).inflate(R.layout.pager_navigator_layout, this);
}
mScrollView = (HorizontalScrollView) root.findViewById(R.id.scroll_view); // mAdjustMode为true时,mScrollView为null
mTitleContainer = (LinearLayout) root.findViewById(R.id.title_container);
mTitleContainer.setPadding(mLeftPadding, 0, mRightPadding, 0);
mIndicatorContainer = (LinearLayout) root.findViewById(R.id.indicator_container);
if (mIndicatorOnTop) {
mIndicatorContainer.getParent().bringChildToFront(mIndicatorContainer);
}
initTitlesAndIndicator();
}
/**
* 初始化title和indicator
*/
private void initTitlesAndIndicator() {
for (int i = 0, j = mNavigatorHelper.getTotalCount(); i < j; i++) {
IPagerTitleView v = mAdapter.getTitleView(getContext(), i);
if (v instanceof View) {
View view = (View) v;
LinearLayout.LayoutParams lp;
if (mAdjustMode) {
lp = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT);
lp.weight = mAdapter.getTitleWeight(getContext(), i);
} else {
lp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
}
mTitleContainer.addView(view, lp);
}
}
if (mAdapter != null) {
mIndicator = mAdapter.getIndicator(getContext());
if (mIndicator instanceof View) {
LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
mIndicatorContainer.addView((View) mIndicator, lp);
}
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (mAdapter != null) {
preparePositionData();
if (mIndicator != null) {
mIndicator.onPositionDataProvide(mPositionDataList);
}
if (mReselectWhenLayout && mNavigatorHelper.getScrollState() == ScrollState.SCROLL_STATE_IDLE) {
onPageSelected(mNavigatorHelper.getCurrentIndex());
onPageScrolled(mNavigatorHelper.getCurrentIndex(), 0.0f, 0);
}
}
}
/**
* 获取title的位置信息,为打造不同的指示器、各种效果提供可能
*/
private void preparePositionData() {
mPositionDataList.clear();
for (int i = 0, j = mNavigatorHelper.getTotalCount(); i < j; i++) {
PositionData data = new PositionData();
View v = mTitleContainer.getChildAt(i);
if (v != null) {
data.mLeft = v.getLeft();
data.mTop = v.getTop();
data.mRight = v.getRight();
data.mBottom = v.getBottom();
if (v instanceof IMeasurablePagerTitleView) {
IMeasurablePagerTitleView view = (IMeasurablePagerTitleView) v;
data.mContentLeft = view.getContentLeft();
data.mContentTop = view.getContentTop();
data.mContentRight = view.getContentRight();
data.mContentBottom = view.getContentBottom();
} else {
data.mContentLeft = data.mLeft;
data.mContentTop = data.mTop;
data.mContentRight = data.mRight;
data.mContentBottom = data.mBottom;
}
}
mPositionDataList.add(data);
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (mAdapter != null) {
mNavigatorHelper.onPageScrolled(position, positionOffset, positionOffsetPixels);
if (mIndicator != null) {
mIndicator.onPageScrolled(position, positionOffset, positionOffsetPixels);
}
// 手指跟随滚动
if (mScrollView != null && mPositionDataList.size() > 0) {
if (mFollowTouch) {
int currentPosition = Math.min(mPositionDataList.size() - 1, position);
int nextPosition = Math.min(mPositionDataList.size() - 1, position + 1);
PositionData current = mPositionDataList.get(currentPosition);
PositionData next = mPositionDataList.get(nextPosition);
float scrollTo = current.horizontalCenter() - mScrollView.getWidth() * mScrollPivotX;
float nextScrollTo = next.horizontalCenter() - mScrollView.getWidth() * mScrollPivotX;
mScrollView.scrollTo((int) (scrollTo + (nextScrollTo - scrollTo) * positionOffset), 0);
} else if (!mEnablePivotScroll) {
// TODO 实现待选中项完全显示出来
}
}
}
}
public float getScrollPivotX() {
return mScrollPivotX;
}
public void setScrollPivotX(float scrollPivotX) {
mScrollPivotX = scrollPivotX;
}
@Override
public void onPageSelected(int position) {
if (mAdapter != null) {
mNavigatorHelper.onPageSelected(position);
if (mIndicator != null) {
mIndicator.onPageSelected(position);
}
}
}
@Override
public void onPageScrollStateChanged(int state) {
if (mAdapter != null) {
mNavigatorHelper.onPageScrollStateChanged(state);
if (mIndicator != null) {
mIndicator.onPageScrollStateChanged(state);
}
}
}
@Override
public void onAttachToMagicIndicator() {
init(); // 将初始化延迟到这里
}
@Override
public void onDetachFromMagicIndicator() {
}
public IPagerIndicator getPagerIndicator() {
return mIndicator;
}
public boolean isEnablePivotScroll() {
return mEnablePivotScroll;
}
public void setEnablePivotScroll(boolean is) {
mEnablePivotScroll = is;
}
@Override
public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) {
if (mTitleContainer == null) {
return;
}
View v = mTitleContainer.getChildAt(index);
if (v instanceof IPagerTitleView) {
((IPagerTitleView) v).onEnter(index, totalCount, enterPercent, leftToRight);
}
}
@Override
public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) {
if (mTitleContainer == null) {
return;
}
View v = mTitleContainer.getChildAt(index);
if (v instanceof IPagerTitleView) {
((IPagerTitleView) v).onLeave(index, totalCount, leavePercent, leftToRight);
}
}
public boolean isSmoothScroll() {
return mSmoothScroll;
}
public void setSmoothScroll(boolean smoothScroll) {
mSmoothScroll = smoothScroll;
}
public boolean isFollowTouch() {
return mFollowTouch;
}
public void setFollowTouch(boolean followTouch) {
mFollowTouch = followTouch;
}
public boolean isSkimOver() {
return mSkimOver;
}
public void setSkimOver(boolean skimOver) {
mSkimOver = skimOver;
mNavigatorHelper.setSkimOver(skimOver);
}
@Override
public void onSelected(int index, int totalCount) {
if (mTitleContainer == null) {
return;
}
View v = mTitleContainer.getChildAt(index);
if (v instanceof IPagerTitleView) {
((IPagerTitleView) v).onSelected(index, totalCount);
}
if (!mAdjustMode && !mFollowTouch && mScrollView != null && mPositionDataList.size() > 0) {
int currentIndex = Math.min(mPositionDataList.size() - 1, index);
PositionData current = mPositionDataList.get(currentIndex);
if (mEnablePivotScroll) {
float scrollTo = current.horizontalCenter() - mScrollView.getWidth() * mScrollPivotX;
if (mSmoothScroll) {
mScrollView.smoothScrollTo((int) (scrollTo), 0);
} else {
mScrollView.scrollTo((int) (scrollTo), 0);
}
} else {
// 如果当前项被部分遮挡,则滚动显示完全
if (mScrollView.getScrollX() > current.mLeft) {
if (mSmoothScroll) {
mScrollView.smoothScrollTo(current.mLeft, 0);
} else {
mScrollView.scrollTo(current.mLeft, 0);
}
} else if (mScrollView.getScrollX() + getWidth() < current.mRight) {
if (mSmoothScroll) {
mScrollView.smoothScrollTo(current.mRight - getWidth(), 0);
} else {
mScrollView.scrollTo(current.mRight - getWidth(), 0);
}
}
}
}
}
@Override
public void onDeselected(int index, int totalCount) {
if (mTitleContainer == null) {
return;
}
View v = mTitleContainer.getChildAt(index);
if (v instanceof IPagerTitleView) {
((IPagerTitleView) v).onDeselected(index, totalCount);
}
}
public IPagerTitleView getPagerTitleView(int index) {
if (mTitleContainer == null) {
return null;
}
return (IPagerTitleView) mTitleContainer.getChildAt(index);
}
public LinearLayout getTitleContainer() {
return mTitleContainer;
}
public int getRightPadding() {
return mRightPadding;
}
public void setRightPadding(int rightPadding) {
mRightPadding = rightPadding;
}
public int getLeftPadding() {
return mLeftPadding;
}
public void setLeftPadding(int leftPadding) {
mLeftPadding = leftPadding;
}
public boolean isIndicatorOnTop() {
return mIndicatorOnTop;
}
public void setIndicatorOnTop(boolean indicatorOnTop) {
mIndicatorOnTop = indicatorOnTop;
}
public boolean isReselectWhenLayout() {
return mReselectWhenLayout;
}
public void setReselectWhenLayout(boolean reselectWhenLayout) {
mReselectWhenLayout = reselectWhenLayout;
}
}