package com.emop.client.widget;
import java.util.ArrayList;
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.ScrollView;
import android.widget.TextView;
import com.emop.client.BuildConfig;
import com.emop.client.R;
import com.emop.client.widget.item.FlowView;
import com.emop.client.widget.item.FlowViewHandler;
public class WaterFallView extends ScrollView {
private RotateAnimation mFlipAnimation;
private RotateAnimation mReverseFlipAnimation;
public static final String TAG = "LazyScrollView";
// 图片显示相关的图片
public int columnCount = 3;
public int itemWidth;
//public int pageCount = 10;
//public int loadedCount = 0;
public ArrayList<LinearLayout> waterfall_items;
public Handler handler;
public Handler itemHandler;
public WaterFallUtils waterFallUtils;
public View view;
public ViewGroup waterfallContainer;
public WaterFallOption options = null;
public int current_page = 0;// 当前页数
public int pictureTotalCount = 1000;
public int[] topIndex;
public int[] bottomIndex;
public int[] lineIndex; //每列一共有多少个图片。
public int[] column_height;// 每列的高度
public SparseArray<String> pins;
public int loaded_count = 0;// 已加载数量
public SparseIntArray[] pin_mark; //每列里面,每行所对应的高度。
public SparseArray<FlowView> iviews;
public WaterFallView(Context context) {
super(context);
}
public WaterFallView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public WaterFallView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
onScrollListener.onAutoScroll(l, t, oldl, oldt);
waterFallUtils.autoReload(l, t, oldl, oldt);
}
public void setOptions() {
}
/**
* 显示开始加载栏。
*/
public void showHeadLoader(){
if(this.options.headLoader != null){
ProgressBar bar = (ProgressBar)this.options.headLoader.findViewById(R.id.loading_bar);
bar.setIndeterminate(true);
this.refreshManager.flag.setVisibility(GONE);
options.headLoader.setVisibility(VISIBLE);
}
}
public void load(){
this.refreshManager.onRefreshing();
}
public boolean isLoading(){
return refreshManager.isLoading;
}
public boolean isHeadLoading(){
if(options.headLoader != null){
return options.headLoader.getVisibility() == VISIBLE;
}else {
return false;
}
}
//private
public void addImage(String filename, int rowIndex, int id, float price) {
addImage(filename, rowIndex, id, price, 0);
}
public void addImage(String filename, int rowIndex, int id, float price, float rectRate) {
this.loaded_count++;
final FlowView item = new FlowView(getContext());
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT);
lp.setMargins(options.itemMarginSize,
options.itemMarginSize,
options.itemMarginSize,
options.itemMarginSize);
item.setLayoutParams(lp);
item.setPadding(0, 0, 0, 0);
item.setRowIndex(rowIndex);
item.setId(id);
item.setViewHandler(itemHandler);
item.setFileName(filename);
item.setItemWidth(options.itemWidth);
item.fontSize = options.itemFontSize;
item.topMargin = options.itemMarginSize;
item.bottomMargin = options.itemMarginSize;
item.price = price;
item.rectRate = rectRate;
this.handler.post(new Runnable(){
public void run(){
item.LoadImage();
}
});
//Log.d("xxx", "added image count:" + this.loaded_count);
}
private void init() {
this.setOnTouchListener(onTouchListener);
column_height = new int[columnCount];
iviews = new SparseArray<FlowView>();
pins = new SparseArray<String>();
pin_mark = new SparseIntArray[columnCount];
this.lineIndex = new int[columnCount];
this.bottomIndex = new int[columnCount];
this.topIndex = new int[columnCount];
for (int i = 0; i < columnCount; i++) {
lineIndex[i] = -1;
bottomIndex[i] = -1;
}
// 初始化话waterfall_items 用于加载图片
waterfall_items = new ArrayList<LinearLayout>();
for (int i = 0; i < columnCount; i++) {
LinearLayout itemLayout = new LinearLayout(getContext());
LinearLayout.LayoutParams itemParam = new LinearLayout.LayoutParams(
itemWidth, LayoutParams.WRAP_CONTENT);
itemLayout.setPadding(0, 0, 0, 0);
itemLayout.setOrientation(LinearLayout.VERTICAL);
itemLayout.setLayoutParams(itemParam);
waterfall_items.add(itemLayout);
// 用于加载单列的显示
waterfallContainer.addView(itemLayout);
pin_mark[i] = new SparseIntArray();
}
//this.setv
//setVerticalScrollBarEnabled(true);
/*
if (isVerticalFadingEdgeEnabled()) {
}*/
}
/**
* 初始化两个动画运行方式。
*/
private void initAnimation(){
//动画变化的开始状态,和结束状态。
mFlipAnimation = new RotateAnimation(0, 180,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
//动画运行速度。 直线平均速度。
mFlipAnimation.setInterpolator(new LinearInterpolator());
//动画的运行时间。
mFlipAnimation.setDuration(250);
//动画结束后,是否保留结束状态。
mFlipAnimation.setFillAfter(true);
mReverseFlipAnimation = new RotateAnimation(180, 0,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
mReverseFlipAnimation.setInterpolator(new LinearInterpolator());
mReverseFlipAnimation.setDuration(250);
mReverseFlipAnimation.setFillAfter(true);
}
/**
* 获得参考的View,主要是为了获得它的MeasuredHeight,然后和滚动条的ScrollY+getHeight作比较。
*/
public void commitWaterFall(WaterFallOption options) {
this.options = options;
this.columnCount = options.column_count;
this.itemWidth = options.itemWidth;
this.waterfallContainer = options.waterFallContainer;
// 一共加载的图片
this.pictureTotalCount = options.pictureTotalCount;
waterFallUtils = new WaterFallUtils(this);
this.view = getChildAt(0);
if (view != null) {
handler = new WaterFallHandler(view, this, (int)(itemWidth * 2));
init();
}
initAnimation();
refreshManager = new RefreshManager();
itemHandler = new FlowViewHandler(this);
}
OnTouchListener onTouchListener = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d(TAG,
"ACTION_DOWN" + "Y->" + event.getY() + "X->"
+ event.getX());
refreshManager.actionDown(event);
break;
case MotionEvent.ACTION_UP:
if (view != null && onScrollListener != null) {
handler.sendMessageDelayed(
handler.obtainMessage(Constants.HANDLER_WHAT),
Constants.MESSAGE_DELAY);
}
refreshManager.actionUp(event);
break;
case MotionEvent.ACTION_MOVE:
refreshManager.actionMove(event);
break;
default:
break;
}
return false;
}
};
/**
* 定义接口
*
* @author admin
*
*/
public interface OnScrollListener {
void onBottom();
void onTop();
void onScroll();
void onAutoScroll(int l, int t, int oldl, int oldt);
}
public interface OnRefreshListener {
void onRefresh();
}
protected OnScrollListener onScrollListener;
protected OnRefreshListener onRefreshListener;
protected RefreshManager refreshManager = null;
public void setOnScrollListener(OnScrollListener onScrollListener) {
this.onScrollListener = onScrollListener;
}
public void setOnRefrreshListener(OnRefreshListener onRefreshListener) {
this.onRefreshListener = onRefreshListener;
}
public void deleteItems(FlowView v) {
int rowIndex = v.getRowIndex();
int columnIndex = v.getColumnIndex();
int height = v.getHeight();
waterfall_items.get(columnIndex).removeView(v);
this.pin_mark[columnIndex].removeAt(rowIndex);
for (int i = rowIndex; i < pin_mark[columnIndex].size(); i++) {
this.pin_mark[columnIndex].put(i,
this.pin_mark[columnIndex].get(i + 1) - height);
this.pin_mark[columnIndex].removeAt(i + 1);
((FlowView) this.waterfall_items.get(columnIndex).getChildAt(i))
.setRowIndex(i);
}
lineIndex[columnIndex]--;
column_height[columnIndex] -= height;
if (this.bottomIndex[columnIndex] > this.lineIndex[columnIndex]) {
bottomIndex[columnIndex]--;
}
}
@Override
public void fling(int velocityY) {
super.fling(velocityY / 2);
//Debug("velocity-->" + velocityY);
}
public static void Debug(String message) {
if (BuildConfig.DEBUG) {
Log.d(TAG, message);
}
}
class RefreshManager{
static final int NO_START_PULL = 1;
static final int START_TO_PULL = 2;
static final int RELEASE_TO_REFRESH = 3;
static final int REFRESHING = 4;
public boolean isLoading = false;
//开始下拉的位置。
private float startPullMotionY = 0;
private int mState = 1;
private View loader = null; //options.headLoader;
private ProgressBar loading = null; //options.headLoader;
private ImageView flag = null; //options.headLoader;
private TextView info = null;
private int mRefreshViewHeight = 0;
private int pullHeight = 0;
private int oldLoaderPadding = 0;
private int downMotionY = 0;
public RefreshManager(){
loader = options.headLoader;
flag = (ImageView)loader.findViewById(R.id.refresh_flag);
loading = (ProgressBar)loader.findViewById(R.id.loading_bar);
info = (TextView)loader.findViewById(R.id.loading_info);
}
public void actionDown(MotionEvent event){
downMotionY = (int)event.getY();
}
public void actionUp(MotionEvent event){
if (!isVerticalScrollBarEnabled()) {
setVerticalScrollBarEnabled(true);
}
if(mState != NO_START_PULL){
loader.setPadding(
loader.getPaddingLeft(),
oldLoaderPadding,
loader.getPaddingRight(),
loader.getPaddingBottom());
if(mState == RELEASE_TO_REFRESH){
onRefreshing();
}else {
onReset();
}
}
mState = NO_START_PULL;
downMotionY = 0;
}
public void actionMove(MotionEvent event){
if(isLoading) return;
if(downMotionY == 0){
downMotionY = (int)event.getY();
return;
}
float prePull = event.getY() - downMotionY;
Log.d("tag", "pre pull size:" + prePull + ", downMotionY:" + downMotionY + ", now:" + event.getY());
if(getScrollY() <= 0 && mState == NO_START_PULL && prePull > 30){
mState = START_TO_PULL;
pullHeight = 0;
startPullMotionY = 0; //event.getY();
if(mRefreshViewHeight == 0){
mRefreshViewHeight = loader.getMeasuredHeight();
oldLoaderPadding = loader.getPaddingTop();
}
onStart();
}else if(mState == START_TO_PULL || mState == RELEASE_TO_REFRESH){
applyHeaderPadding(event);
}else {
Log.d("tag", "scroll y:" + getScrollY() + ", st:" + mState);
}
if(mState == START_TO_PULL && pullHeight > mRefreshViewHeight * 1){
mState = RELEASE_TO_REFRESH;
this.onReleaseToRefresh();
} else if(mState == RELEASE_TO_REFRESH && pullHeight > 0 && pullHeight < mRefreshViewHeight * 1){
mState = START_TO_PULL;
this.onStartToPull();
}
}
private void onReset(){
loader.setVisibility(GONE);
//flag.clearAnimation();
//flag.setImageResource(R.drawable.ic_pulltorefresh_arrow);
scrollTo(0, 0);
}
private void onRefreshing(){
flag.setVisibility(GONE);
loading.setVisibility(VISIBLE);
info.setText("努力加载中");
Log.d(com.emop.client.Constants.TAG_EMOP, "on refreshing...");
if(onRefreshListener != null){
new Thread(){
public void run(){
isLoading = true;
try{
onRefreshListener.onRefresh();
}finally{
isLoading = false;
}
handler.post(new Runnable() {
@Override
public void run() {
onReset();
}});
}
}.start();
}else {
Log.e(com.emop.client.Constants.TAG_EMOP, "no listener....");
}
}
private void onStart(){
loading.setVisibility(GONE);
flag.setVisibility(VISIBLE);
flag.clearAnimation();
flag.setImageResource(R.drawable.ic_pulltorefresh_arrow);
info.setText("下拉刷新");
loader.setVisibility(VISIBLE);
if (isVerticalFadingEdgeEnabled()) {
setVerticalScrollBarEnabled(false);
}
}
private void onReleaseToRefresh(){
info.setText("松开即可刷新");
flag.clearAnimation();
flag.startAnimation(mFlipAnimation);
}
private void onStartToPull(){
info.setText("下拉刷新");
flag.clearAnimation();
flag.startAnimation(mReverseFlipAnimation);
}
private void applyHeaderPadding(MotionEvent ev) {
int historicalY = (int) ev.getY();
if(startPullMotionY == 0){
startPullMotionY = historicalY;
}
pullHeight = (int) (historicalY - startPullMotionY);
//Log.d("xxx", "historicalY:" + historicalY + ",pull height:" + pullHeight + ", loader height:" + mRefreshViewHeight);
//pullHeight = (int) ((event.getY() - startPullMotionY));
loader.setPadding(
loader.getPaddingLeft(),
pullHeight + oldLoaderPadding,
loader.getPaddingRight(),
loader.getPaddingBottom());
}
}
}