自定義控制元件ViewPager
效果圖:
MainActivity
package com.example.administrator.viewgroup_xianxi;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
//scrollToPager(id);
public class MainActivity extends Activity {
private MyviewGroup ViewGroupText;
int dis[]={R.drawable.kkkk, R.drawable.kkkkkk,R.drawable.aaaa};
private RadioGroup rgMain;
@Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewGroupText = (MyviewGroup) findViewById(R.id.ViewGroup_text);
rgMain = (RadioGroup) findViewById(R.id.rg_main);
for (int i = 0; i < dis.length; i++) {
ImageView imageView = new ImageView(this);
imageView.setBackgroundResource(dis[i]);
ViewGroupText.addView(imageView);
}
//因為載入的是一個佈局所以佈局裡面的控制元件要進行測量大小
View addb=View.inflate(this,R.layout.addb,null);
ViewGroupText.addView(addb,1);
for (int i = 0; i < ViewGroupText.getChildCount(); i++) {
RadioButton button=new RadioButton(this);
button.setId(i);//0-3id
if(i==0){
button.setChecked(true);
}
rgMain.addView(button);
}
//設定RadioGroup選中的變化
rgMain.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, int id) {
//MyviewPager
ViewGroupText.scrollToPager(id);//根據下表定位到具體頁面;罪上面
}
});
ViewGroupText.setOnpagerChanglistenter(new MyviewGroup.OnpagerChanglistenter() {
@Override
public void onScrollToPager(int position) {
rgMain.check(position);
}
});
}
}
main佈局.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cheng="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<RadioGroup
android:id="@+id/rg_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="horizontal"></RadioGroup>
<com.example.administrator.viewgroup_xianxi.MyviewGroup
android:id="@+id/ViewGroup_text"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.example.administrator.viewgroup_xianxi.MyviewGroup>
</LinearLayout>
自定義MyviewGroup類
package com.example.administrator.viewgroup_xianxi;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;
import android.widget.Toast;
public class MyviewGroup extends ViewGroup {
int currentIndx;//當前的座標
private Scroller mScrolier;
/**
* 手勢介面卡
* 1,定義出來
* 2,例項化-把想要的方法給重新
* 3,在ontouchEvent()把事件鑽地給手勢識別器
*
*/
private GestureDetector mGestureDetector;
public MyviewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
private void initView(final Context context) {
mScrolier=new Scroller(context);
//2,例項化-把想要的方法給重新
mGestureDetector=new GestureDetector(context,new GestureDetector.SimpleOnGestureListener(){
@Override
public void onLongPress(MotionEvent e) {
Toast.makeText(context, "長安", Toast.LENGTH_SHORT).show();
super.onLongPress(e);
}
/**
* @param e1//e1按下
* @param e2//e2離開
* @param distanceX 在x軸滑動了距離
* @param distanceY 在Y軸滑動了距離
* @return
*/
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
//區別
//scrollTo相對於view的初始位置移動,所以這裡view無論點選多少次,都只會相對於view的初始位置移動一定距離。
//mLayout.scrollTo(getResources().getDimensionPixelSize(R.dimen.a), getResources().getDimensionPixelSize(R.dimen.b));
//scrollBy相對於view的當前位置移動,所以此處view是每點選一次就向右下角移動一次的。
//mLayout.scrollBy(getResources().getDimensionPixelSize(R.dimen.a), getResources().getDimensionPixelSize(R.dimen.b));
//讓自己內容移動(不是讓孩子移動)
//根據當前位置移動:getScrollY初始值
//x:要在x軸平移的距離
//y:要在y軸移動的距離
//看點
//理解相對論(右移動是負)|(左移動是正)
Log.e("hh", "onScroll: "+distanceX );
scrollBy((int)distanceX,getScrollY());
return super.onScroll(e1, e2, distanceX, distanceY);
}
@Override
public boolean onDoubleTap(MotionEvent e) {
Toast.makeText(context, "雙擊", Toast.LENGTH_SHORT).show();
return super.onDoubleTap(e);
}
});
}
@Override
protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
//便利孩子,給每個孩子指定在螢幕的座標位置
for (int j = 0; j < getChildCount(); j++) {
View childAt = getChildAt(j);
//l距離左邊距離t距離top上邊距離,(一個上點)|r距離左(一個下點)b距離上面
childAt.layout(j*getWidth(),0,(j+1)*getWidth(),getHeight());
}
}
//判斷觸控事件的傳遞(我只要x軸用來滑倒下一頁)
//如果當前,方法返回true,攔截事件,將會觸發當前控制元件的onTouchEvent()方法
//如果當前,方法返回false,不攔截事件,事件繼續傳遞給孩子
//攔截事件
private float mStarX;
private float mStarY;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
//因為我在這做了一點滑動判斷所以哪一點也需要傳入手指介面卡不來會跳一下
mGestureDetector.onTouchEvent(ev);
boolean issorllX=false;
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN://按下
//1,記錄按下的xy值
mStarX = ev.getX();
mStarY = ev.getY();
break;
case MotionEvent.ACTION_MOVE://移動
//2,記錄結束xy值
float endX = ev.getX();
float endY = ev.getY();
//3,計算絕對值
float distanceX =Math.abs(mStarX-endX);
float distanceY =Math.abs(mStarY-endY);
if(distanceX>distanceY&&distanceX>10){
issorllX= true;
}else{
scrollToPager(currentIndx);
}
break;
case MotionEvent.ACTION_UP://抬起
break;
}
return issorllX;
}
private float startX;
// getX()是表示Widget相對於自身左上角的x座標
// 而getRawX()是表示相對於螢幕左上角的x座標值(注意:這個螢幕左上角是手機螢幕左上角,不管activity是否有titleBar或是否全螢幕),getY(),getRawY()一樣的道理
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
//3,在ontouchEvent()把事件鑽地給手勢識別器
mGestureDetector.onTouchEvent(event);
switch (event.getAction()){
case MotionEvent.ACTION_DOWN://按下
//1記錄座標
startX=event.getX();
break;
case MotionEvent.ACTION_MOVE://移動
break;
case MotionEvent.ACTION_UP://抬起
//2來到新座標
float endx=event.getX();
//下表位置
int tempIndex=currentIndx;
if((startX-endx)>getWidth()/2){
//顯示下一個頁面
tempIndex++;
}else if ((endx-startX)>getWidth()/2){
//顯示上一個頁面
tempIndex--;
}
scrollToPager(tempIndex);
break;
}
return true;
}
//遮蔽非法值 根據位置移動到指定頁面
public void scrollToPager(int tempIndex) {
if(tempIndex<0){
tempIndex=0;
}
if(tempIndex>getChildCount()-1){
tempIndex=getChildCount()-1;
}
//當前頁面的下標位置
currentIndx=tempIndex;
//distanceX就是滑動時的剩餘距離
int distanceX=currentIndx*getWidth()-getScrollX();
if(mOnpagerChanglistenter!=null){
mOnpagerChanglistenter.onScrollToPager(currentIndx);
}
//移動到指定的位置
// scrollTo(currentIndx*getWidth(),getScrollY());
// mScrolier.startScroll(getScrollX(),getScrollY(),distanceX,0);
mScrolier.startScroll(getScrollX(),getScrollY(),distanceX,0,Math.abs(distanceX));
invalidate();//onDraw();computeScroll()
}
private OnpagerChanglistenter mOnpagerChanglistenter;
//讓使用者傳遞介面的例項過來
public void setOnpagerChanglistenter(OnpagerChanglistenter l){
mOnpagerChanglistenter=l;
}
//監聽頁面的改變
//定義介面
public interface OnpagerChanglistenter{
//當頁面改變的時候回掉這個方法position當前頁面的下表
void onScrollToPager(int position);
}
@Override
public void computeScroll() {
if(mScrolier.computeScrollOffset()){
float currX = mScrolier.getCurrX();
Log.e("hh", "computeScroll: "+currX );
scrollTo((int)currX,0);
invalidate();//onDraw();computeScroll()
}
}
//onLayout設定每個孩子在當前的位置大小
//但如果孩子是佈局的話,沒有給的控制元件測量大小,因控制元件沒有測量大小所以就不會顯示出來
//遍歷孩子,給每個孩子指定在螢幕的座標位置
//獲取每一個View孩子進行測量(如佈局:目的就是讓他的孩子也執行onMeasure測量)
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
for (int i = 0; i < getChildCount(); i++) {
View chid=getChildAt(i);
//如果孩子是ViewGroup那麼就會進去測量ViewGroup的孩子View
chid.measure(widthMeasureSpec,heightMeasureSpec);
}
}
//測量onMeasure()說明: lt點(左上)|rb點(右下) 寬度: 右邊的距離減掉左邊的距離
// 高度: 底部的距離減掉頂部的距離
/**
* 1. 測量的時候測量多次
* 2. widthMeasureSpec父層檢視給當前檢視的寬和模式
* 系統的onMeasure所幹的事:
* 1, 根據widthMeasureSpec求得寬度,和父類view給的模式(高以此類推)
* 2, 根據自身的寬度width,和自身的padding 值,相減(減去兩邊){父類的寬頻減去padding值},求得子View可以擁有的寬度newWidth
* 3, 根據newWidth和模式求得一個新的MeasureSpec值:
* MeasureSpec.makeMeasureSpec(newSize,newmode);
* 用新的MeasureSpec來計算View
*
*/
}
上面打完就完成了效果(下面是對慢慢滑動計算的類)
package com.example.administrator.viewgroup_xianxi;
import android.os.SystemClock;
public class MyScroller {
//起始座標
private long totTime=500;
private float scrollX;
private float scrollY;
//移動的距離
private int distanceX;
private int distanceY;
//kaijishijian
private long startTime;
//是否移動完成
private boolean isFinish;
private float mCurrX;
//得到座標
public float getCurrX() {
return mCurrX;
}
public void startScroll(float scrollX, float scrollY, int distanceX, int distanceY) {
this.scrollX=scrollX;
this.scrollY=scrollY;
this.distanceX=distanceX;
this.distanceY=distanceY;
this.startTime= SystemClock.uptimeMillis();//體統開機時間
this.isFinish=false;
}
//true正在移動
//fles移動結束
public boolean computeScrollOffset(){
if(isFinish){
return false;
}
long endTime=SystemClock.uptimeMillis();
//這一小段所發揮的時間
long passTime=endTime-startTime;
if(passTime<totTime){
//還沒有移動結束
//計算平均速度
// float voleCity=distanceX/totTime;
//移動這一小段對應的距離
float distanceSamllx=passTime*distanceX/totTime;
mCurrX = scrollX + distanceSamllx;
}else{
//移動結束
isFinish=true;
mCurrX = scrollX + distanceX;
}
return true;
}
}
位置理解圖
相關文章
- Android 自定義控制元件 ViewPager頭部指示器控制元件 ViewPagerBelowIndicatorAndroid控制元件ViewpagerIndicator
- 自定義ViewPager指示器Viewpager
- ViewPager之標籤的自定義Viewpager
- Android自定義控制元件之自定義組合控制元件Android控制元件
- Android 自定義控制元件玩轉字型變色 打造炫酷ViewPager指示器Android控制元件Viewpager
- Android自定義控制元件——自定義屬性Android控制元件
- 自定義Switch控制元件控制元件
- 控制元件自定義位置控制元件
- 如何自定義控制元件控制元件
- 4. 自定義控制元件(4) --- 自定義屬性控制元件
- Android自定義控制元件之自定義屬性Android控制元件
- 國人自定義React Native開源元件ViewPagerReact Native元件Viewpager
- Flutter 之 自定義控制元件Flutter控制元件
- iOS自定義控制元件 AlertViewiOS控制元件View
- iOS自定義控制元件 SegmentiOS控制元件
- WPF Blend 自定義控制元件控制元件
- 自定義彈幕控制元件控制元件
- 自定義分頁控制元件控制元件
- winform 自定義容器控制元件ORM控制元件
- 自定義控制元件之歌詞RCL控制元件控制元件
- Android自定義組合控制元件之自定義屬性Android控制元件
- C#自定義控制元件:如果定義控制元件的事件C#控制元件事件
- WPF 自定義控制元件的坑(蠢的:自定義控制元件內容不顯示)控制元件
- Flutter 自定義縮放控制元件Flutter控制元件
- iOS自定義控制元件 SlideriOS控制元件IDE
- Qt實現自定義控制元件QT控制元件
- android:建立自定義控制元件Android控制元件
- 自定義UIView UITableViewCell等控制元件UIView控制元件
- 自定義下拉選單控制元件控制元件
- 自定義的ValidationSummary控制元件控制元件
- iOS自定義控制元件:簡易下拉控制元件iOS控制元件
- android 自定義控制元件 自定義屬性詳細介紹Android控制元件
- (Android自定義控制元件)Android自定義狀態提示圖表Android控制元件
- QT常用控制元件(三)——自定義控制元件封裝QT控制元件封裝
- UWP 自定義密碼框控制元件密碼控制元件
- AngularJS自定義表單控制元件AngularJS控制元件
- 【Android】自定義樹形控制元件Android控制元件
- 自定義控制元件總結和思考控制元件