編輯:關於Android編程
今天看到百度手機助手首頁上的滑動效果非常nice,主要功能歸結為:
1、當手指上劃時,頂部搜索欄隨手指移動距離而縮小到隱藏,隱藏後內容還是可以繼續移動
2、手指下滑時,當顯示內容達到第一個時,頂部搜索欄逐漸變大顯示
自己實現用到的知識:
1、android事件傳遞機制:捕獲到手指移動事件後,根據移動的方向與功能欄的高度對功能欄大小進行修改 。由於listview與功能欄高度要同時移動,需要重寫了dispatchTouchEvent方法,直接調用this.onTouchEvent(ev);進行所有事件的捕捉分析
2、自定義viewgroup:測量view高度
額外添加的功能:
功能欄高度<=1/2時,會自動隱藏
功能欄高度>1/2時,會自動改變到最大值
代碼實現在MotionEvent.ACTION_UP
效果展示,錄像工具太卡,將就著看吧:
vc/Dpr7NzbXAwcHLo6zU2lNjcm9sbEhpZGVMYXlvdXTA4NbQtqjS5cHLwb249rOjwb+jrNaxvdPQtMvAwcvQ6NKqsbuytrvxu6y2r8rCvP7T67jEseS089ChtcR2aWV3SUSjrMq508PKsb/J0tTX1Ly61Nm0zrfi17CjrLvy1d/Wsb3T0N64xElEo6zL5Mi7srvNxrz2o6y1q8rHyqHKwrn+o6GjoaOhPC9wPg0KPGJsb2NrcXVvdGU+DQoJPHA+cHJpdmF0ZSBpbnQgc2Nyb2xsVmlld0lkID0gUi5pZC5zY3JvbGxWaWV3OyAvL7ustq+687Hku6+5psTcwLi1xHZpZXdpZDxiciAvPg0KCXByaXZhdGUgaW50IGNoYW5nZVZpZXdJZCA9IFIuaWQuY2hhbmdlVmlldzsvLyC089Chy+bWrrHku6+1xHZpZXdpZDwvcD4NCjwvYmxvY2txdW90ZT4NCjxwPs3q1fu0+sLro7o8YnIgLz4NCjGhotfUtqjS5bXEdmlld2dyb3VwPC9wPg0KPHByZSBjbGFzcz0="brush:java;">
package com.example.materialtest.widget;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.graphics.PointF;
import android.graphics.RectF;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.LinearLayout;
import com.example.materialtest.R;
/**
* 滑動隱藏控件
*
*
*/
public class ScrollHideLayout extends LinearLayout implements OnScrollListener {
private static final String TAG = ScrollHideLayout.class.getSimpleName();
private int scrollViewId = R.id.scrollView;
private int changeViewId = R.id.changeView;
private int changeViewMaxHeight;
private PointF touchPoint = new PointF();
private View changeView;
private AbsListView scrollView;
private RectF scrollViewRect = new RectF();
public ScrollHideLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ScrollHideLayout(Context context) {
this(context, null);
}
public ScrollHideLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int len = getChildCount();
if (null == changeView || null == scrollView) {
for (int i = 0; i < len; i++) {
View child = getChildAt(i);
// 滑動控件
if (child.getId() == scrollViewId && child instanceof AbsListView) {
scrollView = (AbsListView) child;
setScrollViewRect();
}
if (child.getId() == changeViewId) {
changeView = child;
changeView.setMinimumHeight(0);
changeViewMaxHeight = changeView.getMeasuredHeight();
}
}
} else {
// 重新計算滾動控件的位置
setScrollViewRect();
}
Log.i(TAG, find scrollview and changeView : + scrollViewId + , + changeViewId);
Log.i(TAG, scrollview rect: + changeView.getLayoutParams().getClass().getCanonicalName());
if (null == changeView || null == scrollView) {
throw new IllegalArgumentException(could not foud changeView or scrollView);
}
}
private void setScrollViewRect() {
// 獲取滾動控件的范圍
float left = ViewCompat.getX(scrollView);
float top = ViewCompat.getY(scrollView);
float right = left + scrollView.getMeasuredWidth();
float bottom = top + scrollView.getMeasuredHeight();
scrollViewRect.left = left;
scrollViewRect.top = top;
scrollViewRect.right = right;
scrollViewRect.bottom = bottom;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (!isScrollViewTouch(ev)) {
return false;
}
final android.view.ViewGroup.LayoutParams params = changeView.getLayoutParams();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
touchPoint.x = ev.getX();
touchPoint.y = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
int height = params.height;
// 滑動控件移動事件
float distance = ev.getY() - touchPoint.y;
// 最大高度,不能向下拖動
if (height >= changeViewMaxHeight && distance > 0) {
touchPoint.y = ev.getY();
break;
}
// 已經隱藏 不能向上滑動
if (height <= 0 && distance < 0) {
touchPoint.y = ev.getY();
break;
}
// listview到達頂部才可以向下拖動
if (distance > 0 && scrollView.getFirstVisiblePosition() != 0) {
touchPoint.y = ev.getY();
break;
}
height = Math.round(height + distance);
if (height > changeViewMaxHeight) {
height = changeViewMaxHeight;
}
if (height <= 0 && distance < 0) {
height = 0;
// TODO onhide
}
params.height = height;
changeView.requestLayout();
touchPoint.x = ev.getX();
touchPoint.y = ev.getY();
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
// 高度超過一半,自動隱藏
int[] values = null;
// 向上滑動,剩余位置不足一半
if (params.height <= changeViewMaxHeight / 2) {
values = new int[] { params.height, 0 };
} else {
values = new int[] { params.height, changeViewMaxHeight };
}
if (null != values) {
ValueAnimator anim = ObjectAnimator.ofInt(changeView, translationY, values);
anim.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (int) animation.getAnimatedValue();
params.height = value;
changeView.requestLayout();
}
});
anim.setDuration(250);
anim.setTarget(changeView);
anim.start();
}
break;
}
return true;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// 直接攔截事件
this.onTouchEvent(ev);
return super.dispatchTouchEvent(ev);
}
private boolean isScrollViewTouch(MotionEvent ev) {
float x = ev.getX();
float y = ev.getY();
return (x >= scrollViewRect.left && x <= scrollViewRect.right) && (y >= scrollViewRect.top && y <= scrollViewRect.bottom);
}
/**
* @return Whether it is possible for the child view of this layout to
* scroll up. Override this if the child view is a custom view.
*/
public boolean canChildScrollUp() {
if (android.os.Build.VERSION.SDK_INT < 14) {
if (scrollView instanceof AbsListView) {
final AbsListView absListView = (AbsListView) scrollView;
return absListView.getChildCount() > 0
&& (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0).getTop() < absListView.getPaddingTop());
} else {
return ViewCompat.canScrollVertically(scrollView, -1) || scrollView.getScrollY() > 0;
}
} else {
return ViewCompat.canScrollVertically(scrollView, -1);
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
}
}
listview一般使用步驟:1.定制實體類,加入要填入list的變量,設置好set,get方法。2.自定義item布局,根據要填入的數據。3.自定義適配器類,繼承Arr
本文介紹利用ObjectAnimator簡單地實現ArcMenu,直接使用本文的ArcMenu類即可快捷地實現菜單功能。 最終使用效果:先看下最終的使用效果:
搜索框上下滑動變透明度是現在APP中很常見的效果,先看看效果:首先來看下布局骨架:<RelativeLayout xmlns:android=http://sche
首先上效果圖 大家微信都很熟悉了,這裡的效果就是仿照微信,在主界面左右滑動的時候,下面的導航圖標會產生漸變的效果,滑動是,之前圖標會慢慢變淡,當前的圖標會漸漸邊成選中的顏