日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android多个下拉控件,Android实现支持所有View的通用的下拉刷新控件

發(fā)布時間:2024/3/13 Android 58 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android多个下拉控件,Android实现支持所有View的通用的下拉刷新控件 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

下拉刷新對于一個app來說是必不可少的一個功能,在早期大多數(shù)使用的是chrisbanes的PullToRefresh,或是修改自該框架的其他庫。而到現(xiàn)在已經(jīng)有了更多的選擇,github上還是有很多體驗不錯的下拉刷新。

而下拉刷新主要有兩種實現(xiàn)方式:1. 在ListView中添加header和footer,監(jiān)聽ListView的滑動事件,動態(tài)設置header/footer的高度,但是這種方式只適用于ListView,RecyclerView。

2. 第二種方式則是繼承ViewGroup或其子類,監(jiān)聽事件,通過scroll或Layout的方式移動child。如圖(又分兩種情況)

Layout時將header放到屏幕外面,target則填充滿屏幕。這個也是SwipeRefreshLayout的實現(xiàn)原理(第二種,只下拉h(huán)eader)

這兩種(指的是繼承ListView或繼承ViewGroup)下拉刷新的實現(xiàn)方式主要有以下區(qū)別

而今天,我打算先講第二種方式實現(xiàn)方式,繼承ViewGroup,代碼可以直接參考SwipeRefreshLayout,或者pullToRefresh,或者ultra-pull-to-refresh

一、思考和需求

下拉刷新需要幾個狀態(tài):Reset–> Pull – > Refreshing – >Completed –>Reset

為了應對各式各樣的下拉刷新設計,我們應該提供設置自定義的Header,開發(fā)者可以通過實現(xiàn)接口從而自定義自己的header。

而且header可以有兩種顯示方式,一種是只下拉h(huán)eader,另外一種則是header和target一起下拉。

二、著手實現(xiàn)代碼

2.1 定義Header的接口,創(chuàng)建自定義Layout

/**

* Created by AItsuki on 2016/6/13.

*

*/

public enum State {

RESET, PULL, LOADING, COMPLETE

}

/**

* Created by AItsuki on 2016/6/13.

*

*/

public interface RefreshHeader {

/**

* 松手,頭部隱藏后會回調(diào)這個方法

*/

void reset();

/**

* 下拉出頭部的一瞬間調(diào)用

*/

void pull();

/**

* 正在刷新的時候調(diào)用

*/

void refreshing();

/**

* 頭部滾動的時候持續(xù)調(diào)用

* @param currentPos target當前偏移高度

* @param lastPos target上一次的偏移高度

* @param refreshPos 可以松手刷新的高度

* @param isTouch 手指是否按下狀態(tài)(通過scroll自動滾動時需要判斷)

* @param state 當前狀態(tài)

*/

void onPositionChange(float currentPos, float lastPos, float refreshPos, boolean isTouch, State state);

/**

* 刷新成功的時候調(diào)用

*/

void complete();

}

package com.aitsuki.custompulltorefresh;

import android.content.Context;

import android.graphics.Color;

import android.util.AttributeSet;

import android.view.View;

import android.view.ViewConfiguration;

import android.view.ViewGroup;

import android.widget.ImageView;

/**

* Created by AItsuki on 2016/6/13.

* -

*/

public class RefreshLayout extends ViewGroup {

private View refreshHeader;

private View target;

private int currentTargetOffsetTop; // target偏移距離

private boolean hasMeasureHeader; // 是否已經(jīng)計算頭部高度

private int touchSlop;

private int headerHeight; // header高度

private int totalDragDistance; // 需要下拉這個距離才進入松手刷新狀態(tài),默認和header高度一致

public RefreshLayout(Context context) {

this(context, null);

}

public RefreshLayout(Context context, AttributeSet attrs) {

super(context, attrs);

touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

// 添加默認的頭部,先簡單的用一個ImageView代替頭部

ImageView imageView = new ImageView(context);

imageView.setImageResource(R.drawable.one_piece);

imageView.setBackgroundColor(Color.BLACK);

setRefreshHeader(imageView);

}

/**

* 設置自定義header

*/

public void setRefreshHeader(View view) {

if (view != null && view != refreshHeader) {

removeView(refreshHeader);

// 為header添加默認的layoutParams

ViewGroup.LayoutParams layoutParams = view.getLayoutParams();

if (layoutParams == null) {

layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);

view.setLayoutParams(layoutParams);

}

refreshHeader = view;

addView(refreshHeader);

}

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

if (target == null) {

ensureTarget();

}

if (target == null) {

return;

}

// ----- measure target -----

// target占滿整屏

target.measure(MeasureSpec.makeMeasureSpec(

getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),

MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(

getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), MeasureSpec.EXACTLY));

// ----- measure refreshView-----

measureChild(refreshHeader, widthMeasureSpec, heightMeasureSpec);

if (!hasMeasureHeader) { // 防止header重復測量

hasMeasureHeader = true;

headerHeight = refreshHeader.getMeasuredHeight(); // header高度

totalDragDistance = headerHeight; // 需要pull這個距離才進入松手刷新狀態(tài)

}

}

@Override

protected void onLayout(boolean changed, int l, int t, int r, int b) {

final int width = getMeasuredWidth();

final int height = getMeasuredHeight();

if (getChildCount() == 0) {

return;

}

if (target == null) {

ensureTarget();

}

if (target == null) {

return;

}

// onLayout執(zhí)行的時候,要讓target和header加上偏移距離(初始0),因為有可能在滾動它們的時候,child請求重新布局,從而導致target和header瞬間回到原位。

// target鋪滿屏幕

final View child = target;

final int childLeft = getPaddingLeft();

final int childTop = getPaddingTop() + currentTargetOffsetTop;

final int childWidth = width - getPaddingLeft() - getPaddingRight();

final int childHeight = height - getPaddingTop() - getPaddingBottom();

child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);

// header放到target的上方,水平居中

int refreshViewWidth = refreshHeader.getMeasuredWidth();

refreshHeader.layout((width / 2 - refreshViewWidth / 2),

-headerHeight + currentTargetOffsetTop,

(width / 2 + refreshViewWidth / 2),

currentTargetOffsetTop);

}

/**

* 將第一個Child作為target

*/

private void ensureTarget() {

// Don't bother getting the parent height if the parent hasn't been laid

// out yet.

if (target == null) {

for (int i = 0; i < getChildCount(); i++) {

View child = getChildAt(i);

if (!child.equals(refreshHeader)) {

target = child;

break;

}

}

}

}

}

MainActivity中的布局如下,先用一個TextView作為Target

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context="com.aitsuki.custompulltorefresh.MainActivity">

android:layout_width="match_parent"

android:layout_height="match_parent">

android:layout_width="match_parent"

android:layout_height="match_parent"

android:text="Target"

android:textSize="30sp"

android:gravity="center"

android:background="#FFDAB9"

/>

運行后結(jié)果如圖如下,但是我們還沒有監(jiān)聽事件,所以此時還無法滑動。

2.2 處理事件分發(fā)

控件已經(jīng)測量布局好了,現(xiàn)在就開始處理事件分發(fā),對于事件分發(fā)還不了解的應該先去復習下……

對于多點觸控的處理:記錄活動手指的id(activePointerId),通過此ID獲取move事件的坐標。

1.在手指按下的時候,記錄下activePointerId

2.第二根手指按下的時候,更新activePointerId。(我們讓第二根手指作為活動手指,忽略第一個手指的move)

3.當其中一根手指抬起時,如果是第一根手指,那么不做處理,如果是第二根手指抬起,也就是活動手指抬起的話,將活動手指改回第一根。

對于事件分發(fā)一般有兩種處理方式1. 在onIntercept + onTouchEvnet中處理

2. 在dispatchTouchEvent中處理

在這里我選擇了第二種方式

首先了解DispatchTouchEvent返回值的含義重寫dispatchTouchEvent的時候,無論你是return true,亦或是return false都會導致child接受不到事件。

return true : 告訴parent,這個事件我消費了。如果這個是down事件,那么我就會作為一個target或者說handle(事件持有者),后續(xù)的move事件或者up事件等,都會直接分發(fā)到我這里,不繼續(xù)往下分發(fā)。

return false:告訴parent,這個事件我不需要,那么會交回給parent的onTouchEvnet處理

只有return super.dispatchTouchEvent的時候才會將事件繼續(xù)往下傳遞。

上面只說了最簡單的一點,如果對事件分發(fā)不了解的話需要看看,真的很重要。

分析

在dispatch中,即使child響應了事件,我們也能拿到所有事件。

這樣我們就可以很簡單的控制頭部是否能下拉,那么如何攔截child的事件呢?

可以在合適的時候分發(fā)一個cancel事件給child,那么就相當于攔截了!

雖然我們一直都響應著事件,但肯定是不能所有事件都接收的,以下情況是需要我們處理的

1.如果是下拉,并且child不能往上滾動

2.如果上劃,并且target不在頂部的時候

3.如果是這些時候,我們攔截child的事件(派發(fā)cancel事件)

代碼如下

@Override

public boolean dispatchTouchEvent(MotionEvent ev) {

if (!isEnabled() || target == null) {

return super.dispatchTouchEvent(ev);

}

final int actionMasked = ev.getActionMasked(); // support Multi-touch

switch (actionMasked) {

case MotionEvent.ACTION_DOWN:

Log.e(TAG, "ACTION_DOWN");

activePointerId = ev.getPointerId(0);

isTouch = true; // 手指是否按下

hasSendCancelEvent = false;

mIsBeginDragged = false; // 是否開始下拉

lastTargetOffsetTop = currentTargetOffsetTop; // 上一次target的偏移高度

currentTargetOffsetTop = target.getTop(); // 當前target偏移高度

initDownX = lastMotionX = ev.getX(0); // 手指按下時的坐標

initDownY = lastMotionY = ev.getY(0);

super.dispatchTouchEvent(ev);

return true; // return true,否則可能接收不到move和up事件

case MotionEvent.ACTION_MOVE:

if (activePointerId == INVALID_POINTER) {

Log.e(TAG, "Got ACTION_MOVE event but don't have an active pointer id.");

return super.dispatchTouchEvent(ev);

}

lastEvent = ev; // 最后一次move事件

float x = ev.getX(MotionEventCompat.findPointerIndex(ev,activePointerId));

float y = ev.getY(MotionEventCompat.findPointerIndex(ev,activePointerId));

float xDiff = x - lastMotionX;

float yDiff = y - lastMotionY;

float offsetY = yDiff * DRAG_RATE;

lastMotionX = x;

lastMotionY = y;

if(!mIsBeginDragged && Math.abs(y - initDownY) > touchSlop) {

mIsBeginDragged = true;

}

if (mIsBeginDragged) {

boolean moveDown = offsetY > 0; // ↓

boolean canMoveDown = canChildScrollUp();

boolean moveUp = !moveDown; // ↑

boolean canMoveUp = currentTargetOffsetTop > START_POSITION;

// 判斷是否攔截事件

if ((moveDown && !canMoveDown) || (moveUp && canMoveUp)) {

moveSpinner(offsetY);

return true;

}

}

break;

case MotionEvent.ACTION_CANCEL:

case MotionEvent.ACTION_UP:

isTouch = false;

activePointerId = INVALID_POINTER;

break;

case MotionEvent.ACTION_POINTER_DOWN:

int pointerIndex = MotionEventCompat.getActionIndex(ev);

if (pointerIndex < 0) {

Log.e(TAG, "Got ACTION_POINTER_DOWN event but have an invalid action index.");

return super.dispatchTouchEvent(ev);

}

lastMotionX = ev.getX(pointerIndex);

lastMotionY = ev.getY(pointerIndex);

activePointerId = MotionEventCompat.getPointerId(ev, pointerIndex);

break;

case MotionEvent.ACTION_POINTER_UP:

onSecondaryPointerUp(ev);

lastMotionY = ev.getY(ev.findPointerIndex(activePointerId));

lastMotionX = ev.getX(ev.findPointerIndex(activePointerId));

break;

}

return super.dispatchTouchEvent(ev);

}

private void onSecondaryPointerUp(MotionEvent ev) {

final int pointerIndex = MotionEventCompat.getActionIndex(ev);

final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);

if (pointerId == activePointerId) {

// This was our active pointer going up. Choose a new

// active pointer and adjust accordingly.

final int newPointerIndex = pointerIndex == 0 ? 1 : 0;

lastMotionY = ev.getY(newPointerIndex);

lastMotionX = ev.getX(newPointerIndex);

activePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);

}

}

public boolean canChildScrollUp() {

if (android.os.Build.VERSION.SDK_INT < 14) {

if (target instanceof AbsListView) {

final AbsListView absListView = (AbsListView) target;

return absListView.getChildCount() > 0

&& (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)

.getTop() < absListView.getPaddingTop());

} else {

return ViewCompat.canScrollVertically(target, -1) || target.getScrollY() > 0;

}

} else {

return ViewCompat.canScrollVertically(target, -1);

}

}

以上就是事件的處理,我們還需要在header下拉之前發(fā)送cancel事件給child

private void moveSpinner(float diff) {

int offset = Math.round(diff);

if (offset == 0) {

return;

}

// 發(fā)送cancel事件給child

if (!hasSendCancelEvent && isTouch && currentTargetOffsetTop > START_POSITION) {

sendCancelEvent();

hasSendCancelEvent = true;

}

int targetY = Math.max(0, currentTargetOffsetTop + offset); // target不能移動到小于0的位置……

offset = targetY - currentTargetOffsetTop;

setTargetOffsetTopAndBottom(offset);

}

private void setTargetOffsetTopAndBottom(int offset) {

if (offset == 0) {

return;

}

target.offsetTopAndBottom(offset);

refreshHeader.offsetTopAndBottom(offset);

lastTargetOffsetTop = currentTargetOffsetTop;

currentTargetOffsetTop = target.getTop();

invalidate();

}

private void sendCancelEvent() {

if (lastEvent == null) {

return;

}

MotionEvent ev = MotionEvent.obtain(lastEvent);

ev.setAction(MotionEvent.ACTION_CANCEL);

super.dispatchTouchEvent(ev);

}

代碼有點多,不過沒關系,其實很多都是從SwipeRefreshLayout中復制過來的。

我們來看看代碼運行后的效果,很不錯,就是模擬器錄屏有點卡=。=

換成ListView試試, 也沒有問題。

多點觸控也是可以的,但是模擬器我沒法演示了。

2.3 添加自動滾動

頭雖然可以下拉了, 但是拉下來后就不會回去了啊,我們需要在手指松開讓頭部自動回到原位。

可以使用動畫,可以使用ValueAnimator計算距離移動,也可以使用Scroller計算距離移動。

但是選擇第三種是比較好的,為什么呢。

首先如果使用動畫,在回去的過程中我們無法下拉,我們想做的是一個可以在任何時候都能上下拉的,就像ListView添加頭的哪種效果。

valueAnimator也是,不好停止。

但是scroller卻可以使用forceFinish強行停止計算。

松開手指時,我們通過scroller計算每次移動的offset,然后調(diào)用moveSpinner即可。

在手指按下的時候,需要停止scroller。

我們先寫一個內(nèi)部類,封裝一下滾動功能

private class AutoScroll implements Runnable {

private Scroller scroller;

private int lastY;

public AutoScroll() {

scroller = new Scroller(getContext());

}

@Override

public void run() {

boolean finished = !scroller.computeScrollOffset() || scroller.isFinished();

if (!finished) {

int currY = scroller.getCurrY();

int offset = currY - lastY;

lastY = currY;

moveSpinner(offset); // 調(diào)用此方法移動header和target

post(this);

onScrollFinish(false);

} else {

stop();

onScrollFinish(true);

}

}

public void scrollTo(int to, int duration) {

int from = currentTargetOffsetTop;

int distance = to - from;

stop();

if (distance == 0) {

return;

}

scroller.startScroll(0, 0, 0, distance, duration);

post(this);

}

private void stop() {

removeCallbacks(this);

if (!scroller.isFinished()) {

scroller.forceFinished(true);

}

lastY = 0;

}

}

然后這個是回調(diào),暫時用戶不上,但還是先寫好吧。

/**

* 在scroll結(jié)束的時候會回調(diào)這個方法

* @param isForceFinish 是否是強制結(jié)束的

*/

private void onScrollFinish(boolean isForceFinish) {

}

我們在構(gòu)造中初始化AutoScroll,然后分別在ActionDown和ActionUp中分別調(diào)用stop和scrollto即可,如下

case MotionEvent.ACTION_DOWN:

//...

autoScroll.stop();

//...

break

case MotionEvent.ACTION_CANCEL:

case MotionEvent.ACTION_UP:

//...

if(currentTargetOffsetTop > START_POSITION) {

autoScroll.scrollTo(START_POSITION, SCROLL_TO_TOP_DURATION);

}

//...

運行效果如下圖

2.4 添加刷新狀態(tài)

最開始的時候我們也新建了一個枚舉,設置了幾種狀態(tài),分別是 RESET, PULL, LOADING, COMPLETE

而我們的初始狀態(tài)應該為RESET

private State state = State.RESET;

再分析一下,這幾種狀態(tài)什么時候互相切換:

1. 在RESET狀態(tài)時,第一次下拉出現(xiàn)header的時候,設置狀態(tài)變成PULL

2. 在PULL或者COMPLETE狀態(tài)時,header回到頂部的時候,狀態(tài)變回RESET

3. 如果是從底部回到頂部的過程(往上滾動),并且手指是松開狀態(tài), 并且當前是PULL狀態(tài),狀態(tài)變成LOADING,這時候我們需要強制停止autoScroll。并且正在刷新中的偵聽器也在這里調(diào)用(onRefresh())

4. 在LOADING狀態(tài)中,想變成其他狀態(tài),需要提供公共方法給外部調(diào)用

首先,我們先寫一個改變狀態(tài)的方法,在狀態(tài)改變的同時要回調(diào)給header。

private void changeState(State state) {

this.state = state;

RefreshHeader refreshHeader = this.refreshHeader instanceof RefreshHeader ? ((RefreshHeader) this.refreshHeader) : null;

if (refreshHeader != null) {

switch (state) {

case RESET:

refreshHeader.reset();

break;

case PULL:

refreshHeader.pull();

break;

case LOADING:

refreshHeader.refreshing();

break;

case COMPLETE:

refreshHeader.complete();

break;

}

}

}

還有,提供外部設置刷新成功的方法。

因為刷新成功后需要將header滾動回原位,所以需要做以下判斷

1. 如果已經(jīng)在原位,那么直接將狀態(tài)改成Reset

2. 如果不在原位,延時500毫秒后自動滾動回原位。這里延時500毫秒是為了展示刷新成功的提示,否則在網(wǎng)速很快的情況下,刷新成功后header立即回到原位體驗性不好,感覺就像是下拉后立即就自動回去了。

3. 在自動回滾時還需要判斷當前手指是否在觸摸狀態(tài),如果正在觸摸,代表用戶可能并不想header回去,所以這時候我們不能讓頭部滾動。

4. 再者就是,如果在延時的500內(nèi),用戶按下了手指,我們需要將這個runnable取消,在ActionDown中RemoveCallBack即可。總的來說一句話就是,用戶必須持有header的絕對控制權(quán),在手指按下時,header不應該出現(xiàn)自動滾動的情況。

public void refreshComplete() {

changeState(State.COMPLETE);

// if refresh completed and the target at top, change state to reset.

if (currentTargetOffsetTop == START_POSITION) {

changeState(State.RESET);

} else {

// waiting for a time to show refreshView completed state.

// at next touch event, remove this runnable

if (!isTouch) {

postDelayed(delayToScrollTopRunnable, SHOW_COMPLETED_TIME);

}

}

}

// 刷新成功,顯示500ms成功狀態(tài)再滾動回頂部,這個runnalbe需要在ActionDown事件中Remove

private Runnable delayToScrollTopRunnable = new Runnable() {

@Override

public void run() {

autoScroll.scrollTo(START_POSITION, SCROLL_TO_TOP_DURATION);

}

};

提供設置正在刷新回調(diào)的方法

當用戶松開手指,進入刷新狀態(tài)時我們需要回調(diào)這個方法。

// 定義一個偵聽器

public interface OnRefreshListener {

void onRefresh();

}

// 提供外部設置方法

public void setRefreshListener(OnRefreshListener refreshListener) {

this.refreshListener = refreshListener;

}

做完以上幾部,我們算是完成了LOADING到COMPLETE的狀態(tài)切換,余下的幾個狀態(tài)我們則需要在movespinner這個方法中控制,上面也已經(jīng)分析過了邏輯,那么可以直接看代碼了。

private void moveSpinner(float diff) {

int offset = Math.round(diff);

if (offset == 0) {

return;

}

// 發(fā)送cancel事件給child

if (!hasSendCancelEvent && isTouch && currentTargetOffsetTop > START_POSITION) {

sendCancelEvent();

hasSendCancelEvent = true;

}

int targetY = Math.max(0, currentTargetOffsetTop + offset); // target不能移動到小于0的位置……

offset = targetY - currentTargetOffsetTop;

// 1. 在RESET狀態(tài)時,第一次下拉出現(xiàn)header的時候,設置狀態(tài)變成PULL

if (state == State.RESET && currentTargetOffsetTop == START_POSITION && targetY > 0) {

changeState(State.PULL);

}

// 2. 在PULL或者COMPLETE狀態(tài)時,header回到頂部的時候,狀態(tài)變回RESET

if (currentTargetOffsetTop > START_POSITION && targetY <= START_POSITION) {

if (state == State.PULL || state == State.COMPLETE) {

changeState(State.RESET);

}

}

// 3. 如果是從底部回到頂部的過程(往上滾動),并且手指是松開狀態(tài), 并且當前是PULL狀態(tài),狀態(tài)變成LOADING,這時候我們需要強制停止autoScroll

if (state == State.PULL && !isTouch && currentTargetOffsetTop > totalDragDistance && targetY <= totalDragDistance) {

autoScroll.stop();

changeState(State.LOADING);

if (refreshListener != null) {

refreshListener.onRefresh();

}

// 因為判斷條件targetY <= totalDragDistance,會導致不能回到正確的刷新高度(有那么一丁點偏差),調(diào)整change

int adjustOffset = totalDragDistance - targetY;

offset += adjustOffset;

}

setTargetOffsetTopAndBottom(offset);

// 別忘了回調(diào)header的位置改變方法。

if(refreshHeader instanceof RefreshHeader) {

((RefreshHeader) refreshHeader)

.onPositionChange(currentTargetOffsetTop, lastTargetOffsetTop, totalDragDistance, isTouch,state);

}

}

而ActionUp的時候也不能單純的讓header回到頂部了,而是需要通過判斷狀態(tài),回到刷新高度亦或是回到頂部。

1. 刷新狀態(tài),回到刷新高度

2. 否則,回到頂部

我們將原本在ActionUp中的autoScroll.scrollto(…)抽取成一個方法再調(diào)用,如下

private void finishSpinner() {

if (state == State.LOADING) {

if (currentTargetOffsetTop > totalDragDistance) {

autoScroll.scrollTo(totalDragDistance, SCROLL_TO_REFRESH_DURATION);

}

} else {

autoScroll.scrollTo(START_POSITION, SCROLL_TO_TOP_DURATION);

}

}

好了,大功告成!在changeState方法中添加Toast打印一下狀態(tài),來運行下!

Toast.makeText(getContext(), state.toString(), Toast.LENGTH_SHORT).show();

別忘記在Activity中調(diào)用refreshComplete方法,我們延時三秒后設置刷新成功!

以下是Activity中的調(diào)用:

final RefreshLayout refreshLayout = (RefreshLayout) findViewById(R.id.refreshLayout);

if (refreshLayout != null) {

// 刷新狀態(tài)的回調(diào)

refreshLayout.setRefreshListener(new RefreshLayout.OnRefreshListener() {

@Override

public void onRefresh() {

// 延遲3秒后刷新成功

refreshLayout.postDelayed(new Runnable() {

@Override

public void run() {

refreshLayout.refreshComplete();

}

}, 3000);

}

});

}

運行結(jié)果:我們演示幾種情況

下拉 – >回到頂部 (pull –> reset)

下拉 –>刷新 –> 刷新成功 –> 回到頂部(pull–>loading–>complete–>reset)

下拉 –>刷新 –> 刷新成功 –> 回到頂部(手指按下,不讓header回到頂部)

完全沒有問題,體驗還是可以的!這樣我們就完成了一個下拉刷新控件了!

三、自定義默認的Header

下拉刷新是弄好了,但是我們的header也太寒磣太敷衍了吧!

現(xiàn)在我們就來自定義一個header,包含一個旋轉(zhuǎn)的箭頭,還有文字提示!但是我不準備提供時間提示了~普通點,和QQ一樣的

首先我們需要一些圖片資源,從QQ的apk解壓獲取到

先來定義幾個旋轉(zhuǎn)動畫

rotate_down.xml

android:duration="150"

android:fillAfter="true"

android:fromDegrees="-180"

android:pivotX="50%"

android:pivotY="50%"

android:repeatCount="0"

android:toDegrees="0" />

rotate_up.xml

android:duration="150"

android:fillAfter="true"

android:fromDegrees="0"

android:pivotX="50%"

android:pivotY="50%"

android:toDegrees="180" />

rotate_infinite.xml

android:duration="150"

android:fillAfter="true"

android:fromDegrees="180"

android:interpolator="@android:anim/linear_interpolator"

android:pivotX="50%"

android:pivotY="50%"

android:repeatCount="0"

android:toDegrees="0" />

header代碼如下

import android.content.Context;

import android.util.AttributeSet;

import android.view.View;

import android.view.animation.Animation;

import android.view.animation.AnimationUtils;

import android.widget.FrameLayout;

import android.widget.TextView;

/**

* Created by AItsuki on 2016/6/15.

*

*/

public class QQRefreshHeader extends FrameLayout implements RefreshHeader {

private Animation rotate_up;

private Animation rotate_down;

private Animation rotate_infinite;

private TextView textView;

private View arrowIcon;

private View successIcon;

private View loadingIcon;

public QQRefreshHeader(Context context) {

this(context, null);

}

public QQRefreshHeader(Context context, AttributeSet attrs) {

super(context, attrs);

// 初始化動畫

rotate_up = AnimationUtils.loadAnimation(context , R.anim.rotate_up);

rotate_down = AnimationUtils.loadAnimation(context , R.anim.rotate_down);

rotate_infinite = AnimationUtils.loadAnimation(context , R.anim.rotate_infinite);

inflate(context, R.layout.header_qq, this);

textView = (TextView) findViewById(R.id.text);

arrowIcon = findViewById(R.id.arrowIcon);

successIcon = findViewById(R.id.successIcon);

loadingIcon = findViewById(R.id.loadingIcon);

}

@Override

public void reset() {

textView.setText(getResources().getText(R.string.qq_header_reset));

successIcon.setVisibility(INVISIBLE);

arrowIcon.setVisibility(VISIBLE);

arrowIcon.clearAnimation();

loadingIcon.setVisibility(INVISIBLE);

loadingIcon.clearAnimation();

}

@Override

public void pull() {

}

@Override

public void refreshing() {

arrowIcon.setVisibility(INVISIBLE);

loadingIcon.setVisibility(VISIBLE);

textView.setText(getResources().getText(R.string.qq_header_refreshing));

arrowIcon.clearAnimation();

loadingIcon.startAnimation(rotate_infinite);

}

@Override

public void onPositionChange(float currentPos, float lastPos, float refreshPos, boolean isTouch, State state) {

// 往上拉

if (currentPos < refreshPos && lastPos >= refreshPos) {

if (isTouch && state == State.PULL) {

textView.setText(getResources().getText(R.string.qq_header_pull));

arrowIcon.clearAnimation();

arrowIcon.startAnimation(rotate_down);

}

// 往下拉

} else if (currentPos > refreshPos && lastPos <= refreshPos) {

if (isTouch && state == State.PULL) {

textView.setText(getResources().getText(R.string.qq_header_pull_over));

arrowIcon.clearAnimation();

arrowIcon.startAnimation(rotate_up);

}

}

}

@Override

public void complete() {

loadingIcon.setVisibility(INVISIBLE);

loadingIcon.clearAnimation();

successIcon.setVisibility(VISIBLE);

textView.setText(getResources().getText(R.string.qq_header_completed));

}

}

我們來看看運行結(jié)果,完美~

四、自動下拉刷新

是不是覺得還少了點什么?沒錯,就是自動刷新了!

很多時候,我們進入某個頁面,初始化是需要自動刷新數(shù)據(jù),這時候就需要用到自動刷新了,不需要用戶手動。

分析:

1. 刷新狀態(tài)都是在moveSpinner中變更的,而autoScroll正好是調(diào)用moveSpinner實現(xiàn)滾動

2. 我們可以調(diào)用autoScroll方法,讓它滾動到刷新高度,然后再調(diào)用finishSpinner方法,讓控件進入Loading狀態(tài)

3. 自動刷新一般是在Activity的onCreate的這個生命周期執(zhí)行,此時界面可能還沒有繪制完畢,可以通過postDelay方法延遲個幾百毫秒,保證界面顯示正常。

4. 而如果在postDelay的延遲時間中,用戶如果點擊了界面,我們應該將自動刷新功能移除。

首先我們定義公共方法:

public void autoRefresh() {

autoRefresh(500);

}

/**

* 在onCreate中調(diào)用autoRefresh,此時View可能還沒有初始化好,需要延長一段時間執(zhí)行。

*

* @param duration 延時執(zhí)行的毫秒值

*/

public void autoRefresh(long duration) {

if (state != State.RESET) {

return;

}

postDelayed(autoRefreshRunnable, duration);

}

runnable

// 自動刷新,需要等View初始化完畢才調(diào)用,否則頭部不會滾動出現(xiàn)

private Runnable autoRefreshRunnable = new Runnable() {

@Override

public void run() {

// 標記當前是自動刷新狀態(tài),finishScroll調(diào)用時需要判斷

// 在actionDown事件中重新標記為false

isAutoRefresh = true;

changeState(State.PULL);

autoScroll.scrollTo(totalDragDistance, SCROLL_TO_REFRESH_DURATION);

}

};

當autoScroll滾動結(jié)束的時候,會回調(diào)這個方法,判斷如果是自動刷新,將狀態(tài)設置為Loading,并且調(diào)用finishSpinner方法。

/**

* 滾動結(jié)束回調(diào)

*

* @param isForceFinish 是否強制停止

*/

private void onScrollFinish(boolean isForceFinish) {

if (isAutoRefresh && !isForceFinish) {

isAutoRefresh = false;

changeState(State.LOADING);

if (refreshListener != null) {

refreshListener.onRefresh();

}

finishSpinner();

}

}

搞定,在Activity中調(diào)用

refreshLayout.autoRefresh();

五、添加滑動阻力

目前還有個問題,控件可以無限下拉(多點觸控),我們應該讓阻力隨著滑動距離的增大而逐漸增加,直到劃不動為止。

我們可以用到這個方程

y是阻力,控制在0~1。

x是target偏移量超出刷新高度的百分比,控制在0~2。

代碼如下,寫在moveSpinnner中。

// y = x - (x/2)^2

float extraOS = targetY - totalDragDistance;

float slingshotDist = totalDragDistance;

float tensionSlingshotPercent = Math.max(0, Math.min(extraOS, slingshotDist * 2) / slingshotDist);

float tensionPercent = (float) (tensionSlingshotPercent - Math.pow(tensionSlingshotPercent / 2, 2));

if(offset > 0) { // 下拉的時候才添加阻力

offset = (int) (offset * (1f - tensionPercent));

targetY = Math.max(0, currentTargetOffsetTop + offset);

}

那么,一個體驗還算不錯的下拉刷新控件就這么完成了

部分代碼參考自SwipeRefreshLayout和UltraPullToRefresh

這是Demo下載地址:

https://github.com/AItsuki/CustomPullToRefresh

下一篇博文不出意外應該會實現(xiàn)ListView和Recycler的下拉刷新和加載更多的功能,主要特點就是,他們都可以直接使用本篇文中實現(xiàn)的QQheader。

出處: http://blog.csdn.net/u010386612/article/details/51372696

本文出自:【AItsuki的博客】

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

總結(jié)

以上是生活随笔為你收集整理的android多个下拉控件,Android实现支持所有View的通用的下拉刷新控件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

亚洲视频axxx| 亚洲v精品| 99精品在线观看 | 日本午夜免费福利视频 | 国产在线视频不卡 | 亚洲成年人在线播放 | 91麻豆免费看 | 欧美大片在线看免费观看 | 国产视频在线观看免费 | 视频一区在线免费观看 | 91av在线电影| 国产区网址 | 国产在线美女 | 91亚洲在线观看 | 人人爽久久久噜噜噜电影 | 日韩精品视频在线观看网址 | 黄色影院在线免费观看 | 久草电影免费在线观看 | 蜜臀av性久久久久蜜臀aⅴ流畅 | 在线播放国产一区二区三区 | 黄色在线观看网站 | 国产精品毛片一区视频 | 国产精品免费视频一区二区 | 婷婷.com| 精品美女久久久久久免费 | 99久久婷婷国产 | 天天色天天操天天爽 | 在线影视 一区 二区 三区 | 亚洲少妇激情 | 亚洲爱视频 | 国产黄视频在线观看 | 欧美性极品xxxx娇小 | 欧美一级日韩三级 | 国产一级片在线播放 | 午夜精品视频在线 | 九九热re| 久久国产综合视频 | 天天色图 | 国产精品久久电影网 | 日韩免费看 | 免费在线国产视频 | wwwav视频 | 在线观看韩日电影免费 | 久久免费的视频 | av免费网站观看 | 麻豆精品国产传媒 | 国产精品久久久久久久免费大片 | av在线a| 久久综合九色综合欧美狠狠 | jizz欧美性9 国产一区高清在线观看 | 天堂网av在线 | 在线观看第一页 | 丁香电影小说免费视频观看 | 一区二区三区在线看 | 九九免费在线看完整版 | 亚洲黄色小说网 | 免费看一级一片 | 午夜精品福利一区二区三区蜜桃 | 欧美人体xx | 国产精品成人aaaaa网站 | 在线国产日本 | 亚洲狠狠操| 伊人手机在线 | 久久久久久久久久久网 | 日日摸日日添夜夜爽97 | 激情校园亚洲 | 亚洲激情电影在线 | www.色午夜.com | 在线观看视频你懂得 | 九九九九九国产 | 9热精品| 在线看一级片 | 天堂v中文 | 亚洲成av人片 | 日韩乱色精品一区二区 | 中文字幕精品三级久久久 | 日韩av一区二区三区 | 日本精品视频在线 | 免费高清在线观看成人 | 天天草综合网 | 中文字幕免费观看 | 亚洲另类视频 | 一区二区三区视频在线 | 欧美日韩精品在线观看 | 手机成人在线 | 91成人在线视频观看 | 18岁免费看片 | 天天撸夜夜操 | 99久久久久久久 | 91秒拍国产福利一区 | 中国一级片在线 | 91综合久久一区二区 | 国产经典av| 特级毛片在线免费观看 | 欧美精品被 | 91激情小视频 | 三上悠亚一区二区在线观看 | 婷婷久久综合九色综合 | 亚洲精品视频在线看 | 国产黄免费 | 国产系列精品av | 日韩在线观看你懂的 | 久久久久久毛片 | 成人一级免费视频 | 国产一级免费视频 | 中文字幕 在线 一 二 | 色偷偷av男人天堂 | 国产永久免费高清在线观看视频 | 国产精品日韩欧美 | 国产 日韩 在线 亚洲 字幕 中文 | 成人精品福利 | 最近免费在线观看 | 日批在线看 | 国产精品久久久久久久久久了 | 免费男女羞羞的视频网站中文字幕 | 日韩婷婷 | 国产一卡二卡在线 | www.91国产 | 91精品一区国产高清在线gif | 久草网站在线 | 久草视频免费 | 亚洲一区二区黄色 | 久久精品xxx | av在线一级 | 夜夜夜夜操 | 91九色视频国产 | 人人爽人人片 | 超碰av在线播放 | 日韩影片在线观看 | 国产免费资源 | 国产中文字幕一区二区三区 | 高清在线观看av | 日韩动态视频 | 视频成人| 91麻豆精品国产91久久久久久久久 | 国产黄色片久久 | 久久久久国产精品免费免费搜索 | 99欧美视频| 国产亚洲欧美精品久久久久久 | 可以免费看av | 少妇bbb好爽 | 福利视频区| 91视频久久久久 | 国产高清av在线播放 | 亚洲砖区区免费 | 国产淫片免费看 | 在线小视频国产 | 国产色视频网站 | 日本女人b| 亚洲精选视频在线 | 六月婷婷久香在线视频 | 日韩免费大片 | 一区二区三区四区五区在线 | av免费观看网站 | 精品人人人 | 黄av资源 | 又爽又黄又无遮挡网站动态图 | 五月天天色 | 麻豆你懂的 | 亚洲专区在线 | 精品视频中文字幕 | 天天操夜夜曰 | 中文字幕欲求不满 | 四虎永久免费在线观看 | 黄污在线看 | 91麻豆精品国产91久久久久 | 久久精品91久久久久久再现 | 免费成人黄色 | 8x成人在线 | 久久激情视频 | 成人国产精品久久久 | 日韩电影中文字幕在线观看 | 久久国产一区二区 | 国产一区二区视频在线播放 | 欧美精品一区二区三区一线天视频 | 成人小视频在线 | 亚在线播放中文视频 | 免费福利视频网站 | 992tv人人网tv亚洲精品 | 久久精品久久久久 | 一区二区三区污 | 男女啪啪网站 | 国产免费视频在线 | 国产理论免费 | 欧美日韩国产综合一区二区 | 午夜精品一区二区三区可下载 | 国产美腿白丝袜足在线av | 99视频这里只有 | 中国一级特黄毛片大片久久 | 色.www| 啪啪小视频网站 | 国产精品高潮呻吟久久久久 | 日韩美视频 | 欧美肥妇free | 欧美精品一区二区蜜臀亚洲 | 精品中文字幕在线观看 | 欧美一级片在线 | 91黄视频在线观看 | 天堂av在线 | 亚洲精品麻豆视频 | 九色自拍视频 | 视频国产精品 | 色全色在线资源网 | 91日韩精品 | 亚洲精品在线一区二区 | 国产在线不卡 | 国产精品福利小视频 | 久久成人亚洲欧美电影 | 美女黄网站视频免费 | 亚洲理论在线观看电影 | 狠狠狠狠狠干 | 91丝袜美腿 | 中文字幕免费高清 | 中文在线√天堂 | 婷婷九月丁香 | 欧美亚洲专区 | 久久精品视频中文字幕 | 日韩av在线网站 | 九九热视频在线播放 | 九九视频免费在线观看 | 操操综合网 | 免费av片在线 | www.看片网站 | 黄色1级大片 | 国产91精品一区二区麻豆网站 | 免费网站色 | av免费看在线 | 毛片一级免费一级 | 久久精品爱视频 | 天天在线免费视频 | 欧洲精品二区 | 人人澡人人爽欧一区 | 在线播放亚洲激情 | 999久久久久久久久6666 | 日韩激情在线 | 亚洲九九| 国产午夜精品一区二区三区欧美 | 一区二区三区在线影院 | 国产伦理一区二区 | 婷婷网站天天婷婷网站 | 精品福利网 | 欧美一区二视频在线免费观看 | 久久国产美女视频 | 五月天免费网站 | 免费网站黄色 | 免费黄色av片 | 五月天激情综合 | 特级西西444www大胆高清无视频 | www日日夜夜| 国产精品黄色影片导航在线观看 | 亚洲国产综合在线 | 伊人热 | 成人午夜毛片 | 日本黄色免费看 | 免费看的国产视频网站 | 亚洲精品自拍视频在线观看 | 91亚洲欧美| 在线性视频日韩欧美 | 国产二区视频在线 | 午夜精品电影一区二区在线 | 一区二区三区精品在线 | 毛片网站免费 | 久久国产热视频 | 国产精品综合在线观看 | 碰超在线观看 | 日韩视频在线观看免费 | 顶级bbw搡bbbb搡bbbb | 成人动态视频 | 国产福利精品一区二区 | 亚洲成av人片一区二区梦乃 | 日日摸日日添夜夜爽97 | 国产精品视频永久免费播放 | 国产黄色精品在线 | a久久久久 | 国产在线观看你懂得 | 99热网站| www.香蕉| 少妇做爰k8经典 | 国产成人精品一区二区三区福利 | 亚洲欧美国产精品va在线观看 | 黄色一级网 | 久久国产亚洲精品 | 日本中文字幕在线播放 | 日本狠狠色 | 成人免费观看电影 | 欧美日韩国产网站 | 一区视频在线 | 91免费的视频在线播放 | 97在线视频免费观看 | 美女黄久久| www在线免费观看 | 久久精品久久精品久久精品 | 久久99精品一区二区三区三区 | 久久久久久久久久国产精品 | 亚洲黄色成人 | 99精品国产99久久久久久福利 | 久久草精品 | 久久九九国产精品 | 亚洲成人资源在线 | 久久久免费精品视频 | 天天爽天天爽 | 一区 在线观看 | 欧美精品久久久久久久久久久 | 欧美精品乱码久久久久久按摩 | 国产午夜精品一区二区三区在线观看 | 激情电影影院 | 成人性生交大片免费看中文网站 | 99精品视频在线观看免费 | 国产精品一区在线播放 | 亚洲国产精品推荐 | 在线看日韩| 天天玩天天干 | 九月婷婷综合网 | 婷婷激情五月 | 五月天狠狠操 | 一区二区三区免费在线播放 | 久久超碰网 | 麻豆成人精品视频 | 在线视频欧美精品 | 亚洲国产日韩精品 | 亚洲国产成人精品在线 | 欧美 亚洲 另类 激情 另类 | 久久99热这里只有精品 | 国产91亚洲 | 日韩av成人在线 | av黄色在线观看 | 免费国产一区二区视频 | 一级成人网| 亚洲第一中文字幕 | 国产福利一区二区三区在线观看 | 亚洲成人精品久久久 | 操综合 | 午夜精品久久久久久中宇69 | 波多野结衣在线观看一区二区三区 | 午夜少妇一区二区三区 | 免费男女羞羞的视频网站中文字幕 | 亚洲免费不卡 | 久久久男人的天堂 | 日本久久久影视 | 亚洲更新最快 | 午夜国产一区二区 | 日本不卡123区 | 91精品视屏 | 日韩xxxbbb| 久久久精品亚洲 | www色| 亚州黄色一级 | 国产色就色 | 伊人影院av | 一本一道波多野毛片中文在线 | 欧美成人视 | 嫩草av影院| 韩国av三级 | 亚洲撸撸 | 欧美大码xxxx | 91精品天码美女少妇 | 成人av在线看 | 在线观看国产一区二区 | 日躁夜躁狠狠躁2001 | 天天做天天爱天天爽综合网 | 91欧美国产 | 亚洲精品免费观看 | jizz999| 国产伦理一区二区三区 | 日韩免费看 | 国产精品男女啪啪 | 亚洲成av人片在线观看 | 国产91电影在线观看 | 国产专区日韩专区 | 日韩精品一区二区久久 | 欧美日韩高清国产 | 亚洲国产三级在线 | 久久dvd| 中文字幕制服丝袜av久久 | 国产精品日韩在线播放 | 久久成人国产精品一区二区 | 91免费在线 | www.亚洲精品在线 | 国产成人精品一区在线 | 国产一区二区观看 | 在线国产中文字幕 | 欧美日韩中文字幕综合视频 | 福利在线看片 | 超级碰视频 | 国产精品久久久久久久99 | 亚洲综合色网站 | 亚洲精品午夜一区人人爽 | 国产成人精品999在线观看 | 成人久久久久久久久久 | 久久精品欧美一区二区三区麻豆 | 91天堂素人约啪 | 天天草天天摸 | 999在线精品 | 探花视频在线版播放免费观看 | 久久婷婷精品视频 | 黄色日本片 | 久久精品一区二区 | 久草在线国产 | 视频在线观看入口黄最新永久免费国产 | 国产精品aⅴ | 中国成人一区 | 中文字幕影视 | 福利一区二区三区四区 | 婷婷亚洲综合五月天小说 | 伊人国产在线观看 | 97视频在线免费 | 亚洲综合少妇 | 色综合久久久网 | 国产精品高清在线观看 | 精品国产中文字幕 | 国产专区视频在线 | 中文字幕欧美激情 | 91大神精品视频 | 99人久久精品视频最新地址 | 久久久精品欧美 | 天天玩夜夜操 | 一区二区视频免费在线观看 | a级一a一级在线观看 | 天天天天色射综合 | 91av免费观看 | 狠狠网 | 99热国产在线中文 | 国产精品福利无圣光在线一区 | 天天综合久久综合 | 亚洲乱码国产乱码精品天美传媒 | 天天色天天综合网 | 成人免费观看视频大全 | 不卡视频在线 | 亚洲精品国产精品乱码不99热 | 日韩精品欧美一区 | 日韩午夜视频在线观看 | 中文字幕一区二区三区视频 | 成人黄色中文字幕 | 日韩欧美精品免费 | 久久手机免费视频 | av在线播放网址 | 国产精品一区二区三区久久 | 国产成人无码AⅤ片在线观 日韩av不卡在线 | 中文字幕欧美日韩va免费视频 | 中文字幕有码在线 | 欧美激精品 | 婷婷av网| 免费碰碰 | 中文字幕 国产精品 | 青青河边草手机免费 | 久久激情综合网 | 精品国产乱码久久久久久久 | 免费看污片 | 高清日韩一区二区 | 久久久免费网站 | 天天操天天操天天干 | 国产麻豆剧传媒免费观看 | 国产精品久久久久一区二区三区共 | 亚洲乱码精品久久久 | 丁香六月中文字幕 | 99色视频在线 | 久久av福利| 天天操天天操天天操天天操天天操 | 国产成人亚洲在线电影 | 日韩av电影网站在线观看 | 麻花传媒mv免费观看 | 婷婷五综合 | 欧美性色黄大片在线观看 | 久久国产高清视频 | 久久婷婷色综合 | 免费视频久久 | 国产精品一区二区在线观看 | 日韩精品视频免费 | 婷婷av电影 | 日韩大片在线免费观看 | 亚洲专区欧美专区 | 亚洲一区二区黄色 | 91在线视频免费播放 | 97超碰资源站 | 久久国产精品免费看 | 日p在线观看| 国产大陆亚洲精品国产 | 精品在线一区二区 | 夜夜操狠狠干 | 日韩在线视频免费播放 | 亚洲国产片 | 日韩欧美视频免费看 | 国产91亚洲精品 | 国产日韩av在线 | 丝袜美女在线 | 国产日韩在线观看一区 | 国产xxxx| 亚洲天堂自拍视频 | 国产第页 | 中文字幕在线观看视频一区二区三区 | 欧美999| 国产视频色 | 九9热这里真品2 | 97超碰.com| 日韩中文字幕a | 国内精品久久天天躁人人爽 | 成人蜜桃 | 婷婷色在线视频 | 国产精品久久久久久一区二区 | 丁香午夜 | 午夜色婷婷 | 久久久久激情电影 | 91在线亚洲| 亚洲天堂网视频 | 中文字幕中文字幕在线一区 | 日日干网址 | 国产一区在线免费观看视频 | 国产一级一片免费播放放a 一区二区三区国产欧美 | 日本中文字幕在线观看 | 99久久精品午夜一区二区小说 | 一区二区三区四区在线 | 午夜视频在线观看网站 | 色香com. | 欧美一区二区三区四区夜夜大片 | 婷婷色资源 | 欧美日韩免费在线观看视频 | 999免费视频 | 欧美日韩国产三级 | 国产在线高清视频 | 91精品人成在线观看 | 国产婷婷vvvv激情久 | 91精品国自产拍天天拍 | 中文av在线免费观看 | 黄色www在线观看 | 国产福利91精品一区 | 久久丁香| 欧洲亚洲精品 | 国产成人高清在线 | 热99久久精品 | 日韩欧美电影在线 | 国产精品视频永久免费播放 | 欧美乱淫视频 | 美女一区网站 | 91日韩在线| 99热这里只有精品国产首页 | 午夜体验区 | 欧美极品少妇xxxxⅹ欧美极品少妇xxxx亚洲精品 | 在线激情小视频 | 亚洲视频久久 | 日日碰狠狠添天天爽超碰97久久 | 久久手机精品视频 | 欧洲精品久久久久毛片完整版 | 日韩精品1区2区 | 天天躁日日躁狠狠躁av中文 | 成人在线视频免费观看 | 波多野结衣一区二区三区中文字幕 | 国产a级精品 | 干狠狠| 久久99久国产精品黄毛片入口 | 字幕网在线观看 | 97网在线观看 | 亚洲人成免费 | 国产精品入口66mio女同 | 91精品一| 麻花豆传媒mv在线观看 | wwwwwww色| 在线观看久草 | 国产精品一区二区在线观看免费 | 精品久久片 | 久久久国际精品 | 免费在线观看av网站 | 日韩精品一卡 | 在线免费av网站 | 狠狠的干| 国产精品自产拍在线观看网站 | 91丨九色丨国产在线观看 | 日韩欧美一区二区三区黑寡妇 | 国产成人一区二区啪在线观看 | 欧美成年性 | 国产经典 欧美精品 | 成年人在线看片 | 狠狠干免费| 激情网综合| 久久这里只有精品视频99 | 免费在线观看av网址 | 毛片网站免费在线观看 | 九九国产精品视频 | 国产黄色大片 | 国产成人一区二区精品非洲 | 尤物97国产精品久久精品国产 | 在线有码中文字幕 | 国产又粗又猛又黄又爽的视频 | 亚洲欧洲美洲av | 国产精品爽爽久久久久久蜜臀 | 精品国产乱码 | 日韩高清免费在线 | 色综合天天干 | 国产玖玖精品视频 | 亚洲黄色免费在线 | 精品视频在线看 | 精品在线亚洲视频 | 精品视频在线免费 | 在线看国产一区 | 四虎www com| 一级成人网 | .国产精品成人自产拍在线观看6 | 久久综合中文字幕 | 五月婷婷精品 | 亚洲精品视频在线免费 | 99爱视频 | 国产色区 | 欧洲精品亚洲精品 | 中文字幕在线播放一区二区 | 国产在线播放观看 | 欧美亚洲国产精品久久高清浪潮 | 午夜久久 | 日韩欧美在线高清 | 中文在线www | 国产在线精品区 | 久久久久久久久久久影院 | 国产69精品久久久久久久久久 | 亚洲欧美日韩国产一区二区三区 | 草久久av | 91在线精品一区二区 | 成人av电影免费在线播放 | 69久久久 | 久久久国产一区二区三区四区小说 | 国产精美视频 | 国产亚洲字幕 | 国产午夜精品理论片在线 | 国产黄视频在线观看 | 91精品在线看 | 日b视频在线观看网址 | 天天爱天天色 | 亚洲视频第一页 | 日韩午夜在线播放 | a在线免费 | 四虎在线观看视频 | 欧美日韩一级久久久久久免费看 | 狠狠色噜噜狠狠狠狠2022 | 久久爽久久爽久久av东京爽 | 91麻豆精品国产91久久久久 | 国产精品a久久久久 | av电影在线不卡 | 国产黄色av网站 | 右手影院亚洲欧美 | 亚洲激情在线视频 | 99re8这里有精品热视频免费 | 中文字幕一区二区三区四区 | 欧美日韩国产色综合一二三四 | 福利一区在线视频 | 国产在线第三页 | 亚洲色图色 | 国产精品久久久久永久免费 | 欧美亚洲成人xxx | 婷婷综合电影 | 在线看国产视频 | 一区 二区 精品 | 一区 二区 精品 | 久久爱www. | 亚洲第一区在线播放 | 99热精品久久 | 国产一区二区在线播放视频 | 麻花豆传媒一二三产区 | 久久精品国产一区二区三区 | 欧美黄色特级片 | 中文字幕在线观看免费高清电影 | 精品久久美女 | 免费日韩一级片 | 日韩大片在线 | 久久精品视频4 | 91九色精品女同系列 | 国产人成精品一区二区三 | 欧美99久久 | 久久国产高清视频 | 开心色激情网 | 成 人 黄 色 片 在线播放 | 在线观看久草 | 中文字幕在线电影 | 成人国产一区二区 | 超碰97网站 | 久久涩视频 | 欧美色图亚洲图片 | 男女全黄一级一级高潮免费看 | 国产白浆在线观看 | av黄色免费网站 | 国产精品 中文字幕 亚洲 欧美 | av线上看 | 欧美夫妻性生活电影 | 日本在线中文在线 | 粉嫩一区二区三区粉嫩91 | 日韩精品在线一区 | 99久久久久久久久久 | 国产色综合 | 欧美一区二区三区在线 | 黄网站污 | 天天操夜| 国产成人无码AⅤ片在线观 日韩av不卡在线 | 欧美精品久久99 | 欧产日产国产69 | 精品视频免费在线 | 黄污网| 波多野结衣一区二区 | 免费看片在线观看 | 天天操天天摸天天爽 | 玖玖玖在线| 91精品国产高清自在线观看 | 日本精品视频在线观看 | 国产精品区二区三区日本 | 国产在线小视频 | 69xxxx欧美 | 欧美成人黄 | 亚洲黄色在线观看 | 亚洲精品视频观看 | 欧美-第1页-屁屁影院 | 日躁夜躁狠狠躁2001 | 精品久久久久久久久久久久久久久久久久 | 日韩在线视频播放 | 国产高清在线免费视频 | 在线激情网 | 九九热1| 色91在线 | 夜添久久精品亚洲国产精品 | 五月激情六月丁香 | 婷婷色婷婷 | 五月天天av | 久久亚洲精品国产亚洲老地址 | 国产精品自产拍在线观看网站 | av黄色免费看 | 狠狠色综合网站久久久久久久 | 超黄视频网站 | 国内精品久久久久影院男同志 | 在线观看精品 | 欧美动漫一区二区三区 | 最新av在线免费观看 | 五月婷婷综合激情网 | 精品久久久久久国产偷窥 | 麻豆视频免费播放 | www.福利视频 | 久99久在线视频 | 国产成人久久久77777 | 精品国产欧美一区二区三区不卡 | 在线观看精品 | 97超碰在线久草超碰在线观看 | www.888.av | 99久久激情视频 | 亚洲精品综合在线 | 99国内精品| 综合色综合色 | 69绿帽绿奴3pvideos | 久久国产片 | 在线韩国电影免费观影完整版 | 午夜精品久久久久 | 亚洲一二三在线 | 国产系列 在线观看 | 欧美日韩裸体免费视频 | 久久久精品网 | 天堂资源在线观看视频 | 狠狠做深爱婷婷综合一区 | 亚州激情视频 | 99久精品视频| 99热亚洲精品 | 久久免费av电影 | 免费在线观看日韩欧美 | www.夜夜草 | 欧美大码xxxx | 免费一级片在线 | 最新精品视频在线 | 日韩一区二区三区观看 | 国产一级黄色电影 | 天天操天天色天天射 | 亚洲国产日韩一区 | 久久视频在线免费观看 | 欧美日韩在线视频一区二区 | 99久久精品免费看 | 久久综合欧美精品亚洲一区 | 日韩欧美电影在线观看 | 久久久久激情视频 | 成人久久久精品国产乱码一区二区 | 国产亚洲久一区二区 | 亚洲一本视频 | 麻花传媒mv免费观看 | 摸阴视频 | 欧美精品久久久久久久久老牛影院 | 亚洲高清资源 | 99爱爱 | 91大神精品视频在线观看 | 日韩黄色中文字幕 | 激情五月在线视频 | 国产日韩精品在线 | 激情五月五月婷婷 | 亚洲精品97| 精品国产一区二区三区在线 | 操操操日日 | 国产精品一区二区久久精品爱微奶 | avove黑丝| 日本精品在线看 | www日韩| 国产在线高清精品 | 亚洲免费在线播放视频 | 操综合 | 天天干天天爽 | 久久成人精品电影 | 久久久久婷 | 天天干天天操人体 | 日韩精品一区二区三区视频播放 | 日韩在线观看第一页 | 欧美日韩在线视频免费 | 免费在线观看av网址 | 黄色成人影视 | 色午夜 | 99这里精品 | 综合国产在线观看 | 久久激情影院 | 免费在线观看污 | 国产97在线播放 | 一区二区三区四区精品视频 | 国产精品久久久久av福利动漫 | 91禁在线观看 | 久久久综合 | 玖玖精品在线 | 91夫妻视频 | 精品高清美女精品国产区 | 蜜桃av久久久亚洲精品 | 成人在线免费av | 国产资源精品 | 色婷婷狠狠操 | 国产福利免费在线观看 | 在线a人v观看视频 | 深夜免费福利视频 | 日韩伦理片一区二区三区 | 久久99精品一区二区三区三区 | 亚洲午夜精品一区二区三区电影院 | 伊人宗合| 国产91在线观看 | 久久天天躁狠狠躁亚洲综合公司 | 99视频偷窥在线精品国自产拍 | 在线观看91| 亚洲免费av在线播放 | 黄色精品一区二区 | 成人黄色影片在线 | 国产美女在线免费观看 | 91av在线不卡 | 97电影网手机版 | 亚洲精品在线观 | 99国内精品久久久久久久 | 天天爱天天操天天射 | 成人91免费视频 | 97超碰人人| 黄色福利| 久久色在线观看 | 日韩av免费一区二区 | www四虎影院 | 五月天伊人网 | 日韩免费二区 | 久久亚洲综合国产精品99麻豆的功能介绍 | 99视频免费看 | 日日干天天插 | 亚洲视频中文 | 久久字幕精品一区 | 久草在线一免费新视频 | 日韩特黄一级欧美毛片特黄 | 国产精品九九九九九 | 69精品在线观看 | 国产日韩视频在线观看 | 亚洲国产欧洲综合997久久, | 黄色av一区二区三区 | 日韩视频一二三区 | 免费视频99 | 一级片黄色片网站 | 欧美一二区在线 | 黄色毛片一级 | 91电影福利 | av三级av | 成人免费 在线播放 | 最新真实国产在线视频 | 国产乱对白刺激视频在线观看女王 | 国产视频一二区 | 中文欧美字幕免费 | 欧美色精品天天在线观看视频 | 韩国av永久免费 | 日本成人黄色片 | 91豆麻精品91久久久久久 | 999色视频| 久久久久久久久久福利 | 不卡在线一区 | 国产毛片在线 | 日韩在线 | 一区二区男女 | 丁香激情综合国产 | 天天爽夜夜爽人人爽曰av | 中文字幕91视频 | 日韩一二三区不卡 | 少妇精品久久久一区二区免费 | 免费观看成人网 | 久久香蕉国产精品麻豆粉嫩av | 日韩免费在线网站 | 91精品视频在线 | 在线导航福利 | 亚洲第一久久久 | 亚洲精品视频第一页 | 亚洲一级在线观看 | 亚洲女同ⅹxx女同tv | 91av视频在线播放 | 日本精品一区二区在线观看 | 九九热视频在线免费观看 | 国内精品久久久 | www.成人sex | 能在线看的av | 国产aaa免费视频 | 国产在线理论片 | 国产成人精品a | 女女av在线 | 国产精品黑丝在线观看 | 久久精国产 | 亚av在线| 亚洲黄色免费 | 欧美激情视频一区二区三区免费 | 国产精品久久久久久a | 九九久久在线看 | 久草影视在线 | 人人爽人人爽人人爽 | 国产剧情久久 | 丁香五月缴情综合网 | a电影免费看 | 91精品一区二区在线观看 | 在线精品视频在线观看高清 | 一本到视频在线观看 | 亚洲男男gⅴgay双龙 | 999在线精品 | 97超碰福利久久精品 | 天天天天天天天操 | 91亚色视频在线观看 | 久久久精品成人 | 五月婷婷激情六月 | 久久伦理| 五月天中文字幕mv在线 | 久久激情视频 久久 | 在线a视频 | 一区二区三区四区久久 | 国产成人精品一区二区在线 | www.国产在线| 在线一二区| 国产精品久久久99 | 亚洲在线免费视频 | 亚洲欧美乱综合图片区小说区 | 中文字幕在线电影 | 亚州精品一二三区 | 国产成人高清av | 国产日韩精品一区二区三区 | 狠狠狠狠狠狠操 | www.夜夜夜| 国产青草视频在线观看 | 国产精品久久久久久久久免费看 | 亚洲在线 | 91麻豆精品 | www亚洲精品 | 日本精品中文字幕在线观看 | 中文国产字幕在线观看 | 免费观看成人 | 在线免费观看视频一区二区三区 | 国产99久久99热这里精品5 | 天天爱天天干天天爽 | www.黄色在线| 久久黄色免费观看 | 99在线精品免费视频九九视 | 区一区二区三在线观看 | 国产免费av一区二区三区 | 2021国产精品视频 | 久久久久久久久久久久久国产精品 | 美女国内精品自产拍在线播放 | 久久超| 久久综合欧美 | 一区二区三区av在线 | 热久久影视 | 色天堂在线视频 | 久久免费99精品久久久久久 | 色综合天天综合网国产成人网 | 婷婷丁香在线观看 | www.五月婷婷.com | 色婷婷免费 | 美女国产精品 | 91麻豆精品国产午夜天堂 | 欧美天堂久久 | 国产黄在线免费观看 | www国产精品com | 国产精品成人一区二区 | 欧美日本日韩aⅴ在线视频 插插插色综合 | 久久综合九色99 | 综合激情久久 | 亚洲日韩欧美一区二区在线 | 精品产品国产在线不卡 | 精品久久免费看 | japanese黑人亚洲人4k | 中文字幕精品三区 | 亚洲3级| 欧美黑人巨大xxxxx | 国产精品久久久久久久久毛片 | 九九综合在线 | 麻豆首页 | 狠狠五月婷婷 | 国产三级国产精品国产专区50 | 91精品视频免费观看 | 天天干,天天干 | 久久免费精品国产 | 亚洲成人av片 | 欧美xxxxx在线视频 | 色天天中文|