android 页面容器 下一页很上一页view
2016-01-06 13:58
666 查看
乘着中午休息时间,随便写点
这里是一个page容器可以包含多个BasePageView
容器代码:
这里是BasePageView
有一点针对业务定制,去掉即可,结构不变:
布局文件
这里是一个page容器可以包含多个BasePageView
容器代码:
package com.pingyijinren.guider.setting.view; import java.util.ArrayList; import java.util.Collection; import com.nineoldandroids.animation.Animator; import com.nineoldandroids.animation.Animator.AnimatorListener; import com.nineoldandroids.animation.ValueAnimator; import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener; import com.pingyijinren.guider.Constants; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.widget.LinearLayout; /**既可以滑动,又可以翻页的scrollview<br> * 如果在其layout中添加的子view不是规则的,那么还是按照width来跑一页<br> * 这里的width值是构造函数设置的。通过{@link #setPageWidth(int)}来设置宽度<br> * 在手动滑动的时候,动画会停止,开启手动滑动{@link #enableSlide(boolean)}<br> * 如果手动滑到了2个页面之间,那么在调用 {@link #previous()} 或 {@link #next()} 会移动一个scrollX 求 width的摸值 <br> * 注意!!!不需要再设置linearLayou,已经默认设置好,通过{@link #addPageView(View)} 来添加page<br> * TODO 添加不规则的view可以很好的展现 * @author WenYF * */ public class PageLayout extends LinearLayout implements AnimatorListener , AnimatorUpdateListener{ private static final String TAG = "AnimationHorizontalScrollView"; @SuppressWarnings("unused") private Context nContext; /** * 动画值发生器 */ private ValueAnimator nPositiveValueAnimator; /** * 页面的宽度 */ private int nPageWidth; /** * 是否设置了页面宽度 */ private boolean nHasSetWidth; /** * 页面数量 */ private int nPageCounts; /** * 是否设置了页面数量 */ private boolean nHasSetPageCounts; /** * 当前页面动画的开始位置 */ private int nCurrentStartX; /** * 动画是否打开 */ private boolean nIsEnableAnimation; /** * 动画是否结束 */ private boolean nIsEndAnimation; private Collection<BasePageView> nPageViewsReference; /** * 进入的page */ private BasePageView nInPageView; /** * 出去的page */ private BasePageView nOutPageView; private OnPageListener nPageListener; public void setPageListener(OnPageListener listener) { nPageListener = listener; } /**只能通过改函数来动态设置本view,counts和width一旦设置不能修改 * @param context 上下文 * @param pageCounts 子view的数量 如果为-1则交给scroll view自己来监视有多少个view * @param pageWidth 一页的宽度,-1表示由scroll view来测量自己的宽度 */ public PageLayout(Context context, int pageCounts, int pageWidth) { super(context); nContext = context; initView(pageCounts, pageWidth); } /**使用默认值构造,{@link #PageHorizontalScrollView(Context, int, int)} * @param context */ public PageLayout(Context context) { this(context, null); } /**使用默认值构造,{@link #PageHorizontalScrollView(Context, int, int)} * @param context */ public PageLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } /**使用默认值构造,{@link #PageHorizontalScrollView(Context, int, int)} * @param context */ public PageLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); nContext = context; initView(-1, -1); } private void initView(int counts, int width) { nPageViewsReference = new ArrayList<BasePageView>(); ValueAnimator.setFrameDelay(30); nPositiveValueAnimator = ValueAnimator.ofInt(0, width); nPositiveValueAnimator.setDuration(Constants.ANIMATION_SPEED); nPositiveValueAnimator.addListener(this); nPositiveValueAnimator.addUpdateListener(this); nPageWidth = width; nHasSetWidth = width != -1; nPageCounts = counts; nHasSetPageCounts = nPageCounts != -1; nIsEndAnimation = true; nIsEnableAnimation = true; Log.d(TAG, "width = " + width + ", counts = " + nPageCounts); setHorizontalScrollBarEnabled(false); setHorizontalFadingEdgeEnabled(false); } /** * @param counts 子view的数量 如果为-1则交给scroll view自己来监视有多少个view */ public void setPageCounts(int counts) { if (counts == -1) { nHasSetPageCounts = false; } else { nHasSetPageCounts = true; nPageCounts = counts; } } /** * @param width 一页的宽度,-1表示由scroll view来测量自己的宽度 */ public void setPageWidth(int width) { if (width == -1) { nHasSetWidth = false; } else { nHasSetWidth = true; nPageWidth = width; } } /**打开或关闭跳转页面动画 * @param enable */ public void enableAnimation(boolean enable) { nIsEnableAnimation = enable; } /** 给容器添加view,而不是scroll view * @param page */ public void addPageView(BasePageView page) { addView(page); nPageViewsReference.add(page); } /** 给容器添加view,而不是scroll view * @param child * @param index */ public void addPageView(BasePageView page, int index) { addView(page, index); nPageViewsReference.add(page); } /** 给容器添加view,而不是scroll view * @param child * @param index * @param params */ public void addPageView(BasePageView page, int index, android.view.ViewGroup.LayoutParams params) { addView(page, params); nPageViewsReference.add(page); } /** 给容器添加view,而不是scroll view * @param child * @param width * @param height */ public void addPageView(BasePageView page, int width, int height) { addView(page, width, height); nPageViewsReference.add(page); } /** 给容器添加view,而不是scroll view * @param child * @param params */ public void addPageView(BasePageView page, android.view.ViewGroup.LayoutParams params) { addView(page, params); nPageViewsReference.add(page); } public Collection<BasePageView> getPageViews() { return nPageViewsReference; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); Log.d(TAG, "onMeasure view width = " + getWidth()); if (!nHasSetWidth) { nPositiveValueAnimator.setIntValues(0, getWidth()); nPageWidth = getWidth(); } if (!nHasSetPageCounts) { nPageCounts = getChildCount(); Log.d(TAG, "onMeasure page Counts = " + nPageCounts); } } /** * 下一页, 如果动画没有结束,调用没有效果<br> * 如果不完整会显示完整 */ public void next() { Log.d(TAG, "next scrollx = " + getScrollX()); if (nPageCounts <= 0 || nPageWidth <= 0) { Log.w(TAG, "the values is invalid, page counts = " + ", width = " + nPageWidth); return; } // 最后一页,通知 if (getScrollX() >= nPageWidth * (nPageCounts - 1) && nPageListener != null) { nPageListener.onEnd(); } if (getScrollX() < nPageWidth * (nPageCounts - 1) && nIsEndAnimation) { int inPageIndex = getScrollX() / nPageWidth + 1; int outPageIndex = getScrollX() / nPageWidth; Log.d(TAG, "inPageIndex = " + inPageIndex); Log.d(TAG, "outPageIndex = " + outPageIndex); nInPageView = (BasePageView) getChildAt(inPageIndex); nOutPageView = (BasePageView) getChildAt(outPageIndex); // 得到要移动的距离 int deltaX = nPageWidth - (getScrollX() % nPageWidth) != 0 ? nPageWidth - (getScrollX() % nPageWidth) : nPageWidth; Log.d(TAG, "next deltaX = " + deltaX); // 前一页离开 nOutPageView.out(); if (!nIsEnableAnimation) { nCurrentStartX = getScrollX() + deltaX; scrollTo(nCurrentStartX, 0); // 后一页进入 nInPageView.in(); } else { nCurrentStartX = getScrollX(); nPositiveValueAnimator.setIntValues(0, deltaX); nPositiveValueAnimator.start(); } } } /** * 上一页, 如果动画没有结束,调用没有效果<br> * 如果不完整会显示完整 */ public void previous() { Log.d(TAG, "previous scrollx = " + getScrollX()); if (nPageCounts <= 0 || nPageWidth <= 0) { Log.w(TAG, "the values is invalid, page counts = " + nPageCounts + ", width = " + nPageWidth); return; } if (getScrollX() > 0 && nIsEndAnimation) { int totleWidth = nPageCounts * nPageWidth; int inPageIndex = nPageCounts - 1 - ((totleWidth - (getScrollX() + nPageWidth)) / nPageWidth + 1); int outPageIndex = nPageCounts - 1 - (totleWidth - (getScrollX() + nPageWidth)) / nPageWidth; Log.d(TAG, "inPageIndex = " + inPageIndex); Log.d(TAG, "outPageIndex = " + outPageIndex); nInPageView = (BasePageView) getChildAt(inPageIndex); nOutPageView = (BasePageView) getChildAt(outPageIndex); // 得到要移动的距离 int deltaX = getScrollX() % nPageWidth != 0 ? getScrollX() % nPageWidth : nPageWidth; Log.d(TAG, "previous deltaX = " + deltaX); // 前一页离开 nOutPageView.out(); nCurrentStartX = getScrollX() - deltaX; if (!nIsEnableAnimation) { scrollTo(nCurrentStartX, 0); // 后一页进入 nInPageView.in(); } else { nPositiveValueAnimator.setIntValues(0, deltaX); nPositiveValueAnimator.reverse(); } } } @Override public void onAnimationStart(Animator animation) { nIsEndAnimation = false; setEnabled(false); } @Override public void onAnimationEnd(Animator animation) { nIsEndAnimation = true; nInPageView.in(); setEnabled(true); } @Override public void onAnimationCancel(Animator animation) { nIsEndAnimation = true; setEnabled(true); } @Override public void onAnimationRepeat(Animator animation) { } @Override public void onAnimationUpdate(ValueAnimator animation) { int values = nCurrentStartX + (Integer) animation.getAnimatedValue(); Log.v(TAG, "values = " + values); scrollTo((int)values, 0); } public interface OnPageListener { public void onEnd(); } }
这里是BasePageView
有一点针对业务定制,去掉即可,结构不变:
package com.pingyijinren.guider.setting.view; import com.pingyijinren.guider.R; import android.app.Dialog; import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.RelativeLayout; /**这是一个开机引导中页面的view基类<br> * 它尽可能的对这些页面进行了抽象,但依旧不是很理想<br> * 对整个界面有一个rootView,是一个{@link RelativeLayout}对象<br> * 另外还有2个{@link RelativeLayout}对象 分别是上容器和下容器<br> * 在上容器里面定义了2个按钮,一个是“上一步” 另一个是“跳过”<br> * {@link #in()} , {@link #out()} 表示page完成进入和开始退出回调<br> * @author WenYF * */ public abstract class BasePageView extends RelativeLayout{ /** * page中唯一的一个对话框 */ protected Dialog nDialog; /** * 页面的根view */ protected RelativeLayout nRootView; /** * 上容器 */ protected RelativeLayout nTopViewContainer; /** * 下容器 */ protected RelativeLayout nBottomViewContainer; /** * 上一步按钮,父view是{@link #nTopViewContainer} */ protected ImageView nPreviousView; /** * 跳过按钮,父view是{@link #nTopViewContainer} */ protected ImageView nSkipView; /** * 保护此页面的容器view */ protected PageLayout nPageControlView; /** * top container 用来显示title的panel */ protected ImageWithTextView nTopTitlePanal; public BasePageView(Context context) { this(context, null); } public BasePageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public BasePageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); LayoutInflater.from(context).inflate(R.layout.container_view_main, this, true); nRootView = (RelativeLayout) findViewById(R.id.container_root); nTopViewContainer = (RelativeLayout) findViewById(R.id.container_top); nTopTitlePanal = (ImageWithTextView) findViewById(R.id.top_title_panal); nBottomViewContainer = (RelativeLayout) findViewById(R.id.container_bottom); nPreviousView = (ImageView) findViewById(R.id.button_previous); nSkipView = (ImageView) findViewById(R.id.button_skip); nPreviousView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { nPageControlView.previous(); } }); nSkipView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { nPageControlView.next(); } }); } /**设置跳过和上一页按钮的visibility * @param visibility */ public void setButtonViewVisibility(int visibility) { nSkipView.setVisibility(visibility); nPreviousView.setVisibility(visibility); } /**设置上下两个容器 Visibility 值 * @param visibility {@link View#VISIBLE} or {@link View#INVISIBLE} or {@link View#GONE} */ public void setContainerViewVisibility(int visibility) { nTopViewContainer.setVisibility(visibility); nBottomViewContainer.setVisibility(visibility); } /**设置底部的view容器的height * @param height {@link RelativeLayout.LayoutParams} match_parent \ warp_content \ custom height */ public void setBottomContainerHeight(int height) { RelativeLayout.LayoutParams params = (LayoutParams) nBottomViewContainer.getLayoutParams(); params.height = height; nBottomViewContainer.setLayoutParams(params); } public void setPageControlView(PageLayout view) { nPageControlView = view; } /** * 页面完成进来的时候处理 */ public abstract void in(); /** * 页面开始出去的时候处理 */ public abstract void out(); /** * 释放view中可能没有办法释放的内存 */ public abstract void destory(); }注意,代码里面用到了http://download.csdn.net/detail/juy19901128/9392637的android动画开源库
布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container_root" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.pingyijinren.guider.setting.activity.GuiderSettingActivity" > <RelativeLayout android:id="@+id/container_top" android:layout_width="match_parent" android:layout_height="125.33dp" android:layout_marginTop="6.67dp" android:layout_marginLeft="6.67dp" android:layout_marginRight="6.67dp" android:background="@drawable/top"> <ImageView android:id="@+id/button_previous" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="9.33dp" android:layout_marginTop="9.33dp" android:clickable="true" android:background="@android:color/transparent" android:contentDescription="@string/text_image_view_desc" android:src="@drawable/selector_button_previous"/> <ImageView android:id="@+id/button_skip" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_marginRight="9.33dp" android:layout_marginTop="9.33dp" android:clickable="true" android:background="@android:color/transparent" android:contentDescription="@string/text_image_view_desc" android:src="@drawable/selector_button_skip"/> <com.pingyijinren.guider.setting.view.ImageWithTextView android:id="@+id/top_title_panal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="35.33dp" android:layout_centerHorizontal="true" > </com.pingyijinren.guider.setting.view.ImageWithTextView> </RelativeLayout> <RelativeLayout android:id="@+id/container_bottom" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/container_top" android:layout_marginLeft="6.67dp" android:layout_marginRight="6.67dp" android:background="@drawable/bottom"> </RelativeLayout> </RelativeLayout>
相关文章推荐
- Android框架One
- 关于android studio找不到subversion的解决方法
- android 手机开启debug日志
- Android APK反编译就这么简单 详解
- Android:进度条
- Android:菜单
- Android系统之路(初识MTK) ------ 默认打开开发者模式默认打开USB调试
- Android:拖动条SeekBar
- 分享一下 Android 圆形按钮控件和带进度条的开始暂停按钮
- Android:StatFs类
- Android:下拉列表Spinner(三)
- Android:下拉列表Spinner(二)
- Android 控件收集
- Android:下拉列表Spinner
- Android:多选按钮
- Android抽象布局——include、merge 、ViewStub
- Android:单选按钮
- 关于android 联系人数据库处理
- Android:对话框
- android studio下载地址