自定义ViewPager+RadioGroup联动效果的实现
package com.loaderman.myviewpager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
public class MainActivity extends AppCompatActivity {
private MyViewPager mViewPager;
private RadioGroup rgGroup;
private int[] mImageIds = new int[]{R.drawable.a1, R.drawable.a2, R.drawable.a3, R.drawable
.a4, R.drawable.a5, R.drawable.a6};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewPager = (MyViewPager) findViewById(R.id.viewpager);
rgGroup = (RadioGroup) findViewById(R.id.rg_group);
//给自定义Viewpager添加图片
for (int id : mImageIds) {
ImageView view = new ImageView(this);
view.setBackgroundResource(id);
mViewPager.addView(view);
}
//添加测试页面布局
View view = View.inflate(this, R.layout.item_test, null);
mViewPager.addView(view, 2);
//动态添加RaidoButton
for (int i = 0; i <= mImageIds.length; i++) {
RadioButton rb = new RadioButton(this);
rb.setId(i);//以当前位置为id
rgGroup.addView(rb);
if (i == 0) {
rb.setChecked(true);
}
}
//点击RadioButton, 切换页面
rgGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
System.out.println("checkedId:" + checkedId);
int pos = checkedId;
mViewPager.setCurrentItem(pos);
}
});
//切换页面, 更新RadioButton
mViewPager.addOnPageChangeListener(new MyViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
int id = position;
rgGroup.check(id);
}
}); }
}
package com.loaderman.myviewpager;
import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;
/**
* 自定义ViewPager流程:
* 1. 写一个类继承ViewGroup
* 2. 在actvity中添加图片对象
* 3. 重写onLayout, 保证子控件一字排开
* 4. 滑动布局,切换页面, 手势识别器 onScroll: scrollBy, scrollTo
* 5. 平滑滑动效果 Scroller滑动器
* 6. 加测试页面ScrollView
* 7. 重写onMeasure测量所有子控件
* 8. 事件传递流程, 苹果例子
* 9. 事件拦截流程
* 10. 保证viewpager和scrollview分别处理相关事件
* 11. 添加RadioButton
* 12. 点击RadioButton切换页面
* 13. 滑动页面, 切换RadioButton
*/
public class MyViewPager extends ViewGroup {
private GestureDetector mDetector;
private Scroller mScroller;
private int startX;
private int startY;
public MyViewPager(Context context) {
this(context, null);
}
public MyViewPager(Context context, AttributeSet attrs) {
this(context, attrs, -1);
}
public MyViewPager(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mDetector = new GestureDetector(getContext(), new GestureDetector
.SimpleOnGestureListener() {
//触摸滑动的方法
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float
distanceY) {
//distanceX: 水平滑动距离
scrollBy((int) distanceX, 0);//基于当前位置进行滑动, 参1:水平滑动的偏移量, 相对位置
return super.onScroll(e1, e2, distanceX, distanceY);
}
});
//滑动器
mScroller = new Scroller(getContext());
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);//设置ViewPager本身的尺寸
//遍历所有子控件,设置每个控件的尺寸
//解决测试页面显示白板的问题
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.measure(widthMeasureSpec, heightMeasureSpec);
}
//widthMeasureSpec: 并不是真实的宽高信息, 它包含两部分, 1: 宽高模式信息; 2. 具体的尺寸
// System.out.println("widthMeasureSpec:" + widthMeasureSpec);
// System.out.println("heightMeasureSpec:" + heightMeasureSpec);
//MeasureSpec.AT_MOST; 至多模式, 当前控件有多大就显示多大 wrap_content
//MeasureSpec.EXACTLY; 确定模式, 宽高写死dp, match_parent(父控件多大,我就多大,所以也是确定的)
//MeasureSpec.UNSPECIFIED; 未确定模式, ListView, ScrollView // int mode = MeasureSpec.getMode(widthMeasureSpec);
// int size = MeasureSpec.getSize(widthMeasureSpec);
//
// System.out.println("mode:" + mode);
// System.out.println("size:" + size);
}
//设置控件的位置
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//遍历所有子控件, 设置每个子控件位置
//子控件一字排开
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.layout(getWidth() * i, 0, getWidth() * (i + 1), getHeight());
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mDetector.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
System.out.println("ViewPager 按下...");
break;
case MotionEvent.ACTION_MOVE:
System.out.println("ViewPager 移动...");
break;
case MotionEvent.ACTION_UP:
System.out.println("ViewPager 抬起...");
//手指抬起
//确定下一页的位置
int scrollX = getScrollX();//获取当前移动后的x值
// System.out.println("scrollX:" + scrollX);
//计算当前页面位置
int currPos = scrollX / getWidth();
// System.out.println("currPos:" + currPos);
int offset = scrollX % getWidth();//多划出的距离
if (offset > getWidth() / 2) {
currPos++;
}
//避免越界 0->图片个数-1
if (currPos < 0) {
currPos = 0;
}
if (currPos > getChildCount() - 1) {
currPos = getChildCount() - 1; //System.out.println("下一页位置:" + currPos); //跳到下一页位置
// scrollTo(currPos * getWidth(), 0);//绝对位置,移动到确定位置
//计算滑动距离
// int dx = currPos * getWidth() - getScrollX();//目标位置-当前位置=滑动距离
// //此方法不能产生滑动的动画效果, 会导致回调computeScroll方法, 需要在computeScroll方法中处理动画
// mScroller.startScroll(getScrollX(), 0, dx, 0, Math.abs(dx));//距离和时间要成正比
// invalidate();//要刷新界面
setCurrentItem(currPos);
break;
default:
break;
}
return true;
}
//此方法会回调多次, 每一次回调后修改页面位置, 连续在一起就形成动画
@Override
public void computeScroll() {
super.computeScroll();
if (mScroller.computeScrollOffset()) {//判断有没有滑动结束
int currX = mScroller.getCurrX();//获取当前应该滑动到的位置
System.out.println("currX:" + currX);
scrollTo(currX, 0);//滑动到特定位置
invalidate();//要刷新界面
}
}
//事件分发
//dispatchTouchEvent->onInterceptTouchEvent-->onTouchEvent
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
//如果上下滑动, 不需要中断事件
//左右滑动, 才需要中断事件
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = (int) ev.getX();
startY = (int) ev.getY();
//由于按下之后, 返回false, 按下事件被子控件处理,导致ViewPager丢掉了按下事件,滑动时页面出现bug
//补上按下事件
mDetector.onTouchEvent(ev);
break;
case MotionEvent.ACTION_MOVE:
int endX = (int) ev.getX();
int endY = (int) ev.getY();
int dx = endX - startX;
int dy = endY - startY;
if (Math.abs(dx) > Math.abs(dy)) {
//左右滑动
return true;//表示中断事件传递, 交给当前ViewPager处理, 子控件无法处理
}
break;
default:
break;
}
return false;//不中断事件, 交给子控件(ScrollView)处理
}
//设置当前页面
public void setCurrentItem(int pos) {
//计算滑动距离
int dx = pos * getWidth() - getScrollX();//目标位置-当前位置=滑动距离
//此方法不能产生滑动的动画效果, 会导致回调computeScroll方法, 需要在computeScroll方法中处理动画
mScroller.startScroll(getScrollX(), 0, dx, 0, Math.abs(dx));//距离和时间要成正比
invalidate();//要刷新界面
//回调页面位置
if (listener != null) {
listener.onPageSelected(pos);
}
}
private OnPageChangeListener listener;
public void addOnPageChangeListener(OnPageChangeListener listener) {
this.listener = listener;
}
public interface OnPageChangeListener {
public void onPageSelected(int position);
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.loaderman.myviewpager.MainActivity"> <RadioGroup
android:id="@+id/rg_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
</RadioGroup> <com.loaderman.myviewpager.MyViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
item_test.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--item_test-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试文本"
android:textSize="30sp"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试文本"
android:textSize="30sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试文本"
android:textSize="30sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试文本"
android:textSize="30sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试文本"
android:textSize="30sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试文本"
android:textSize="30sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试文本"
android:textSize="30sp"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试文本"
android:textSize="30sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试文本"
android:textSize="30sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试文本"
android:textSize="30sp"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试文本"
android:textSize="30sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试文本"
android:textSize="30sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试文本"
android:textSize="30sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试文本"
android:textSize="30sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试文本"
android:textSize="30sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试文本"
android:textSize="30sp"/>
</LinearLayout>
</ScrollView>
效果:

自定义ViewPager+RadioGroup联动效果的实现的更多相关文章
- 实现ViewPager的联动效果
参考链接:android - Synchronizing two ViewPagers using OnPageChangeListener - Stack Overflow 其中有个非常完美的解决方 ...
- Android 自定义 ViewPager 打造千变万化的图片切换效果
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38026503 记得第一次见到ViewPager这个控件,瞬间爱不释手,做东西的主 ...
- Android实现图片轮显效果——自定义ViewPager控件
一.问题概述 使用ViewPager控件实现可横向翻页.水平切换图片等效果,但ViewPager需要手动滑动才能切换页面,图片轮显效果的效果本质上就是在ViewPager控件的基础上让它能自动的进行切 ...
- jquery.cityselect.js基于jQuery+JSON的省市或自定义联动效果
一.插件介绍 最早做省市联动的时候都特别麻烦,后来在helloweba的一篇文章中看到这个插件,很不错的,后来就一直用了. 省市区联动下拉效果在WEB中应用非常广泛,尤其在一些会员信息系统.电商网站最 ...
- Android底部导航栏创建——ViewPager + RadioGroup
原创文章,引用请注明出处:http://www.cnblogs.com/baipengzhan/p/6270201.html Android底部导航栏有多种实现方式,本文详解其中的ViewPager ...
- Android之自定义ViewPager实现图片的无线轮播
PS:以前也写过关于图片轮播这一块的博客.不过写的很烂,并且很多情况没有考虑到(没有支持无线轮播,和手势点击事件).因此这里写一篇补上.也是当时太年轻了. 注:图片请放大后再看.否则看不清楚. 学习内 ...
- Json 基于jQuery+JSON的省市联动效果
helloweba.com 作者:月光光 时间:2012-09-12 21:57 标签: jQuery JSON Ajax 省市联动 省市区联动下拉效果在WEB中应用非常广泛,尤其在一些 ...
- 【转】android 自定义ViewPager,修改原动画
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38026503 记 得第一次见到ViewPager这个控件,瞬间爱不释手,做东西的 ...
- 仿百度壁纸客户端(二)——主页自定义ViewPager广告定时轮播图
仿百度壁纸客户端(二)--主页自定义ViewPager广告定时轮播图 百度壁纸系列 仿百度壁纸客户端(一)--主框架搭建,自定义Tab + ViewPager + Fragment 仿百度壁纸客户端( ...
随机推荐
- TP-LINK WR941N路由器研究
TP-LINK WR941N路由器研究 之前看到了一个CVE, CVE-2017-13772 是TP-Link WR940N后台的RCE, 手头上正好有一个TP-Link WR941N的设备,发现也存 ...
- JSON parse error: syntax error, expect {, actual error, pos 0, fastjson-version 1.2.58; nested exception is com.alibaba.fastjson.JSONExcetion: syntax error, except {, actual error, pos ...
这个报错信息告诉你,你提交的参数需要是json类型.所以,POST请求携带的数据需要序列化一下json.dumps(data).
- linux 重定向类型 超级块 i节点
超级块:定义文件系统的元数据(总大小.块大小.空闲.......):在格式化的时候确定 查看超级块信息:tune2fs -l 目录 i节点:定义文件的元数据(名称.大小.存放位置.权限.修改时间 ...
- CentOS7 xrdp 安装和设置
1) 安装 $ sudo yum install xrdp $ sudo yum install tigervnc $ sudo yum install tigervnc-server 2) 设置密码 ...
- BZOJ 1006 完美消除序列&最大势算法&弦图
K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则.他们认为三角关系:即AB相互认识,BC相互认识,CA相互认识,是简洁高效的.为了巩固三角关系,K国禁止四边关系,五边关系等等的存在.所谓N边关系 ...
- solr介绍
solr架构图: 以下是Apache Solr的主要构建块(组件) 请求处理程序 - 发送到Apache Solr的请求由这些请求处理程序处理.请求可以是查询请求或索引更新请求.根据这些请示的要求来选 ...
- nginx.conf文件的使用
默认配置语法 全局---服务级别的配置 user 设置nginx服务的系统使用用户,基本上不用动 worker_processes 工作进程数---跟nginx多worker有关,增大连接数的并发处理 ...
- Java-CharTools工具类
package com.gootrip.util; import java.io.UnsupportedEncodingException; /** * <p>Title:字符编码工具类 ...
- VC:检测网络连接的方法
方法一: #include "stdafx.h" #include "windows.h" #include <Sensapi.h> #includ ...
- 数据类型之字符串类型与Number类型
㈠字符串类型 ⑴在JS中字符串需要使用引号引起来 ⑵使用双引号或单引号都可以,但是不要混着用 ⑶引号不能嵌套,双引号不能放双引号,单引号不能放单引号 ⑷在字符串中,可以使用“\”作为转义字符,当表示一 ...