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

上上周写的一个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);
}
/**
* @param 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);
}
/**
* @param view
*/
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);
}
/**
* @param topPadding
*/
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
/**
* @param ev
*/
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;
/**
* Created by nangua on 2016/8/28.
*/
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;
}
/**
* @author Administrator
*/
public interface IReflashListener {
void onReflash();
}
}

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

(0)

相关推荐

  • Android项目实战之仿网易顶部导航栏效果

    随着时间的推移现在的软件要求显示的内容越来越多,所以要在小的屏幕上能够更好的显示更多的内容,首先我们会想到底部菜单栏,但是有时候想网易新闻要显示的内容太多,而且又想在主页面全部显示出来,所以有加了顶部导航栏,但是Android这样的移动设备内存是受限的,那么多界面缓存到内存中,很容易导致内存溢出,这个是比较致命的,所以不得不考虑.虽然我在之前也做过网易的顶部导航栏但是方式并不好,就像使用viewpager做一些复杂的界面由于图片占用内存过多,很容易导致内存溢出,学习了今天的内容大家做一下对比相信

  • Android项目实战之仿网易新闻的页面(RecyclerView )

    本文实例实现一个仿网易新闻的页面,上面是轮播的图片,下面是 RecyclerView 显示新闻列表,具体内容如下 错误方法 <?xml version="1.0" encoding="utf-8"?> <LinearLayout ...> <ViewPager ... /> <android.support.v7.widget.RecyclerView .../> </LinearLayout> 这样布局

  • Android实现网易新闻客户端首页效果

    关于实现网易新闻客户端的界面,以前写过很多博客,请参考: Android实现网易新闻客户端效果 Android实现网易新闻客户端侧滑菜单(一) Android实现网易新闻客户端侧滑菜单(二) 今天用ViewPager + FragmentAdapter + ViewPagerIndicator来实现. ViewPagerIndicator是一款分页指标小部件兼容ViewPager,封装上做得非常不错,目前已为众多知名应用所使用.具体API的使用,大家可以下载官方demo示例研究研究就知道啦! 下

  • Android实现仿网易今日头条等自定义频道listview 或者grideview等item上移到另一个view中

    我这里只是简单的用了两个listview来实现的,先上效果图.比较粗糙.预留了自定义的空间. 思路: 从上图应该可以看的出来.就是上下两个listview.点击下面的ltem.会动态的移动到上一个listview的最后.上面的listview 为listview1,下面的为listview2. 点击listview2,获取到view ,设置一个动画,移动到listview1 ,listview2中删除被点的item.listview1中新增一个. 上代码: Mainactivity.java 部

  • Android客户端实现注册、登录详解(1)

    我们在开发安卓App时难免要与服务器打交道,尤其是对于用户账号信息的注册与登录更是每个Android开发人员必须掌握的技能,本文将对客户端的注册/登录功能的实现进行分析,不到之处还请指出. 在这里我们仅讨论客户端如何请求服务器进行注册,而服务器在收到客户端请求后进行的一系列操作并不在本文所述范围内,有兴趣大家可以参考 请求服务器 客户端在进行用户信息的注册和登录时一般使用post请求(携带参数)去服务器.以volley框架请求服务器为例,真正与服务器进行交互的就是如下代码: StringRequ

  • Android仿网易客户端顶部导航栏效果

    最近刚写了一个网易客户端首页导航条的动画效果,现在分享出来给大家学习学习.我说一下这个效果的核心原理.下面是效果图: 首先是布局,这个布局是我从网易客户端反编译后弄来的.大家看后应该明白,布局文件如下: <FrameLayout android:id="@id/column_navi" android:layout_width="fill_parent" android:layout_height="wrap_content" androi

  • Android打造属于自己的新闻平台(客户端+服务器)

    完全属于自己的新闻展示平台,展示给大家,希望大家喜欢. 一.新闻的数据库的构建 脚本代码如下:(使用的mysql5.0 数据库) SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; SET time_zone = "+00:00"; -- Database: `newsdemo` -- 表的结构 `news` CREATE TABLE IF NOT EXISTS `news` ( `id` int(10) NOT NULL AUTO_IN

  • 基于PHP后台的Android新闻浏览客户端

    本文实例为大家分享了Android新闻浏览客户端,基于php后台,供大家参考,具体内容如下 1.使用HBuilder进行PHP环境配置,测试是否可以查询MySQL语句,之前都已经详细说明过了. 2.此处php后台实现mysql的查询功能,并以JSON数据格式返回个客户端 在PHP此处建立一个mysql_connect.php文件,实现数据库的连接,并设置字符集格式. <?php $con = mysql_connect("localhost","root",&

  • Android实现仿网易新闻的顶部导航指示器

    我们知道,页面导航器(Navigator)在几乎所有的项目中都会用到,平时大多数时候为了节省时间,都会直接在github上面拿别人的开源项目来用,最近自己在复习自定义View,就尝试封装了一下,源码参考项目PagerSlidingTabStrip 大家先来看一下效果图 基于文字的页面导航器 基于图片的页面导航器 使用方法 主要步骤分为三步 1)在xml文件里面 <com.xujun.viewpagertabindicator.TabPagerIndicator android:id="@+

  • Android实现仿网易新闻主界面设计

    下面先来一张效果图 根据图片分析,要实现的有侧边栏DrawerLayout,ActionBar的颜色和菜单以及ActionBarDrawerToggle的动画效果. 在这之前,Theme要改成带有ActionBar的主题 android:theme="@android:style/Theme.Holo.Light" 一:侧边栏-DrawerLayout 根据官方文档,DrawerLayout布局的第一个视图是activity的主视图,第二个是侧边栏视图 因此主布局可以如下这样 Fram

随机推荐