自定義View——仿ViewPager
阿新 • • 發佈:2019-02-03
1.主佈局
<?xml version="1.0" encoding="utf-8"?>
<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">
<RadioGroup
android:id ="@+id/rg_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="horizontal" />
<com.hbwj.a06viewpager.MyViewPager
android:id="@+id/myviewpager"
android:layout_width ="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/rg_main" />
</RelativeLayout>
2.程式碼中例項化MyScrollerView,並且新增頁面
private MyViewPager myviewpager;
private int[] ids = {R.drawable.a1, R.drawable.a2, R.drawable.a3, R.drawable.a4, R.drawable.a 5, R.drawable.a6};
private RadioGroup rg_main;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
myviewpager = (MyViewPager) findViewById(R.id.myviewpager);
rg_main = (RadioGroup) findViewById(R.id.rg_main);
//新增6頁面
for (int i = 0; i < ids.length; i++) {
ImageView imageView = new ImageView(this);
imageView.setBackgroundResource(ids[i]);
//新增到MyViewPager這個View中
myviewpager.addView(imageView);
}
}
}
3.onLayout方法實現:指定6個圖片的位置
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//遍歷孩子,給每個孩子指定在螢幕的座標位置
for (int i = 0; i < getChildCount(); i++) {
View childView = getChildAt(i);
childView.layout(i * getWidth(), 0, (i + 1) * getWidth(), getHeight());
}
}
畫圖分析
4.對自定義的viewpager進行滑動,此時想到的便是手勢識別器,手勢識別器分為3步走:
- 1.定義出來
- 2.例項化-把想要的方法給重新
- 3.在onTouchEvent()把事件傳遞給手勢識別器
private GestureDetector detector;
private void initView(final Context context) {
//2.例項化手勢識別器
detector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public void onLongPress(MotionEvent e) {
super.onLongPress(e);
Toast.makeText(context, "長按", Toast.LENGTH_SHORT).show();
}
/**
*
* @param e1
* @param e2
* @param distanceX 在X軸滑動了的距離
* @param distanceY 在Y軸滑動了的距離
* @return
*/
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
/**
*x:要在X軸移動的距離
*y:要在Y軸移動的距離
*/
scrollBy((int) distanceX, 0);
return true;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
Toast.makeText(context, "雙擊", Toast.LENGTH_SHORT).show();
return super.onDoubleTap(e);
}
});
}
//3.把事件傳遞給手勢識別器:onTouchEvent方法中
detector.onTouchEvent(event);
5.滑動到某個位置後自動到合適的位置下標停留
private float startX;
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
//3.把事件傳遞給手勢識別器
detector.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//1.記錄座標
startX = event.getX();
System.out.println("onTouchEvent==ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
System.out.println("onTouchEvent==ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
System.out.println("onTouchEvent==ACTION_UP");
//2.來到新的座標
float endX = event.getX();
//下標位置
int tempIndex = currentIndex;
if ((startX - endX) > getWidth() / 2) {
//顯示下一個頁面
tempIndex++;
} else if ((endX - startX) > getWidth() / 2) {
//顯示上一個頁面
tempIndex--;
}
//根據下標位置移動到指定的頁面
scrollToPager(tempIndex);
break;
}
return true;
}
/**
* 遮蔽非法值,根據位置移動到指定頁面
*
* @param tempIndex
*/
public void scrollToPager(int tempIndex) {
if (tempIndex < 0) {
tempIndex = 0;
}
if (tempIndex > getChildCount() - 1) {
tempIndex = getChildCount() - 1;
}
//當前頁面的下標位置
currentIndex = tempIndex;
//總距離計算出來
int distanceX = currentIndex * getWidth() - getScrollX();
// int distanceX = 目標 - getScrollX();
//移動到指定的位置
scrollTo(currentIndex*getWidth(),getScrollY());
}
滑動到某一個頁面的演算法
6.解決仿viewpager回彈時的生硬問題:使用系統自帶的Scroller
private Scroller scroller;
//初始化
scroller = new Scroller(context);
/**
* 遮蔽非法值,根據位置移動到指定頁面
*
* @param tempIndex
*/
public void scrollToPager(int tempIndex) {
if (tempIndex < 0) {
tempIndex = 0;
}
if (tempIndex > getChildCount() - 1) {
tempIndex = getChildCount() - 1;
}
//當前頁面的下標位置
currentIndex = tempIndex;
if (onPagerChangeListener != null) {
onPagerChangeListener.onScrollToPager(tempIndex);
}
//總距離計算出來
int distanceX = currentIndex * getWidth() - getScrollX();
// int distanceX = 目標 - getScrollX();
//移動到指定的位置
//scrollTo(currentIndex*getWidth(),getScrollY());
//scroller.startScroll(getScrollX(),getScrollY(),distanceX,0);
scroller.startScroll(getScrollX(), getScrollY(), distanceX, 0, Math.abs(distanceX));
invalidate();//強制繪製;//onDraw();computeScroll();
}
@Override
public void computeScroll() {
// super.computeScroll();
if (scroller.computeScrollOffset()) {
//得到移動這個一小段對應的座標
float currX = scroller.getCurrX();
scrollTo((int) currX, 0);
invalidate();
}
}
新增RadioGroup點選並實現雙向跳轉
for (int i = 0; i < myviewpager.getChildCount(); i++) {
RadioButton button = new RadioButton(getApplicationContext());
button.setId(i);
if (i == 0) {
button.setChecked(true);
}
rg_main.addView(button);
}
rg_main.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) {
myviewpager.scrollToPager(checkedId);
}
});
定義介面PagerChangeListener監聽頁面變化
/**
* 監聽頁面變化
*/
interface OnPagerChangeListener {
void onScrollToPager(int position);
}
OnPagerChangeListener onPagerChangeListener;
public void setOnPagerChangeListener(OnPagerChangeListener onPagerChangeListener) {
this.onPagerChangeListener = onPagerChangeListener;
}
//scrollToPager中新增程式碼
if (onPagerChangeListener != null) {
onPagerChangeListener.onScrollToPager(tempIndex);
}
使用介面
myviewpager.setOnPagerChangeListener(new MyViewPager.OnPagerChangeListener() {
@Override
public void onScrollToPager(int position) {
rg_main.check(position);
}
});
7.新增測試頁面
佈局如下
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#55ff0000"
android:weightSum="1">
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleLarge"
android:layout_width="136dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
<ProgressBar
android:id="@+id/progressBar2"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="372dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
<ProgressBar
android:id="@+id/progressBar3"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
<ScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal">
<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="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
</ScrollView>
</LinearLayout>
MainActivity中添加布局
//指定頁面添加布局
View view=View.inflate(getApplicationContext(),R.layout.test,null);
myviewpager.addView(view,2);
8.解決無法看到效果,在MyScrollView中重寫OnMeasure
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
for (int i = 0; i < getChildCount(); i++) {
View childView = getChildAt(i);
childView.measure(widthMeasureSpec, heightMeasureSpec);
}
}
9.解決事件攔截問題
MyViewPager中新增攔截事件
/**
* 攔截事件
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean result = false;
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
detector.onTouchEvent(ev);
//第一次按下的座標
downX = ev.getX();
downY = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
float newdownX = ev.getX();
float newdownY = ev.getY();
int distanceX = (int) Math.abs(newdownX - downX);
int distanceY = (int) Math.abs(newdownY - downY);
//防止抖動為1的情況
if(distanceX>distanceY&&distanceX>10){
result=true;
}
break;
case MotionEvent.ACTION_UP:
break;
}
return result;
}