package com.geekband.luminous.homework.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Adapter;
import android.widget.AdapterView;
import java.util.LinkedList;
/**
* A customize listView
* Created by hisashieki on 15/8/14.
*/
public class MyListViewX extends AdapterView {
public static final String TAG = "MyListViewX";
int mTouchStartY;
int mListTopStart;
/** The top of this ListView */
int mListTop;
/** The offset from the top of the currently first visible item to the top of the first item */
int mListTopOffset;
/** adapter positions of the first currently visible views */
int mFirstItemPosition;
/** adapter positions of the last currently visible views */
int mLastItemPosition;
/** The adapter with all the data */
private Adapter mAdapter;
/** the cache of Views */
private LinkedList<View> cacheViews = new LinkedList<>();
public MyListViewX(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public Adapter getAdapter() {
return mAdapter;
}
@Override
public void setAdapter(Adapter adapter) {
mAdapter = adapter;
}
@Override
public View getSelectedView() {
throw new UnsupportedOperationException("Not supported");
}
@Override
public void setSelection(int position) {
throw new UnsupportedOperationException("Not supported");
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (mAdapter == null) {
return;
}
if (getChildCount() == 0) {
mLastItemPosition = -1;
fillListDown(0, 0);
} else {
int offset = mListTop;
removeNonVisibleViews(offset);
fillList(offset);
}
positionItems();
}
private void fillListDown(int bottomEdge, int offset) {
Log.e(TAG, "fillListDown times+1");
while (bottomEdge < getHeight() && mLastItemPosition + 1 < mAdapter.getCount()) {
View newBottomChild = mAdapter.getView(mLastItemPosition + 1, null, this);
addAndMeasureChild(newBottomChild);
bottomEdge += newBottomChild.getMeasuredHeight();
mLastItemPosition++;
Log.d(TAG, "fillListDown " + mLastItemPosition + "bottomEdge: " + bottomEdge);
}
}
private void fillListUp(int topEdge, int offset) {
}
private void fillList(int offset) {
final int bottomEdge = getChildAt(getChildCount() - 1).getBottom();
fillListDown(bottomEdge, offset);
final int topEdge = getChildAt(0).getTop();
fillListUp(topEdge, offset);
}
private void addAndMeasureChild(View child) {
LayoutParams params = child.getLayoutParams();
if (params == null) {
params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}
addViewInLayout(child, -1, params, true);
int itemWidth = getWidth();
child.measure(MeasureSpec.EXACTLY | itemWidth, MeasureSpec.EXACTLY | itemWidth);
}
/**
* @param offset Offset of the visible area
*/
private void removeNonVisibleViews(int offset) {
int childCount = getChildCount();
if (mLastItemPosition != mAdapter.getCount() - 1 && childCount > 1) {
View firstChild = getChildAt(0);
if (firstChild.getBottom() < 0) {
removeViewInLayout(firstChild);
cacheViews.addLast(firstChild);
}
}
}
private void positionItems() {
int top = +mListTopOffset + mListTop;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
int width = child.getMeasuredWidth();
int height = child.getMeasuredHeight();
int left = (getWidth() - width) / 2;
child.layout(left, top, left + width, top + height);
top += height;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (getChildCount() == 0) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mTouchStartY = (int) event.getY();
mListTopStart = getChildAt(0).getTop();
break;
case MotionEvent.ACTION_MOVE:
int scrolledDistance = (int) event.getY() - mTouchStartY;
mListTop = mListTopStart + scrolledDistance;
requestLayout();
break;
default:
break;
}
return true;
}
}