文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android仿网易一元夺宝客户端下拉加载动画效果(一)

2022-06-06 07:37

关注

上上周写的一个demo,仿照网易一元夺宝的下拉刷新效果。

原效果是(第一部分)一个小太阳拉下来,然后松开回弹上去,

(第二部分)再掉下来一个硬币进行中轴旋转。

本文实现的效果的是第一部分的,效果演示图如下:

Gif图看起来比较卡顿。。。其实真机演示效果还是很流畅的。

下面分析实现过程:

当时因为时间有限没有写在下拉刷新的组件中,也没有封装成一个单独的组件,只是在主布局后面写了一个View然后实现相应的操作,进行封装并不难,这里就不花时间BB了,下面是布局文件:


<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" 
tools:context=".aty.MainActivity"> 
<location.haidian.com.wypulltoreflush.view.NGImgView 
android:id="@+id/ngimg_main" 
android:layout_width="match_parent" 
android:layout_height="match_parent"/> 
<ImageView 
android:id="@+id/img_main_sun" 
android:layout_width="50dp" 
android:layout_height="50dp" 
android:layout_centerHorizontal="true" 
android:layout_marginTop="5dp" 
android:src="@drawable/ic_sun1"/> 
<LinearLayout 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:background="#00123456" 
android:orientation="vertical"> 
<RelativeLayout 
android:layout_width="match_parent" 
android:layout_height="55dp" 
android:background="#FF4081"> 
</RelativeLayout> 
<View 
android:layout_width="match_parent" 
android:layout_height="0.5dp" 
android:background="@android:color/darker_gray"></View> 
<location.haidian.com.wypulltoreflush.view.NGReFlashListView 
android:id="@+id/lv_main" 
android:layout_width="fill_parent" 
android:layout_height="0dp" 
android:layout_weight="1" 
android:cacheColorHint="#00000000" 
/> 
</LinearLayout> 
</RelativeLayout>

布局文件预览:

因为设置了透明,所以这里在没有item的情况下是能看到后面的布局的。

代码实现:

通过下拉刷新类NGReFlashListView进行事件判断,然后通过回调把相应的事件传递给NGImageView中改变视图显示。

下面是两个类的源代码:

NGReFlashListView类:


package location.haidian.com.wypulltoreflush.view; 
import android.content.Context; 
import android.util.AttributeSet; 
import android.view.LayoutInflater; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.AbsListView; 
import android.widget.AbsListView.OnScrollListener; 
import android.widget.ListView; 
import location.haidian.com.wypulltoreflush.R; 
public class NGReFlashListView extends ListView implements OnScrollListener { 
private View header; 
private int headerHeight; 
private int firstVisibleItem; 
private int scrollState; 
private final int NONE = 0; 
private final int PULL = 1; 
private final int RELESE = 2; 
private final int REFLASHING = 3; 
public NGReFlashListView(Context context) { 
super(context); 
initView(context); 
} 
public NGReFlashListView(Context context, AttributeSet attrs) { 
super(context, attrs); 
initView(context); 
} 
public NGReFlashListView(Context context, AttributeSet attrs, int defStyle) { 
super(context, attrs, defStyle); 
initView(context); 
} 
 
private void initView(Context context) { 
LayoutInflater inflater = LayoutInflater.from(context); 
header = inflater.inflate(R.layout.layout_heard, null); 
measureView(header); 
headerHeight = header.getMeasuredHeight(); 
topPadding(-headerHeight); 
this.addHeaderView(header); 
this.setOnScrollListener(this); 
} 
 
private void measureView(View view) { 
ViewGroup.LayoutParams p = view.getLayoutParams(); 
if (p == null) { 
p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 
ViewGroup.LayoutParams.WRAP_CONTENT); 
} 
int width = ViewGroup.getChildMeasureSpec(0, 0, p.width); 
int height; 
int tempHeight = p.height; 
if (tempHeight > 0) { 
height = MeasureSpec.makeMeasureSpec(tempHeight, 
MeasureSpec.EXACTLY); 
} else { 
height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 
} 
view.measure(width, height); 
} 
 
private void topPadding(int topPadding) { 
header.setPadding(header.getPaddingLeft(), topPadding, 
header.getPaddingRight(), header.getPaddingBottom()); 
header.invalidate(); 
} 
@Override 
public void onScroll(AbsListView view, int firstVisibleItem, 
int visibleItemCount, int totalItemCount) { 
this.firstVisibleItem = firstVisibleItem; 
} 
@Override 
public void onScrollStateChanged(AbsListView view, int scrollState) { 
this.scrollState = scrollState; 
} 
boolean isRemark;//初始化标识 
int startY; 
int state; 
@Override 
public boolean onTouchEvent(MotionEvent ev) { 
switch (ev.getAction()) { 
case MotionEvent.ACTION_DOWN: 
if (firstVisibleItem == 0) { 
onRlvScrollListener.onScrollYChangged(0, 0); 
isRemark = true; 
startY = (int) ev.getY(); 
} 
break; 
case MotionEvent.ACTION_MOVE: 
onMove(ev); 
break; 
case MotionEvent.ACTION_UP: 
if (state == RELESE) { 
onRlvScrollListener.onScrollYChangged(0, 3); 
state = REFLASHING; 
reflashViewByState(); 
//iReflashListener.onReflash(); 
} else if (state == PULL) { 
state = NONE; 
onRlvScrollListener.onScrollYChangged(0, 0); 
isRemark = false; 
reflashViewByState(); 
} 
break; 
} 
return super.onTouchEvent(ev); 
} 
int space; //间距 
int topPadding; //headview距离顶端的距离,初始-200 
 
private void onMove(MotionEvent ev) { 
if (!isRemark) { 
return; 
} 
int tempY = (int) ev.getY(); 
space = tempY - startY; 
if (space >= 230) { 
space = 230; 
} 
topPadding = space - headerHeight; 
onRlvScrollListener.onScrollYChangged(space, state); 
switch (state) { 
case NONE: 
if (space > 0) { 
state = PULL; 
reflashViewByState(); 
} 
break; 
case PULL: 
topPadding(topPadding); 
if (space == headerHeight + 30 
&& scrollState == SCROLL_STATE_TOUCH_SCROLL) { 
state = RELESE; 
reflashViewByState(); 
} 
break; 
case RELESE: 
if (space < headerHeight + 30) { 
state = PULL; 
reflashViewByState(); 
} else if (space <= 0) { 
state = NONE; 
isRemark = false; 
reflashViewByState(); 
} 
break; 
} 
} 
 
private void reflashViewByState() { 
switch (state) { 
case NONE: 
//缓慢滑上去 
topPadding(-headerHeight); 
break; 
case PULL: 
break; 
case RELESE: 
break; 
case REFLASHING: 
break; 
} 
} 
 
public void reflashComplete() { 
state = NONE; 
onRlvScrollListener.onScrollYChangged(0, state); 
isRemark = false; 
reflashViewByState(); 
} 
//绘制背景的接口 
public interface OnRlvScrollListener { 
void onScrollYChangged(int Y, int state); 
} 
private OnRlvScrollListener onRlvScrollListener; 
public void setOnRlvScrollListener(OnRlvScrollListener onRlvScrollListener) { 
this.onRlvScrollListener = onRlvScrollListener; 
} 
}

NGImgView.java

实现比较简单,根据传来的回调状态改变进行小太阳和两只球球手以及手臂的绘制就可以了。


package location.haidian.com.wypulltoreflush.view; 
import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.RectF; 
import android.graphics.drawable.BitmapDrawable; 
import android.util.AttributeSet; 
import android.util.Log; 
import android.widget.ImageView; 
import location.haidian.com.wypulltoreflush.R; 
 
public class NGImgView extends ImageView implements NGReFlashListView.OnRlvScrollListener { 
private float scale; 
private final int NONE = 0; 
private final int PULL = 1; 
private final int RELESE = 2; 
private final int REFLASHING = 3; 
public int state = 0; 
private float WITH; //屏幕总宽 
private float scrollY; 
private Bitmap sun0; 
public float time = 0; 
public NGImgView(Context context, AttributeSet attrs) { 
super(context, attrs); 
initView(); 
} 
private void initView() { 
sun0 = ((BitmapDrawable) getResources().getDrawable(R.drawable.ic_sun0)).getBitmap(); 
scale = this.getResources().getDisplayMetrics().density; 
} 
@Override 
protected void onDraw(Canvas canvas) { 
Paint paint = new Paint(); 
paint.setAntiAlias(true);//抗锯齿 
paint.setColor(Color.parseColor("#C4885A")); 
Log.d("xiaojingyu","State:" + state); 
if (state!=3) { 
time = 0; //重置时间 
//画两只球球手 
canvas.drawCircle(WITH / 2 - 40 * scale, 55 * scale, 5 * scale, paint); 
canvas.drawCircle(WITH / 2 + 40 * scale, 55 * scale, 5 * scale, paint); 
//画笑脸 
canvas.drawBitmap(sun0, 
null, 
new RectF(WITH / 2 - 50, 
55 * scale + scrollY - (scrollY / 230) * 50, 
WITH / 2 + 50, 
55 * scale + scrollY - (scrollY / 230) * 50 + 100), 
null 
); 
//画手臂 
paint.setStrokeWidth(1); 
canvas.drawLine(WITH / 2 - 40 * scale, 55 * scale, 
WITH / 2 - 50, 55 * scale + scrollY, 
paint 
); 
canvas.drawLine(WITH / 2 + 40 * scale, 55 * scale, 
WITH / 2 + 50, 55 * scale + scrollY, 
paint 
); 
} else if (state == 3) { 
//1秒钟拉上去,2秒钟旋转 
//第一秒 
if (time < 30) { 
time += 1; 
//画两只球球手 
canvas.drawCircle(WITH / 2 - 40 * scale, 55 * scale, 5 * scale, paint); 
canvas.drawCircle(WITH / 2 + 40 * scale, 55 * scale, 5 * scale, paint); 
//画笑脸 
canvas.drawBitmap(sun0, 
null, 
new RectF(WITH / 2 - 50, 
55 * scale + 180 - (time / 30) * 230, 
WITH / 2 + 50, 
55 * scale + 280 - (time / 30) * 230), 
null 
); 
//画手臂 
paint.setStrokeWidth(1); 
canvas.drawLine(WITH / 2 - 40 * scale, 55 * scale, 
WITH / 2 - 50, 
55 * scale + 230 - (time / 30) * 230, 
paint 
); 
canvas.drawLine(WITH / 2 + 40 * scale, 55 * scale, 
WITH / 2 + 50, 
55 * scale + 230 - (time / 30) * 230, 
paint 
); 
postInvalidateDelayed(1); 
} else { 
if (!isBeginMainAnimation) { 
isBeginMainAnimation = true; 
iReflashListener.onReflash(); 
} 
} 
} 
super.onDraw(canvas); 
} 
public static boolean isBeginMainAnimation = false; 
@Override 
protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 
super.onLayout(changed, left, top, right, bottom); 
WITH = this.getWidth(); 
} 
@Override 
public void onScrollYChangged(int Y, int state) { 
this.state = state; 
switch (state) { 
case NONE: 
break; 
case PULL: 
//下拉 
scrollY = Y; 
break; 
case RELESE: 
break; 
case REFLASHING: 
break; 
} 
} 
private IReflashListener iReflashListener; //回调接口 
public void setInterface(IReflashListener iReflashListener) { 
this.iReflashListener = iReflashListener; 
} 
 
public interface IReflashListener { 
void onReflash(); 
} 
}

以上所述是小编给大家介绍的Android仿网易一元夺宝客户端下拉加载动画效果(一),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程网网站的支持!

您可能感兴趣的文章:android ListView结合xutils3仿微信实现下拉加载更多Android ListView实现下拉加载功能Android实现仿慕课网下拉加载动画Android中使用RecyclerView实现下拉刷新和上拉加载Android下拉刷新上拉加载控件(适用于所有View)Android RecyclerView实现下拉刷新和上拉加载android开发教程之实现listview下拉刷新和上拉刷新效果Android实现上拉加载更多以及下拉刷新功能(ListView)Android RecyclerView 上拉加载更多及下拉刷新功能的实现方法PullToRefreshListView实现多条目加载上拉刷新和下拉加载


阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯