ViewGroup重写——滚动页面容器
来源:互联网 发布:js获取input file路径 编辑:程序博客网 时间:2024/06/04 19:27
滚动页面容器
- 子控件水平排列
- 子控件之间可以相互滚动切换
- 松开手指可以自动前后切换
比如像ViewPager一样,跟随手势滚动,松开手指可以自动判断滚动到上一个还是下一个。如图。
重写onLayout指定子控件的位置,重写onTouchEvent处理触摸事件,实现onGestureListener接口,处理scroll事件。
onLayout的规则就很简单了,高不变,宽按照个数叠加就可以了
getChildAt(i).layout(getWidth() * i, 0, getWidth() * (i + 1), getHeight());onTouchEvent中使用,GestureListener 的onTouchEvent(event)就可以自动处理好多事件,比如onDown,onScroll,onLongPress等。
松开手指用一个帮助类来计算时间差,并不断的调用computeScroll来实现自动缓慢滚动。
容器类PagedView
public class PagedView extends ViewGroup implements OnGestureListener {private final String TAG = "PagedView";private final boolean DEBUG = false;private int mCurrentIndex;private float mDownX;private DistanceHelper mDistanceHelper;GestureDetector detector = new GestureDetector(getContext(), this);public PagedView(Context context) {this(context, null);}public PagedView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public PagedView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);mDistanceHelper = new DistanceHelper(getContext());}protected void onLayout(boolean changed, int l, int t, int r, int b) {int count = getChildCount();for (int i = 0; i < count; i++) {getChildAt(i).layout(getWidth() * i, 0, getWidth() * (i + 1), getHeight());}}@Overridepublic boolean onTouchEvent(MotionEvent event) {detector.onTouchEvent(event);//调用之后会自动处理手势switch (event.getAction()) {case MotionEvent.ACTION_UP:// Log.i(TAG, "up");int tmpId = 0;if ((event.getX() - mDownX) > getWidth() / 2) {tmpId = mCurrentIndex - 1;} else if (mDownX - event.getX() > getWidth() / 2) {tmpId = mCurrentIndex + 1;} else {tmpId = mCurrentIndex;}int childCount = getChildCount();mCurrentIndex = tmpId < 0 ? 0 : (tmpId > childCount - 1 ? childCount - 1 : tmpId);// scrollTo(mCurrentIndex * getWidth(), 0);moveTo();break;default:break;}return true;}private void moveTo() {int distance = mCurrentIndex * getWidth() - getScrollX();mDistanceHelper.startScroll(getScrollX(), 0, distance, 0);invalidate();}@Overridepublic boolean onDown(MotionEvent e) {if (DEBUG)Log.i(TAG, "onDown");mDownX = e.getX();return false;}@Overridepublic void onShowPress(MotionEvent e) {if (DEBUG)Log.i(TAG, "onShowPress");}@Overridepublic boolean onSingleTapUp(MotionEvent e) {if (DEBUG)Log.i(TAG, "onSingleTapUp");return false;}@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {if (DEBUG)Log.i(TAG, "onScroll");// Log.i(TAG, "onScroll=" + distanceX + "," + distanceY);scrollBy((int) distanceX, 0);return false;}public void onLongPress(MotionEvent e) {if (DEBUG)Log.i(TAG, "onLongPress");}public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {if (DEBUG)Log.i(TAG, "onFling");Log.i("Gmw", velocityX + "");return false;}public void scrollNext() {}public void scrollLast() {}public void setCurrent(int index) {mCurrentIndex = index;scrollTo(index * getWidth(), 0);invalidate();// requestLayout();}public int getCurrent() {return mCurrentIndex;}@Overridepublic void computeScroll() {Log.i("Gmw", "computeScroll");if (!mDistanceHelper.computeScrollOffset()) {int newX = (int) mDistanceHelper.getCurrentX();scrollTo(newX, 0);invalidate();}// super.computeScroll();}}
public class DistanceHelper {private int startX;private int startY;private int distanceX;private int distanceY;private long startTime;private boolean isFinish;private long duration;private long currentX;private long currentY;public long getCurrentX() {return currentX;}public void setCurrentX(long currentX) {this.currentX = currentX;}public DistanceHelper(Context context) {isFinish = false;}public void startScroll(int startX, int startY, int distanceX, int distanceY) {this.startX = startX;this.startY = startY;this.distanceX = distanceX;this.distanceY = distanceY;this.startTime = SystemClock.uptimeMillis();this.duration = 200;this.isFinish = false;}public boolean computeScrollOffset() {if (isFinish) {return isFinish;}long passTime = SystemClock.uptimeMillis() - startTime;if (passTime < duration) {currentX = startX + distanceX * passTime / duration;currentY = startY + distanceX * passTime / duration;} else {currentX = startX + distanceX;currentY = startY + distanceY;isFinish = true;}return false;}}
使用
XML文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <com.zoe.pagedview.PagedView android:id="@+id/pagedview1" android:layout_width="match_parent" android:layout_height="match_parent" > </com.zoe.pagedview.PagedView></RelativeLayout>java代码:
public class MainActivity extends Activity {PagedView mPagedView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mPagedView = (PagedView) findViewById(R.id.pagedview1);View view;for (int i = 0; i < 5; i++) {view = new View(this);if (i == 0) {view.setBackgroundColor(Color.RED);} else if (i == 1) {view.setBackgroundColor(Color.BLUE);} else if (i == 21) {view.setBackgroundColor(Color.GREEN);} else if (i == 3) {view.setBackgroundColor(Color.YELLOW);} else if (i == 4) {view.setBackgroundColor(Color.RED);}mPagedView.addView(view);}mPagedView.setCurrent(1);}}
效果如下:
0 0
- ViewGroup重写——滚动页面容器
- ViewGroup重写——网格容器
- Android——自定义滚动ViewGroup
- ScrollerLayout——可横向滚动的自定义viewgroup
- Android进阶——自定义View之重写ViewGroup组合系统控件实现自定义ToolBar模板
- 重写ViewGroup注意事项
- Android中View的事件体系(3)——自定义横向滚动viewGroup
- Viewgroup(View容器)
- 用ViewGroup实现左右滚动
- 自定义ViewGroup实现垂直滚动
- 自定义ViewGroup实现垂直滚动
- 自定义ViewGroup实现垂直滚动
- 用ViewGroup实现左右滚动
- 自定义ViewGroup实现垂直滚动
- 自定义ViewGroup (滚动布局)
- Android仿人人客户端(v5.7.1)——采用ViewGroup做父容器,实现左侧滑动菜单(三)
- 图片左右滚动控件(带倒影)——重写Gallery
- 图片左右滚动控件(带倒影)——重写Gallery
- const和#define宏定义的区别
- 生成系列数(1、2、3 ... N)应用实例
- C++类的前置声明
- std::function和std::bind的使用(总结)
- Remove Nth Node From End of List
- ViewGroup重写——滚动页面容器
- linux shell中的点命令------谈谈. ./a.sh和./a.sh的区别
- NS2网络仿真的过程
- Android签名时混淆包名
- 关于AutoLayout的框架Masonry的使用
- csu 1328: 近似回文词
- GLSL 纹理贴图
- 个人感悟(1):最近的学习与感悟
- Leetcode Course Schedule