android 页面容器 下一页很上一页view

乘着中午休息时间,随便写点

这里是一个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
* 如果在其layout中添加的子view不是规则的,那么还是按照width来跑一页
* 这里的width值是构造函数设置的。通过{@link #setPageWidth(int)}来设置宽度
* 在手动滑动的时候,动画会停止,开启手动滑动{@link #enableSlide(boolean)}
* 如果手动滑到了2个页面之间,那么在调用 {@link #previous()} 或 {@link #next()} 会移动一个scrollX 求 width的摸值
* 注意!!!不需要再设置linearLayou,已经默认设置好,通过{@link #addPageView(View)} 来添加page
* 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 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(); 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 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); } } /** * 下一页, 如果动画没有结束,调用没有效果
* 如果不完整会显示完整 */ 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(); } } } /** * 上一页, 如果动画没有结束,调用没有效果
* 如果不完整会显示完整 */ 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基类
* 它尽可能的对这些页面进行了抽象,但依旧不是很理想
* 对整个界面有一个rootView,是一个{@link RelativeLayout}对象
* 另外还有2个{@link RelativeLayout}对象 分别是上容器和下容器
* 在上容器里面定义了2个按钮,一个是“上一步” 另一个是“跳过”
* {@link #in()} , {@link #out()} 表示page完成进入和开始退出回调
* @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动画开源库

布局文件


    
    
        
		
		
		
		
		
    	
		
    
    

    
    




android 页面容器 下一页很上一页view_第1张图片


你可能感兴趣的:(android,android,view,page)