Android Moveview滑屏移動(dòng)視圖類完整實(shí)例
本文示例所述程序?yàn)橐粋€(gè)Android Moveview移動(dòng)視圖類。其主要實(shí)現(xiàn)主屏左右滑屏拖動(dòng)功能,并適時(shí)顯示拖動(dòng)時(shí)候屏幕的顯示情況,該代碼中還包括完整的邏輯。其完整代碼如下:
import android.study.shift.ItemView;
import android.study.shift.MainView;
import android.study.shift.Moveview;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.MeasureSpec;
public class Moveview extends ViewGroup{
private final static int TOUCH_STATE_REST = 0;
private final static int TOUCH_STATE_MOVING = 1;
private final static int MOVE_TO_LEFT = 1;
//private final static int MOVE_TO_RIGHT = 2;
private final static int MOVE_TO_REST = 0;
public final static int MAIN = 0;
public final static int LEFT = 1;
public final static int RIGHT = 2;
private int touch_state = TOUCH_STATE_REST;
private int move_state = MOVE_TO_REST;
private int now_state = MAIN;
private final float WIDTH_RATE = 0.18f;
private MainView main_show_view;
private ItemView left_show_view;
private int min_distance = 30;//此處只是初始化為30 ,其實(shí)不起作用
private int screen_w;
private int screen_h;
private int move_x_v;
private boolean isAimationMoving = false;
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {//處理消息
synchronized (Moveview.this) {//同步
isAimationMoving = true;
int move_change = (int) (screen_w * WIDTH_RATE / 5);
int left = main_show_view.getView().getLeft();
if (msg.what == 1) {//主屏在向右拖曳。。。
move(move_change + left);//參數(shù)為拖出來(lái)后主屏的坐標(biāo)。
}
if (msg.what == 11) {
isAimationMoving = false;
moveToLeft(false); //滿足可以顯示的要求開(kāi)始顯示,false只是一個(gè)判定條件,以區(qū)別按鈕起的效果
}
if (msg.what == 2) {//代表主屏向左在拖曳。。。
move(-1 * move_change + left);
}
if (msg.what == 12) {
isAimationMoving = false;
//moveToRight(false);
}
if (msg.what == 0) {
if (now_state == LEFT) {//如果現(xiàn)在已經(jīng)顯示左邊
move(-1 * move_x_v);//那么還原成主屏
} else {
move(move_x_v);
}
}
if (msg.what == 10) {
isAimationMoving = false;
moveToMain(false);
}
}
}
};
public Moveview(Context context) {
super(context);
}
public Moveview(Context context, AttributeSet attrs) {
super(context, attrs);
}
public Moveview(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void initView() {
if (main_show_view == null) {
main_show_view = new MainView(this.getContext(), this);
left_show_view = new ItemView(this.getContext());
//right_show_view = new ItemView(this.getContext(), "aaa");
}
this.addView(left_show_view.getView());
//this.addView(right_show_view.getView());
this.addView(main_show_view.getView());
}
public void initContent() {
}
public void move(int start) {//本函數(shù)顯示拖動(dòng)的時(shí)候屏幕的顯示情況。
int left = main_show_view.getView().getLeft();//left代表主屏左邊緣的位置坐標(biāo)。
if (now_state == MAIN) {
if (left > 0) {//如果屏幕的左邊被移向右,則left變成正數(shù)
if (move_state != MOVE_TO_LEFT) {
move_state = MOVE_TO_LEFT;
}
left_show_view.getView().setVisibility(View.VISIBLE);//設(shè)置左邊可見(jiàn)
//right_show_view.getView().setVisibility(View.GONE);
} //else if (left < 0) {//如果屏幕的左邊被移向左,則left變成負(fù)數(shù)
//if (move_state != MOVE_TO_RIGHT) {
// move_state = MOVE_TO_RIGHT;
//}
//right_show_view.getView().setVisibility(View.VISIBLE);
//left_show_view.getView().setVisibility(View.GONE);
//}
else {
move_state = MOVE_TO_REST;
}
main_show_view.getView().layout(start, 0, start + screen_w,
screen_h);//參數(shù)依次為左、上、右、下。
} else {
left = (int) (screen_w * WIDTH_RATE);//left為左邊應(yīng)該留出的控件空間,或者主屏左邊應(yīng)該在的位置
if (now_state == RIGHT) {
left = -1 * left;//若狀態(tài)是在右邊空出來(lái),則主屏的左邊為負(fù)數(shù)
}
left = left + start;
main_show_view.getView().layout(left, 0, left + screen_w, screen_h);
}
}
@Override
protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
if (move_state == MOVE_TO_REST) {
if (now_state == MAIN) {
int w = (int) (screen_w * WIDTH_RATE);//留下預(yù)定的寬度,顯示各個(gè)view的參數(shù)設(shè)置。
main_show_view.getView().layout(0, 0, screen_w, screen_h);
left_show_view.getView().layout(0, 0, w, screen_h);
} else if (now_state == LEFT) {
moveToLeft(false);
} else {
}
}
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
main_show_view.getView().measure(widthMeasureSpec, heightMeasureSpec);
left_show_view.getView().measure(MeasureSpec.UNSPECIFIED,//unspecified為未指定的
heightMeasureSpec);
left_show_view.setWidth((int) (screen_w * WIDTH_RATE));//設(shè)置view寬度
super.onMeasure(widthMeasureSpec, heightMeasureSpec);//調(diào)用父類的構(gòu)造函數(shù)
}
private int start_x;
private int start_y;
private boolean isMoved;
public boolean dispatchTouchEvent(MotionEvent ev) {//分發(fā)觸摸消息事件
if (isAimationMoving) {
return super.dispatchTouchEvent(ev);
} else {
int action = ev.getAction();
float x = ev.getX();
float y = ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
super.dispatchTouchEvent(ev);
start_y = (int) y;
move_x_v = 0;
if (this.touch_state == TOUCH_STATE_REST) {
this.touch_state = TOUCH_STATE_MOVING;
start_x = (int) x;
isMoved = false;
move_state = MOVE_TO_REST;
}
break;
case MotionEvent.ACTION_MOVE:
int last_y = (int) y;
int last_x = (int) x;
super.dispatchTouchEvent(ev);
if (!isMoved) {
if (Math.abs(last_y - start_y) > Math.abs(last_x - start_x)) {//如果Y上面移動(dòng)的距離大于X上面移動(dòng)的距離。
super.onTouchEvent(ev);
return true;
} else {//X移動(dòng)距離大于Y
if (Math.abs(last_x - start_x) > 5) {//X移動(dòng)距離大于5就被認(rèn)為移動(dòng)了
isMoved = true;
}
}
}
if (isMoved) {
if (this.touch_state == TOUCH_STATE_MOVING) {
if (Math.abs(last_x - start_x) > 10) {//如果移動(dòng)的X距離大于10
int left = main_show_view.getView().getLeft();
Log.d("msg", "left:" + left);
Log.d("msg", "x:" + last_x);
isMoved = true;
int move_x = last_x - start_x;
if (move_x > 0 && now_state == LEFT) {//方向正確的移動(dòng)才算是移動(dòng)的狀態(tài)
isMoved = false;
break;
}
if (move_x < 0 && now_state == RIGHT) {//如果現(xiàn)在在顯示右邊,那么再向右移就不反應(yīng)。
isMoved = false;
break;
}
if (move_x < 0 && now_state ==MAIN){//如果現(xiàn)在在主屏,向右移動(dòng)也是無(wú)效的
isMoved = false;
break;
}
if (move_x > 234 && now_state ==MAIN){
isMoved = true;//設(shè)置為true那么移動(dòng)還是發(fā)生了,break之后還是會(huì)在ACTIONUP中起作用
break;//break之后不會(huì)執(zhí)行下面的move()語(yǔ)句,
}
if (move_x < -234 && now_state ==LEFT){
isMoved = true;
break;
}
move(move_x);//以移動(dòng)的距離為參數(shù)調(diào)用move()實(shí)現(xiàn)移動(dòng)的動(dòng)態(tài)顯示
}
}
return false;
}
break;
case MotionEvent.ACTION_UP://
if (this.touch_state == TOUCH_STATE_MOVING) {
if (isMoved) {
last_x = (int) x;
if (Math.abs(last_x - start_x) > min_distance) {//
if (now_state == MAIN) {
if (move_state == MOVE_TO_LEFT) {
this.moveToLeft(false);
}
} else {
this.moveToMain(false);
}
} else { //
if (now_state == MAIN) {
this.moveToMain(false);
}
if (now_state == LEFT) {
this.moveToLeft(false);
}
if (now_state == RIGHT) {
//this.moveToRight(false);
}
}
move_state = MOVE_TO_REST;
} else {
super.dispatchTouchEvent(ev);
this.touch_state = TOUCH_STATE_REST;
return false;//
}
}
super.onTouchEvent(ev);
this.touch_state = TOUCH_STATE_REST;
break;
}
return true;
}
}
public boolean getIsMoved() {
return isMoved;
}
public void moveToLeft(boolean b) {
if (!b) {
int move_x = (int) (screen_w * WIDTH_RATE);
left_show_view.getView().layout(0, 0, screen_w, screen_h);
//right_show_view.getView().layout(move_x, 0, move_x * 2, screen_h);
main_show_view.getView().layout(move_x, 0, move_x + screen_w,
screen_h);
now_state = LEFT;//為什么現(xiàn)在又把now_state賦值為left?
}
// else {//else以及括號(hào)中的語(yǔ)句都是為原來(lái)的按鈕準(zhǔn)備的。。。
// mHandler.postDelayed(new Runnable() {//一個(gè)新的可運(yùn)行的函數(shù)
//
// @Override
// public void run() {
// int move_change = (int) (screen_w * WIDTH_RATE / 5);//五分之一要顯示的寬度
// int left = (int) (screen_w * WIDTH_RATE - main_show_view
// .getView().getLeft());//getleft()返回的是主屏左邊緣離左邊的距離
// Message msg = new Message();
// if (left > move_change) {//括號(hào)里面不懂,起什么作用?
// msg.what = 1;
// mHandler.sendMessage(msg);
// mHandler.postDelayed(this, 10);//又調(diào)用自己,基本上非要是小于關(guān)系
// } else {
// msg.what = 11;
// mHandler.sendMessage(msg);
// mHandler.removeCallbacks(this);
// }
// }
// }, 0);
// }
}
public void moveToMain(boolean b) {
if (!b) {
//right_show_view.getView().setVisibility(View.VISIBLE);
left_show_view.getView().setVisibility(View.VISIBLE);
int w = (int) (screen_w * WIDTH_RATE);
main_show_view.getView().layout(0, 0, screen_w, screen_h);
left_show_view.getView().layout(0, 0, w, screen_h);
now_state = MAIN;
}
}
public void initScreenSize(int w, int h) {
this.screen_w = w;
this.screen_h = h;
Log.d("screen", "screen_w:" + w);
this.setKeepScreenOn(true);
min_distance = (int) (screen_w / 12.0);//min_distance在這里又被初始化為屏幕的一個(gè)比例大小
initView();
initContent();
moveToMain(false);
}
public int getNowState() {
return this.now_state;
}
}
- Android使用ViewFlipper和GestrueDetector共同實(shí)現(xiàn)滑屏效果實(shí)例
- Android組件banner實(shí)現(xiàn)左右滑屏效果
- Android利用ViewPager實(shí)現(xiàn)滑動(dòng)廣告板實(shí)例源碼
- Android 開(kāi)發(fā)之BottomBar+ViewPager+Fragment實(shí)現(xiàn)炫酷的底部導(dǎo)航效果
- Android ViewPager相冊(cè)橫向移動(dòng)的實(shí)現(xiàn)方法
- Android 使用viewpager實(shí)現(xiàn)無(wú)限循環(huán)(定時(shí)+手動(dòng))
- Android App中使用ViewPager+Fragment實(shí)現(xiàn)滑動(dòng)切換效果
- Android App中ViewPager與Fragment結(jié)合的一些問(wèn)題解決
- Android App中ViewPager所帶來(lái)的滑動(dòng)沖突問(wèn)題解決方法
- Android ViewPager無(wú)限循環(huán)實(shí)現(xiàn)底部小圓點(diǎn)動(dòng)態(tài)滑動(dòng)
- Android基礎(chǔ)之使用Fragment控制切換多個(gè)頁(yè)面
- Android基礎(chǔ)之Fragment與Activity交互詳解
- Android基于ViewPager+Fragment實(shí)現(xiàn)左右滑屏效果的方法
相關(guān)文章
Activity透明/半透明效果的設(shè)置transparent(兩種實(shí)現(xiàn)方法)
兩種方法實(shí)現(xiàn)Activity透明/半透明效果的設(shè)置,代碼思路很有調(diào)理,感興趣的朋友可以參考下,希望本文可以幫助到你2013-02-02
android仿即刻點(diǎn)贊文字部分的自定義View的示例代碼
本篇文章主要介紹了android仿即刻點(diǎn)贊文字部分的自定義View的示例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11
Android自定義view實(shí)現(xiàn)輸入框效果
這篇文章主要為大家詳細(xì)介紹了Android自定義view實(shí)現(xiàn)輸入框效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-03-03
Android如何實(shí)現(xiàn)時(shí)間線效果
這篇文章主要介紹了?Android如何實(shí)現(xiàn)時(shí)間線效果,下面文章圍繞?Android如何實(shí)現(xiàn)時(shí)間線效果的相關(guān)資料展開(kāi)詳細(xì)內(nèi)容,具有一定的參考價(jià)值?,需要的朋友可以參考一下2021-11-11
Android中分析Jetpack?Compose動(dòng)畫內(nèi)部的實(shí)現(xiàn)原理
這篇文章主要介紹了Android中分析Jetpack?Compose動(dòng)畫內(nèi)部的實(shí)現(xiàn)原理,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的小伙伴可以參考一下2022-09-09
Android MediaPlayer音頻播放器封裝示例淺析
Android提供了許多方法來(lái)控制播放的音頻/視頻文件和流。其中該方法是通過(guò)一類稱為MediaPlayer。Android是提供MediaPlayer類訪問(wèn)內(nèi)置的媒體播放器的服務(wù),如播放音頻,視頻等為了使用MediaPlayer,我們要調(diào)用這個(gè)類的靜態(tài)create()方法2023-04-04
Android編程中ViewPage判斷左右滑動(dòng)方向的方法
這篇文章主要介紹了Android編程中ViewPage判斷左右滑動(dòng)方向的方法,涉及Android中ViewPage針對(duì)滑動(dòng)判定的相關(guān)技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2015-10-10
Android自定義控件之圓形/圓角的實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了Android自定義控件之圓形/圓角的實(shí)現(xiàn)代碼,感興趣的小伙伴們可以參考一下2016-03-03

