package com.wasu.cs.widget; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.ScrollView; import com.wasu.module.log.WLog; import cn.com.wasu.main.R; /** * @author danxingxi created on 2016.6.7 * 中国蓝 CS 模板 最外层容器控件 */ public class ListScrollView extends ScrollView implements OnClickListener { /** * Item点击的回调 */ private OnItemClickListener mListener; private Adapter mAdapter; /** * 屏幕的高度 */ private int mScreenHeight; /** * 每个条目的高度 */ private int mItemHeight = getResources().getDimensionPixelOffset(R.dimen.d_260dp); private ViewGroup mContainer; /** * 条目总数 */ private int mItemCount; private boolean flag = false; private final String TAG="ListScrollView"; /** * 适配器 * @author zhy * */ public static abstract class Adapter { public abstract View getView(ListScrollView parent, int pos); public abstract int getCount(); } /** * 点击的回调 */ public interface OnItemClickListener { void onItemClick(int pos, View view); } public ListScrollView(Context context, AttributeSet attrs) { super(context, attrs); // 计算屏幕的高度 WindowManager wm = (WindowManager) context .getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); mScreenHeight = outMetrics.heightPixels; mScreenHeight -= getStatusHeight(context); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // notifyDataSetChanged(); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } public View getItemByIndex(int index){ return mContainer.getChildAt(index); } public void addChildView(View view) { mContainer.addView(view); } /** * 在容器末尾添加一个Item * @param i */ private void addChildView(int i) { View item = mAdapter.getView(this, i); ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, mItemHeight); item.setLayoutParams(lp);//设置参数 item.setTag(i);//设置Tag item.setOnClickListener(this);//添加事件 mContainer.addView(item); } /** * 在容器指定位置添加一个Item * @param i * @param index */ private void addChildView(int i, int index) { View item = mAdapter.getView(this, i); ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, mItemHeight); item.setLayoutParams(lp); item.setTag(i); item.setOnClickListener(this); mContainer.addView(item, index); } /* @Override public boolean onTouchEvent(MotionEvent ev) { flag = true; int action = ev.getAction(); int scrollY = getScrollY(); switch (action) { case MotionEvent.ACTION_MOVE: Log.e("TAG", "scrollY = " + scrollY); // 表示此时ScrollView的顶部已经达到屏幕顶部 if (scrollY == 0) { addChildToFirst(); } // ScrollView的顶部已经到达屏幕底部 if (Math.abs(scrollY - mItemHeight) <= mItemCount) { addChildToLast(); } break; case MotionEvent.ACTION_UP: checkForReset(); return true; default: break; } return super.onTouchEvent(ev); } */ /** * 在底部添加一个View,并移除第一个View */ private void addChildToLast() { Log.e("TAG", "addChildToLast"); int pos = (Integer) mContainer.getChildAt(1).getTag(); addChildView(pos); mContainer.removeViewAt(0); this.scrollTo(0, 0); } /** * 在顶部添加一个View,并移除最后一个View */ protected void addChildToFirst() { Log.e("TAG", "addChildToFirst"); int pos = (Integer) mContainer.getChildAt(mItemCount - 1).getTag(); addChildView(pos, 0); mContainer.removeViewAt(mContainer.getChildCount() - 1); this.scrollTo(0, mItemHeight); } /** * 检查当前getScrollY,显示完成Item,或者收缩此Item */ private void checkForReset() { int val = getScrollY() % mItemHeight; if (val >= mItemHeight / 2) { smoothScrollTo(0, mItemHeight); } else { smoothScrollTo(0, 0); } } /** * 获得状态栏的高度 * * @param context * @return */ public int getStatusHeight(Context context) { int statusHeight = -1; try { Class clazz = Class.forName("com.android.internal.R$dimen"); Object object = clazz.newInstance(); int height = Integer.parseInt(clazz.getField("status_bar_height") .get(object).toString()); statusHeight = context.getResources().getDimensionPixelSize(height); } catch (Exception e) { e.printStackTrace(); } return statusHeight; } public void setAdapter(Adapter mAdapter) { WLog.d("danxx" ,"setAdapter"); this.mAdapter = mAdapter; notifyDataSetChanged(); } /** * 设置item的高度 默认是280 * @param height */ public void setmItemHeight(int height){ mItemHeight = height; } private void notifyDataSetChanged(){ WLog.d("danxx" ,"notifyDataSetChanged"); //防止多次调用 if (!flag) { //根据Adapter的方法,为容器添加Item if (mAdapter != null) { mContainer = (ViewGroup) findViewById(R.id.layoutBody); mItemCount = mAdapter.getCount(); //mItemHeight = mScreenHeight / mItemCount; WLog.d(TAG,"ItemHeight="+mItemHeight); //mItemHeight = 300; mContainer.removeAllViews(); for (int i = 0,count =mAdapter.getCount(); i < count ; i++) { addChildView(i); } } } } public void setOnItemClickListener(OnItemClickListener mListener) { this.mListener = mListener; } @Override public void onClick(View v) { int pos = (Integer) v.getTag(); if (mListener != null) { mListener.onItemClick(pos, v); } } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); flag = true; } @Override protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) { if (getChildCount() == 0) return 0; int height = getHeight(); int screenTop = getScrollY(); int screenBottom = screenTop + height; /**增加提前滚动距离**/ int fadingEdge = getVerticalFadingEdgeLength()+this.getResources().getDimensionPixelSize( cn.com.wasu.main.R.dimen.d_200dp); // leave room for top fading edge as long as rect isn't at very top if (rect.top > 0) { screenTop += fadingEdge; } // leave room for bottom fading edge as long as rect isn't at very bottom if (rect.bottom < getChildAt(0).getHeight()) { screenBottom -= fadingEdge; } int scrollYDelta = 0; if (rect.bottom > screenBottom && rect.top > screenTop) { // need to move down to get it in view: move down just enough so // that the entire rectangle is in view (or at least the first // screen size chunk). if (rect.height() > height) { // just enough to get screen size chunk on scrollYDelta += (rect.top - screenTop); } else { // get entire rect at bottom of screen scrollYDelta += (rect.bottom - screenBottom); } // make sure we aren't scrolling beyond the end of our content int bottom = getChildAt(0).getBottom(); int distanceToBottom = bottom - screenBottom; scrollYDelta = Math.min(scrollYDelta, distanceToBottom); } else if (rect.top < screenTop && rect.bottom < screenBottom) { // need to move up to get it in view: move up just enough so that // entire rectangle is in view (or at least the first screen // size chunk of it). if (rect.height() > height) { // screen size chunk scrollYDelta -= (screenBottom - rect.bottom); } else { // entire rect at top scrollYDelta -= (screenTop - rect.top); } // make sure we aren't scrolling any further than the top our content scrollYDelta = Math.max(scrollYDelta, -getScrollY()); } return scrollYDelta; } }