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<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>





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 ViewPager 中显示上一页和下一页,你可以使用一个自定义的布局来实现。这个布局可以包含两个按钮,一个用于显示上一页,另一个用于显示下一页。在每个按钮的点击事件中,你可以调用 ViewPager 的 setCurrentItem() 方法来设置当前显示的页码。 下面是一个简单的实现示例: 1. 创建一个自定义的布局文件 pager_navigation.xml,添加上一页和下一页按钮: ```xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center"> <Button android:id="@+id/btn_previous" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="上一页" /> <Button android:id="@+id/btn_next" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="下一页" /> </LinearLayout> ``` 2. 在 Activity 中加载布局文件,并找到上一页和下一页按钮: ```java View pagerNavigation = getLayoutInflater().inflate(R.layout.pager_navigation, null); Button btnPrevious = pagerNavigation.findViewById(R.id.btn_previous); Button btnNext = pagerNavigation.findViewById(R.id.btn_next); ``` 3. 设置按钮的点击事件,通过 ViewPager 的 setCurrentItem() 方法切换页面: ```java btnPrevious.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int currentPage = viewPager.getCurrentItem(); if (currentPage > 0) { viewPager.setCurrentItem(currentPage - 1); } } }); btnNext.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int currentPage = viewPager.getCurrentItem(); if (currentPage < adapter.getCount() - 1) { viewPager.setCurrentItem(currentPage + 1); } } }); ``` 其中,adapter.getCount() 方法返回 ViewPager 中页面的总数。注意,在设置当前页码时,要判断当前页码是否已经到达边界。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值