日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

android listview下拉动画效果,Android开发中利用ListView实现一个渐变式的下拉刷新动画...

發(fā)布時(shí)間:2025/1/21 Android 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android listview下拉动画效果,Android开发中利用ListView实现一个渐变式的下拉刷新动画... 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Android開(kāi)發(fā)中利用ListView實(shí)現(xiàn)一個(gè)漸變式的下拉刷新動(dòng)畫(huà)

發(fā)布時(shí)間:2020-11-23 16:50:31

來(lái)源:億速云

閱讀:80

作者:Leah

本篇文章給大家分享的是有關(guān)Android開(kāi)發(fā)中利用ListView實(shí)現(xiàn)一個(gè)漸變式的下拉刷新動(dòng)畫(huà),小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著小編一起來(lái)看看吧。

主要要點(diǎn)

listview刷新過(guò)程中主要有三個(gè)步驟當(dāng)前:狀態(tài)為下拉刷新,當(dāng)前狀態(tài)為下拉刷新,當(dāng)前狀態(tài)為放開(kāi)刷新,當(dāng)前狀態(tài)為正在刷新;主要思路為三個(gè)步驟分別對(duì)應(yīng)三個(gè)自定義的view;即ibuRefreshFirstStepView,ibuRefreshSecondStepView,ibuRefreshThirdStepView。

效果圖

ibuRefreshFirstStepView代碼,例如:

private Bitmap initialBitmap;

private float mCurrentProgress;

private Bitmap scaledBitmap;

public ibuRefreshFirstStepView(Context context, AttributeSet attrs,

int defStyle) {

super(context, attrs, defStyle);

init(context);

}

public ibuRefreshFirstStepView(Context context, AttributeSet attrs) {

super(context, attrs);

init(context);

}

public ibuRefreshFirstStepView(Context context) {

super(context);

init(context);

}

private void init(Context context) {

//這個(gè)就是那個(gè)火箭圖片

initialBitmap = Bitmap.createBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.img_huojian1));

}

/**

* 重寫(xiě)onMeasure方法主要是設(shè)置wrap_content時(shí) View的大小

* @param widthMeasureSpec

* @param heightMeasureSpec

*/

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

//根據(jù)設(shè)置的寬度來(lái)計(jì)算高度 設(shè)置為符合第二階段娃娃圖片的寬高比例

setMeasuredDimension(measureWidth(widthMeasureSpec),measureWidth(widthMeasureSpec)*initialBitmap.getHeight()/initialBitmap.getWidth());

}

/**

* 當(dāng)wrap_content的時(shí)候,寬度即為第二階段娃娃圖片的寬度

* @param widMeasureSpec

* @return

*/

private int measureWidth(int widMeasureSpec){

int result = 0;

int size = MeasureSpec.getSize(widMeasureSpec);

int mode = MeasureSpec.getMode(widMeasureSpec);

if (mode == MeasureSpec.EXACTLY){

result = size;

}else{

result = initialBitmap.getWidth();

if (mode == MeasureSpec.AT_MOST){

result = Math.min(result,size);

}

}

return result;

}

/**

* 在onLayout里面獲得測(cè)量后View的寬高

* @param changed

* @param left

* @param top

* @param right

* @param bottom

*/

@Override

protected void onLayout(boolean changed, int left, int top, int right,

int bottom) {

super.onLayout(changed, left, top, right, bottom);

// 給火箭圖片進(jìn)行等比例的縮放

scaledBitmap = Bitmap.createScaledBitmap(initialBitmap,89,110, false);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//這個(gè)方法是對(duì)畫(huà)布進(jìn)行縮放,從而達(dá)到橢圓形圖片的縮放,第一個(gè)參數(shù)為寬度縮放比例,第二個(gè)參數(shù)為高度縮放比例,

// canvas.scale(mCurrentProgress, mCurrentProgress, measuredWidth/2, measuredHeight/2);

//將等比例縮放后的橢圓形畫(huà)在畫(huà)布上面

canvas.drawBitmap(scaledBitmap,90,dip2px(getContext(),80*mCurrentProgress),null);

}

/**

* 根據(jù)手機(jī)的分辨率從 dp 的單位 轉(zhuǎn)成為 px(像素)

*/

public static int dip2px(Context context, float dpValue) {

final float scale = context.getResources().getDisplayMetrics().density;

return (int) (dpValue * scale + 0.5f);

}

/**

* 設(shè)置縮放比例,從0到1 0為最小 1為最大

* @param currentProgress

*/

public void setCurrentProgress(float currentProgress){

mCurrentProgress = currentProgress;

}

}

ibuRefreshSecondStepView代碼,例如:

private Bitmap endBitmap,scaledBitmap;

public ibuRefreshSecondStepView(Context context, AttributeSet attrs,

int defStyle) {

super(context, attrs, defStyle);

init();

}

public ibuRefreshSecondStepView(Context context, AttributeSet attrs) {

super(context, attrs);

init();

}

public ibuRefreshSecondStepView(Context context) {

super(context);

init();

}

private void init() {

endBitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.img_huojian2), 89, 110, false);

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

setMeasuredDimension(measureWidth(widthMeasureSpec), measureWidth(widthMeasureSpec) * endBitmap.getHeight() / endBitmap.getWidth());

}

@Override

protected void onLayout(boolean changed, int left, int top, int right,

int bottom) {

super.onLayout(changed, left, top, right, bottom);

scaledBitmap = Bitmap.createScaledBitmap(endBitmap, 89, 110, false);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

canvas.drawBitmap(endBitmap, 90, dip2px(getContext(), 80 * 1), null);

}

/**

* 根據(jù)手機(jī)的分辨率從 dp 的單位 轉(zhuǎn)成為 px(像素)

*/

public static int dip2px(Context context, float dpValue) {

final float scale = context.getResources().getDisplayMetrics().density;

return (int) (dpValue * scale + 0.5f);

}

private int measureWidth(int widthMeasureSpec){

int result = 0;

int size = MeasureSpec.getSize(widthMeasureSpec);

int mode = MeasureSpec.getMode(widthMeasureSpec);

if (mode == MeasureSpec.EXACTLY) {

result = size;

}else {

result = endBitmap.getWidth();

if (mode == MeasureSpec.AT_MOST) {

result = Math.min(result, size);

}

}

return result;

}

}

ibuRefreshThirdStepView代碼,例如:

private Bitmap endBitmap,scaledBitmap;

public ibuRefreshThirdStepView(Context context, AttributeSet attrs,

int defStyle) {

super(context, attrs, defStyle);

init();

}

public ibuRefreshThirdStepView(Context context, AttributeSet attrs) {

super(context, attrs);

init();

}

public ibuRefreshThirdStepView(Context context) {

super(context);

init();

}

private void init() {

endBitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.img_huojian3), 89, 170, false);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

canvas.drawBitmap(endBitmap, 90, dip2px(getContext(), 40 * 1), null);

}

/**

* 根據(jù)手機(jī)的分辨率從 dp 的單位 轉(zhuǎn)成為 px(像素)

*/

public static int dip2px(Context context, float dpValue) {

final float scale = context.getResources().getDisplayMetrics().density;

return (int) (dpValue * scale + 0.5f);

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

setMeasuredDimension(measureWidth(widthMeasureSpec), measureWidth(widthMeasureSpec)*endBitmap.getHeight()/endBitmap.getWidth());

}

private int measureWidth(int widthMeasureSpec){

int result = 0;

int size = MeasureSpec.getSize(widthMeasureSpec);

int mode = MeasureSpec.getMode(widthMeasureSpec);

if (mode == MeasureSpec.EXACTLY) {

result = size;

}else {

result = endBitmap.getWidth();

if (mode == MeasureSpec.AT_MOST) {

result = Math.min(result, size);

}

}

return result;

}

代碼塊

IbuListView 代碼,例如:

private static final int DONE = 0;

private static final int PULL_TO_REFRESH = 1;

private static final int RELEASE_TO_REFRESH = 2;

private static final int REFRESHING = 3;

private static final int RATIO = 3;

private RelativeLayout headerView;

private int headerViewHeight;

private float startY;

private float offsetY;

private TextView tv_pull_to_refresh;

private OnMeiTuanRefreshListener mOnRefreshListener;

private int state;

private int mFirstVisibleItem;

private boolean isRecord;

private boolean isEnd;

private boolean isRefreable;

private FrameLayout mAnimContainer;

// private Animation animation;

private SimpleDateFormat format;

private ibuRefreshFirstStepView mFirstView;

private ibuRefreshSecondStepView mSecondView;

private AnimationDrawable secondAnim;

private ibuRefreshThirdStepView mThirdView;

private AnimationDrawable thirdAnim;

public IbuListView(Context context) {

super(context);

init(context);

}

public IbuListView(Context context, AttributeSet attrs) {

super(context, attrs);

init(context);

}

public IbuListView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init(context);

}

public interface OnMeiTuanRefreshListener{

void onRefresh();

}

/**

* 回調(diào)接口,想實(shí)現(xiàn)下拉刷新的listview實(shí)現(xiàn)此接口

* @param onRefreshListener

*/

public void setOnMeiTuanRefreshListener(OnMeiTuanRefreshListener onRefreshListener){

mOnRefreshListener = onRefreshListener;

isRefreable = true;

}

/**

* 刷新完畢,從主線程發(fā)送過(guò)來(lái),并且改變headerView的狀態(tài)和文字動(dòng)畫(huà)信息

*/

public void setOnRefreshComplete(){

//一定要將isEnd設(shè)置為true,以便于下次的下拉刷新

isEnd = true;

state = DONE;

changeHeaderByState(state);

}

private ImageView imageViewBack,imageView_B;

private void init(Context context) {

setOverScrollMode(View.OVER_SCROLL_NEVER);

setOnScrollListener(this);

headerView = (RelativeLayout) LayoutInflater.from(context).inflate(R.layout.ibu_item, null, false);

imageViewBack= (ImageView) headerView.findViewById(R.id.icon_back);

imageView_B= (ImageView) headerView.findViewById(R.id.image_b);

mFirstView = (ibuRefreshFirstStepView) headerView.findViewById(R.id.first_view);

tv_pull_to_refresh = (TextView) headerView.findViewById(R.id.tv_pull_to_refresh);

mSecondView = (ibuRefreshSecondStepView) headerView.findViewById(R.id.second_view);

mThirdView = (ibuRefreshThirdStepView) headerView.findViewById(R.id.third_view);

measureView(headerView);

addHeaderView(headerView);

headerViewHeight = headerView.getMeasuredHeight();

headerView.setPadding(0, -headerViewHeight, 0, 0);

Log.i("zhangqi","headerViewHeight="+headerViewHeight);

state = DONE;

isEnd = true;

isRefreable = false;

}

@Override

public void onScrollStateChanged(AbsListView absListView, int i) {

}

@Override

public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

mFirstVisibleItem = firstVisibleItem;

}

@Override

public boolean onTouchEvent(MotionEvent ev) {

if (isEnd) {//如果現(xiàn)在時(shí)結(jié)束的狀態(tài),即刷新完畢了,可以再次刷新了,在onRefreshComplete中設(shè)置

if (isRefreable) {//如果現(xiàn)在是可刷新?tīng)顟B(tài) 在setOnMeiTuanListener中設(shè)置為true

switch (ev.getAction()){

//用戶按下

case MotionEvent.ACTION_DOWN:

//如果當(dāng)前是在listview頂部并且沒(méi)有記錄y坐標(biāo)

if (mFirstVisibleItem == 0 && !isRecord) {

//將isRecord置為true,說(shuō)明現(xiàn)在已記錄y坐標(biāo)

isRecord = true;

//將當(dāng)前y坐標(biāo)賦值給startY起始y坐標(biāo)

startY = ev.getY();

}

imageView_B.setVisibility(VISIBLE);

break;

//用戶滑動(dòng)

case MotionEvent.ACTION_MOVE:

//再次得到y(tǒng)坐標(biāo),用來(lái)和startY相減來(lái)計(jì)算offsetY位移值

float tempY = ev.getY();

//再起判斷一下是否為listview頂部并且沒(méi)有記錄y坐標(biāo)

if (mFirstVisibleItem == 0 && !isRecord) {

isRecord = true;

startY = tempY;

}

//如果當(dāng)前狀態(tài)不是正在刷新的狀態(tài),并且已經(jīng)記錄了y坐標(biāo)

if (state!=REFRESHING && isRecord ) {

//計(jì)算y的偏移量

offsetY = tempY - startY;

//計(jì)算當(dāng)前滑動(dòng)的高度

float currentHeight = (-headerViewHeight+offsetY/3);

//用當(dāng)前滑動(dòng)的高度和頭部headerView的總高度進(jìn)行比 計(jì)算出當(dāng)前滑動(dòng)的百分比 0到1

float currentProgress = 1+currentHeight/headerViewHeight;

//如果當(dāng)前百分比大于1了,將其設(shè)置為1,目的是讓第一個(gè)狀態(tài)的橢圓不再繼續(xù)變大

if (currentProgress>=1) {

currentProgress = 1;

}

//如果當(dāng)前的狀態(tài)是放開(kāi)刷新,并且已經(jīng)記錄y坐標(biāo)

if (state == RELEASE_TO_REFRESH && isRecord) {

setSelection(0);

//如果當(dāng)前滑動(dòng)的距離小于headerView的總高度

if (-headerViewHeight+offsetY/RATIO<0) {

//將狀態(tài)置為下拉刷新?tīng)顟B(tài)

state = PULL_TO_REFRESH;

//根據(jù)狀態(tài)改變headerView,主要是更新動(dòng)畫(huà)和文字等信息

changeHeaderByState(state);

//如果當(dāng)前y的位移值小于0,即為headerView隱藏了

}else if (offsetY<=0) {

//將狀態(tài)變?yōu)閐one

state = DONE;

//根據(jù)狀態(tài)改變headerView,主要是更新動(dòng)畫(huà)和文字等信息

changeHeaderByState(state);

}

}

//如果當(dāng)前狀態(tài)為下拉刷新并且已經(jīng)記錄y坐標(biāo)

if (state == PULL_TO_REFRESH && isRecord) {

setSelection(0);

//如果下拉距離大于等于headerView的總高度

if (-headerViewHeight+offsetY/RATIO>=0) {

//將狀態(tài)變?yōu)榉砰_(kāi)刷新

state = RELEASE_TO_REFRESH;

//根據(jù)狀態(tài)改變headerView,主要是更新動(dòng)畫(huà)和文字等信息

changeHeaderByState(state);

//如果當(dāng)前y的位移值小于0,即為headerView隱藏了

}else if (offsetY<=0) {

//將狀態(tài)變?yōu)閐one

state = DONE;

//根據(jù)狀態(tài)改變headerView,主要是更新動(dòng)畫(huà)和文字等信息

changeHeaderByState(state);

}

}

//如果當(dāng)前狀態(tài)為done并且已經(jīng)記錄y坐標(biāo)

if (state == DONE && isRecord) {

//如果位移值大于0

if (offsetY>=0) {

//將狀態(tài)改為下拉刷新?tīng)顟B(tài)

state = PULL_TO_REFRESH;

}

}

//如果為下拉刷新?tīng)顟B(tài)

if (state == PULL_TO_REFRESH) {

//則改變headerView的padding來(lái)實(shí)現(xiàn)下拉的效果

headerView.setPadding(0,(int)(-headerViewHeight+offsetY/RATIO) ,0,0);

//給第一個(gè)狀態(tài)的View設(shè)置當(dāng)前進(jìn)度值

mFirstView.setCurrentProgress(currentProgress);

//重畫(huà)

mFirstView.postInvalidate();

}

//如果為放開(kāi)刷新?tīng)顟B(tài)

if (state == RELEASE_TO_REFRESH) {

//改變headerView的padding值

headerView.setPadding(0,(int)(-headerViewHeight+offsetY/RATIO) ,0, 0);

//給第一個(gè)狀態(tài)的View設(shè)置當(dāng)前進(jìn)度值

mFirstView.setCurrentProgress(currentProgress);

//重畫(huà)

mFirstView.postInvalidate();

}

}

break;

//當(dāng)用戶手指抬起時(shí)

case MotionEvent.ACTION_UP:

//如果當(dāng)前狀態(tài)為下拉刷新?tīng)顟B(tài)

if (state == PULL_TO_REFRESH) {

//平滑的隱藏headerView

this.smoothScrollBy((int)(-headerViewHeight+offsetY/RATIO)+headerViewHeight, 500);

//根據(jù)狀態(tài)改變headerView

changeHeaderByState(state);

}

//如果當(dāng)前狀態(tài)為放開(kāi)刷新

if (state == RELEASE_TO_REFRESH) {

//平滑的滑到正好顯示headerView

this.smoothScrollBy((int)(-headerViewHeight+offsetY/RATIO), 500);

//將當(dāng)前狀態(tài)設(shè)置為正在刷新

state = REFRESHING;

//回調(diào)接口的onRefresh方法

mOnRefreshListener.onRefresh();

//根據(jù)狀態(tài)改變headerView

changeHeaderByState(state);

}

//這一套手勢(shì)執(zhí)行完,一定別忘了將記錄y坐標(biāo)的isRecord改為false,以便于下一次手勢(shì)的執(zhí)行

isRecord = false;

break;

}

}

}

return super.onTouchEvent(ev);

}

private Animation animation;

/**

* 根據(jù)狀態(tài)改變headerView的動(dòng)畫(huà)和文字顯示

* @param state

*/

private void changeHeaderByState(int state){

switch (state) {

case DONE://如果的隱藏的狀態(tài)

//設(shè)置headerView的padding為隱藏

headerView.setPadding(0, -headerViewHeight, 0, 0);

//第一狀態(tài)的view顯示出來(lái)

mFirstView.setVisibility(View.VISIBLE);

imageView_B.setVisibility(VISIBLE);

tv_pull_to_refresh.setText("下拉刷新");

//第二狀態(tài)的view隱藏起來(lái)

mSecondView.setVisibility(View.GONE);

//停止第二狀態(tài)的動(dòng)畫(huà)

secondAnim.stop();

//第三狀態(tài)的view隱藏起來(lái)

mThirdView.setVisibility(View.GONE);

//停止第三狀態(tài)的動(dòng)畫(huà)

thirdAnim.stop();

break;

case RELEASE_TO_REFRESH://當(dāng)前狀態(tài)為放開(kāi)刷新

//文字顯示為放開(kāi)刷新

tv_pull_to_refresh.setText("放開(kāi)刷新");

//第一狀態(tài)view隱藏起來(lái)

mFirstView.setVisibility(View.GONE);

//第二狀態(tài)view顯示出來(lái)

mSecondView.setVisibility(View.VISIBLE);

//播放第二狀態(tài)的動(dòng)畫(huà)

secondAnim.start();

//第三狀態(tài)view隱藏起來(lái)

mThirdView.setVisibility(View.GONE);

//停止第三狀態(tài)的動(dòng)畫(huà)

thirdAnim.stop();

break;

case PULL_TO_REFRESH://當(dāng)前狀態(tài)為下拉刷新

imageView_B.setVisibility(VISIBLE);

//設(shè)置文字為下拉刷新

tv_pull_to_refresh.setText("下拉刷新");

//第一狀態(tài)view顯示出來(lái)

mFirstView.setVisibility(View.VISIBLE);

//第二狀態(tài)view隱藏起來(lái)

mSecondView.setVisibility(View.GONE);

//第二狀態(tài)動(dòng)畫(huà)停止

secondAnim.stop();

//第三狀態(tài)view隱藏起來(lái)

mThirdView.setVisibility(View.GONE);

//第三狀態(tài)動(dòng)畫(huà)停止

thirdAnim.stop();

break;

case REFRESHING://當(dāng)前狀態(tài)為正在刷新

//文字設(shè)置為正在刷新

tv_pull_to_refresh.setText("正在刷新");

//第一狀態(tài)view隱藏起來(lái)

mFirstView.setVisibility(View.GONE);

//第三狀態(tài)view顯示出來(lái)

mThirdView.setVisibility(View.VISIBLE);

//第二狀態(tài)view隱藏起來(lái)

mSecondView.setVisibility(View.GONE);

//停止第二狀態(tài)動(dòng)畫(huà)

secondAnim.stop();

//啟動(dòng)第三狀態(tài)view

thirdAnim.start();

imageView_B.setVisibility(GONE);

animation = new TranslateAnimation(0, 0, 0, 600);

animation.setDuration(3000);

imageViewBack.setAnimation(animation);

break;

default:

break;

}

}

private void measureView(View child) {

ViewGroup.LayoutParams p = child.getLayoutParams();

if (p == null) {

p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,

ViewGroup.LayoutParams.WRAP_CONTENT);

}

int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);

int lpHeight = p.height;

int childHeightSpec;

if (lpHeight > 0) {

childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,

MeasureSpec.EXACTLY);

} else {

childHeightSpec = MeasureSpec.makeMeasureSpec(0,

MeasureSpec.UNSPECIFIED);

}

child.measure(childWidthSpec, childHeightSpec);

}

}

以上就是Android開(kāi)發(fā)中利用ListView實(shí)現(xiàn)一個(gè)漸變式的下拉刷新動(dòng)畫(huà),小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

總結(jié)

以上是生活随笔為你收集整理的android listview下拉动画效果,Android开发中利用ListView实现一个渐变式的下拉刷新动画...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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