編輯:關於android開發
如圖所示是效果圖,當向下拉時,圖片會被拉出來,松手後恢復。和ListView的側滑刪除

1.視差特效
首先圖片是通過addHeaderView加上去的,所以在設置Adapter前先設置一個View來作為頭布局,圖片的設置android:scaleType="centerCrop"
然後可以重寫ListView主要是用通過overScrollBy來實現圖片的拉出效果的,當拉出圖片繪制後,重寫onTouchEvent方法MotionEvent.ACTION_UP
實現回彈
如下是主代碼
1 package com.demo.sb.main;
2
3 import com.demo.sb.adapter.ParallacAdapter;
4 import com.demo.sb.widget.MyParallaxListView;
5 import com.demo.suibian.R;
6
7 import android.app.Activity;
8 import android.os.Bundle;
9 import android.view.View;
10 import android.view.Window;
11 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
12 import android.widget.ImageView;
13
14 /**
15 * 視差特效類型於QQ空間上的
16 *
17 * @author Administrator
18 *
19 */
20 public class MActivity_Parallac extends Activity {
21
22 private MyParallaxListView mListView;
23
24 @Override
25 protected void onCreate(Bundle savedInstanceState) {
26 // TODO Auto-generated method stub
27 super.onCreate(savedInstanceState);
28 requestWindowFeature(Window.FEATURE_NO_TITLE);
29 setContentView(R.layout.mactivity_parallax);
30
31 mListView = (MyParallaxListView) findViewById(R.id.lv);
32 mListView.setOverScrollMode(View.OVER_SCROLL_NEVER);
33 // 加上Header
34 final View mHeaderView = View.inflate(MActivity_Parallac.this,
35 R.layout.viewheader, null);
36 final ImageView mImage = (ImageView) mHeaderView.findViewById(R.id.iv);
37 mListView.addHeaderView(mHeaderView);
38
39 mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(
40 new OnGlobalLayoutListener() {
41
42 @Override
43 public void onGlobalLayout() {
44 // TODO Auto-generated method stub
45 mListView.setParallaxImage(mImage);
46
47 mHeaderView.getViewTreeObserver()
48 .removeGlobalOnLayoutListener(this);
49 }
50 });
51
52 // mListView.setAdapter(new SuibianAdapter(this));
53 mListView.setAdapter(new ParallacAdapter(this));
54 }
55 }

重寫的ListView
1 package com.demo.sb.widget;
2
3 import com.nineoldandroids.animation.ValueAnimator;
4 import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener;
5
6 import android.content.Context;
7 import android.util.AttributeSet;
8 import android.util.Log;
9 import android.view.MotionEvent;
10 import android.view.animation.Animation;
11 import android.view.animation.OvershootInterpolator;
12 import android.view.animation.Transformation;
13 import android.widget.ImageView;
14 import android.widget.ListView;
15
16 public class MyParallaxListView extends ListView{
17
18 private ImageView mImage;
19 private int drawableHeight;
20 private int mOriginalHeight;
21 public MyParallaxListView(Context context) {
22 super(context);
23 // TODO Auto-generated constructor stub
24 }
25
26 public MyParallaxListView(Context context, AttributeSet attrs) {
27 super(context, attrs);
28 // TODO Auto-generated constructor stub
29 }
30
31 public MyParallaxListView(Context context, AttributeSet attrs, int defStyle) {
32 super(context, attrs, defStyle);
33 // TODO Auto-generated constructor stub
34 }
35
36 /**
37 * 設置ImageView圖片,拿到引用
38 * @param mImage
39 */
40 public void setParallaxImage(ImageView mImage) {
41 // TODO Auto-generated method stub
42 this.mImage = mImage;
43 mOriginalHeight = mImage.getHeight();
44 drawableHeight = mImage.getDrawable().getIntrinsicHeight();
45
46 Log.d("jiejie", "height: " + mOriginalHeight + " drawableHeight: " + drawableHeight);
47 }
48
49 @Override
50 protected boolean overScrollBy(int deltaX, int deltaY, int scrollX,
51 int scrollY, int scrollRangeX, int scrollRangeY,
52 int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
53 // TODO Auto-generated method stub
54 // deltaY : 豎直方向的瞬時偏移量 / 變化量 dx 頂部到頭下拉為-, 底部到頭上拉為+
55 // scrollY : 豎直方向的偏移量 / 變化量
56 // scrollRangeY : 豎直方向滑動的范圍
57 // maxOverScrollY : 豎直方向最大滑動范圍
58 // isTouchEvent : 是否是手指觸摸滑動, true為手指, false為慣性
59
60 Log.d("jiejie", "deltaY: " +deltaY + " scrollY: " + scrollY + " scrollRangeY: " + scrollRangeY
61 + " maxOverScrollY: " + maxOverScrollY + " isTouchEvent: " + isTouchEvent);
62 //手指拉動並且是下拉
63 if(isTouchEvent && deltaY <0){
64 //把拉動的瞬時變化量的絕對值交給Header,就可以實現放大的效果了
65 if(mImage.getHeight() <=drawableHeight ){
66 int newHeight = (int)(mImage.getHeight() + Math.abs(deltaY / 3.0f));
67 //高度不超過圖片最大高度時,才讓其生效
68 mImage.getLayoutParams().height = newHeight;
69 mImage.requestLayout();
70 }
71 }
72
73 return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,
74 scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
75 }
76
77 @Override
78 public boolean onTouchEvent(MotionEvent ev) {
79 // TODO Auto-generated method stub
80
81 switch (ev.getAction()) {
82 case MotionEvent.ACTION_UP:
83 //執行回彈動畫,方式一:屬性動畫
84 //從當前高度mImage.getHeight(),執行動畫到原始高度mOriginalHeight
85 final int startHeight = mImage.getHeight();
86 final int endHeight = mOriginalHeight;
87 //ValueAnimator(startHeight,endHeight);
88
89
90 //執行回彈動畫,方式二:自定義Animation
91 ResetAnimation animation = new ResetAnimation(mImage,startHeight,endHeight);
92 startAnimation(animation);
93
94 break;
95
96 default:
97 break;
98 }
99 return super.onTouchEvent(ev);
100 }
101
102 private void ValueAnimator(final int startHeight, final int endHeight) {
103 // TODO Auto-generated method stub
104 ValueAnimator mValueAnimator = ValueAnimator.ofInt(1);
105 mValueAnimator.addUpdateListener(new AnimatorUpdateListener() {
106
107 @Override
108 public void onAnimationUpdate(ValueAnimator arg0) {
109 // TODO Auto-generated method stub
110 float fraction = arg0.getAnimatedFraction();
111 //percent 0.0-1.0
112 Integer newHeight = evaluate(fraction, startHeight, endHeight);
113
114 mImage.getLayoutParams().height = newHeight;
115 mImage.requestLayout();
116 }
117 });
118 mValueAnimator.setInterpolator(new OvershootInterpolator());
119 mValueAnimator.setDuration(800);
120 mValueAnimator.start();
121 }
122 /**
123 * 類型估值器
124 * @param fraction
125 * @param startValue
126 * @param endValue
127 * @return
128 */
129 public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
130 int startInt = startValue;
131 return (int)(startInt + fraction * (endValue - startInt));
132 }
133
134 /**
135 * 執行的動畫
136 * @author Administrator
137 *
138 */
139 private class ResetAnimation extends Animation{
140
141 private final ImageView mImageView;
142 private final int startHeight;
143 private final int endHeight;
144
145 public ResetAnimation(ImageView mImage, int startHeight, int endHeight) {
146 // TODO Auto-generated constructor stub
147 this.mImageView = mImage;
148 this.startHeight = startHeight;
149 this.endHeight = endHeight;
150 /**
151 * Interpolator被用來修飾動畫效果,定義動畫的變化率,可以使存在的動畫效果accelerated(加速)
152 * decelerated(減速),repeated(重復),bounced(彈跳)等
153 *
154 * OvershootInterpolator 向前甩一定值後再回到原來位置
155 */
156 setInterpolator(new OvershootInterpolator());
157 //設置動畫的執行時長
158 setDuration(800);
159 }
160 @Override
161 protected void applyTransformation(float interpolatedTime,
162 Transformation t) {
163 // TODO Auto-generated method stub
164 System.out.println(interpolatedTime );
165 //interpolatedTime 0.0f -> 1.0f
166 Integer newHeightInteger = evaluate(interpolatedTime, startHeight, endHeight);
167
168 mImageView.getLayoutParams().height = newHeightInteger;
169 mImageView.requestLayout();
170 super.applyTransformation(interpolatedTime, t);
171 }
172 }
173 }
2.實現ListView的側滑刪除功能
自定義的布局來顯示側滑的功能
1 package com.demo.sb.adapter;
2
3 import com.demo.sb.utils.DensityUtil;
4
5 import android.content.Context;
6 import android.graphics.Rect;
7 import android.support.v4.view.ViewCompat;
8 import android.support.v4.widget.ViewDragHelper;
9 import android.util.AttributeSet;
10 import android.view.MotionEvent;
11 import android.view.View;
12 import android.widget.FrameLayout;
13
14 /**
15 * 側拉刪除控件
16 *
17 * @author Administrator
18 *
19 */
20 public class SwipeLayout extends FrameLayout {
21
22 private Status status = Status.Close;
23 private OnSwipeLayoutListener swipeLayoutListener;
24
25 public Status getStatus() {
26 return status;
27 }
28
29 public void setStatus(Status status) {
30 this.status = status;
31 }
32
33 public OnSwipeLayoutListener getSwipeLayoutListener() {
34 return swipeLayoutListener;
35 }
36
37 public void setSwipeLayoutListener(OnSwipeLayoutListener swipeLayoutListener) {
38 this.swipeLayoutListener = swipeLayoutListener;
39 }
40
41 public static enum Status {
42 Close, Open, Draging
43 }
44
45 public static interface OnSwipeLayoutListener {
46 void onClose(SwipeLayout mSwipeLayout);
47
48 void onOpen(SwipeLayout mSwipeLayout);
49
50 void onDraging(SwipeLayout mSwipeLayout);
51
52 // 要去關閉
53 void onStartClose(SwipeLayout mSwipeLayout);
54
55 // 要去開啟
56 void onStartOpen(SwipeLayout mSwipeLayout);
57 }
58
59 public SwipeLayout(Context context) {
60 this(context, null);
61 // TODO Auto-generated constructor stub
62 }
63
64 public SwipeLayout(Context context, AttributeSet attrs) {
65 this(context, attrs, 0);
66 // TODO Auto-generated constructor stub
67 }
68
69 public SwipeLayout(Context context, AttributeSet attrs, int defStyle) {
70 super(context, attrs, defStyle);
71 // TODO Auto-generated constructor stub
72 mDragHelper = ViewDragHelper.create(this, 1.0f, mCallback);
73 }
74
75 ViewDragHelper.Callback mCallback = new ViewDragHelper.Callback() {
76 // c . 重寫監聽
77 @Override
78 public boolean tryCaptureView(View arg0, int arg1) {
79 // TODO Auto-generated method stub
80 return true;
81 }
82
83 // 限定移動范圍
84 public int clampViewPositionHorizontal(View child, int left, int dx) {
85 // left
86 if (child == mFrontView) {
87 if (left > 0) {
88 return 0;
89 } else if (left < -mRange) {
90 return -mRange;
91 }
92 } else if (child == mBackView) {
93 if (left > mWidth) {
94 return mWidth;
95 } else if (left < mWidth - mRange) {
96 return mWidth - mRange;
97 }
98 }
99 return left;
100 };
101
102 public void onViewPositionChanged(View changedView, int left, int top,
103 int dx, int dy) {
104 // 專遞事件
105 if (changedView == mFrontView) {
106 mBackView.offsetLeftAndRight(dx);
107 } else if (changedView == mBackView) {
108 mFrontView.offsetLeftAndRight(dx);
109 }
110 despatchSwipeEvent();
111
112 // 兼容老版本
113 invalidate();
114
115 };
116
117 public void onViewReleased(View releasedChild, float xvel, float yvel) {
118 if (xvel == 0 && mFrontView.getLeft() < -mRange / 2.0f) {
119 open();
120 } else if (xvel < 0) {
121 open();
122 } else {
123 close();
124 }
125 };
126
127 };
128
129 private ViewDragHelper mDragHelper;
130 private View mBackView;
131 private View mFrontView;
132 private int mHeight;
133 private int mWidth;
134 private int mRange;
135
136 // b. 專遞觸摸事件
137 @Override
138 public boolean onInterceptTouchEvent(MotionEvent ev) {
139 // TODO Auto-generated method stub
140 return mDragHelper.shouldInterceptTouchEvent(ev);
141 }
142
143 protected void despatchSwipeEvent() {
144 // TODO Auto-generated method stub
145 if (swipeLayoutListener != null) {
146 swipeLayoutListener.onDraging(this);
147 }
148 // 記錄上一次的狀態
149 Status preStatus = status;
150 // 更新當前的狀態
151 status = updateStatus();
152 if (preStatus != status && swipeLayoutListener != null) {
153 if (status == Status.Close) {
154 swipeLayoutListener.onClose(this);
155 } else if (status == Status.Open) {
156 swipeLayoutListener.onOpen(this);
157 } else if (status == Status.Draging) {
158 if (preStatus == Status.Close) {
159 swipeLayoutListener.onStartOpen(this);
160 } else if (preStatus == Status.Open) {
161 swipeLayoutListener.onStartClose(this);
162 }
163 }
164 }
165 }
166
167 private Status updateStatus() {
168
169 int left = mFrontView.getLeft();
170 if (left == 0) {
171 return Status.Close;
172 } else if (left == -mRange) {
173 return Status.Open;
174 }
175 return Status.Draging;
176 }
177
178 public void close() {
179 // TODO Auto-generated method stub
180 DensityUtil.showToast(getContext(), "Close");
181 close(true);
182 }
183
184 public void close(boolean isSmooth) {
185 // TODO Auto-generated method stub
186 int finalLeft = 0;
187 if (isSmooth) {
188 // 開始動畫
189 if (mDragHelper.smoothSlideViewTo(mFrontView, finalLeft, 0)) {
190 ViewCompat.postInvalidateOnAnimation(this);
191 }
192 } else {
193 layoutContent(false);
194 }
195 }
196
197 public void open() {
198 DensityUtil.showToast(getContext(), "Open");
199 open(true);
200 }
201
202 public void open(boolean isSmooth) {
203 int finalLeft = -mRange;
204 if (isSmooth) {
205 // 開始動畫
206 if (mDragHelper.smoothSlideViewTo(mFrontView, finalLeft, 0)) {
207 ViewCompat.postInvalidateOnAnimation(this);
208 }
209 } else {
210 layoutContent(true);
211 }
212 }
213
214 @Override
215 public void computeScroll() {
216 // TODO Auto-generated method stub
217 super.computeScroll();
218
219 if (mDragHelper.continueSettling(true)) {
220 ViewCompat.postInvalidateOnAnimation(this);
221 }
222 }
223
224 @Override
225 public boolean onTouchEvent(MotionEvent event) {
226 // TODO Auto-generated method stub
227 try {
228 mDragHelper.processTouchEvent(event);
229 } catch (Exception e) {
230 e.printStackTrace();
231 }
232 return true;
233 }
234
235 @Override
236 protected void onLayout(boolean changed, int left, int top, int right,
237 int bottom) {
238 // TODO Auto-generated method stub
239 super.onLayout(changed, left, top, right, bottom);
240 // 擺放位置
241 layoutContent(false);
242 }
243
244 private void layoutContent(boolean isOpen) {
245 // TODO Auto-generated method stub
246 // 擺放錢View
247 Rect frontRect = computeFrontViewRect(isOpen);
248 mFrontView.layout(frontRect.left, frontRect.top, frontRect.right,
249 frontRect.bottom);
250 // 擺放後View
251 Rect backRect = computeBackViewViaFront(frontRect);
252 mBackView.layout(backRect.left, backRect.top, backRect.right,
253 backRect.bottom);
254
255 // 調整順序,把mFrontView前置
256 bringChildToFront(mFrontView);
257 }
258
259 private Rect computeBackViewViaFront(Rect frontRect) {
260 // TODO Auto-generated method stub
261 int left = frontRect.right;
262 return new Rect(left, 0, left + mRange, 0 + mHeight);
263 }
264
265 private Rect computeFrontViewRect(boolean isOpen) {
266 // TODO Auto-generated method stub
267 int left = 0;
268 if (isOpen) {
269 left = -mRange;
270 }
271 return new Rect(left, 0, left + mWidth, 0 + mHeight);
272 }
273
274 @Override
275 protected void onFinishInflate() {
276 // TODO Auto-generated method stub
277 super.onFinishInflate();
278 mBackView = getChildAt(0);
279 mFrontView = getChildAt(1);
280 }
281
282 @Override
283 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
284 // TODO Auto-generated method stub
285 super.onSizeChanged(w, h, oldw, oldh);
286 mHeight = mFrontView.getMeasuredHeight();
287 mWidth = mFrontView.getMeasuredWidth();
288
289 mRange = mBackView.getMeasuredWidth();
290 }
291
292 }
1 package com.demo.sb.adapter;
2
3 import java.util.ArrayList;
4
5 import com.demo.sb.adapter.SwipeLayout.OnSwipeLayoutListener;
6 import com.demo.sb.utils.DensityUtil;
7 import com.demo.suibian.R;
8
9 import android.app.AlertDialog;
10 import android.content.Context;
11 import android.content.DialogInterface;
12 import android.view.View;
13 import android.view.ViewGroup;
14 import android.widget.BaseAdapter;
15 import android.widget.TextView;
16
17 public class ParallacAdapter extends BaseAdapter {
18
19 private Context context;
20 private int[] cost = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
21 private String[] nameStrings = { "宋江", "盧俊義", "吳用", "公孫勝", "關勝", "林沖",
22 "秦明", "呼延灼", "花榮", "柴進", "李應", "魯智深", "索超", "戴宗" };
23 private ArrayList<SwipeLayout> opendItems;
24
25 public ParallacAdapter(Context context) {
26 super();
27 this.context = context;
28
29 opendItems = new ArrayList<SwipeLayout>();
30 }
31
32 @Override
33 public int getCount() {
34 // TODO Auto-generated method stub
35 return nameStrings.length;
36 }
37
38 @Override
39 public Object getItem(int arg0) {
40 // TODO Auto-generated method stub
41 return nameStrings[arg0];
42 }
43
44 @Override
45 public long getItemId(int arg0) {
46 // TODO Auto-generated method stub
47 return arg0;
48 }
49
50 @Override
51 public View getView(final int arg0, View arg1, ViewGroup arg2) {
52 // TODO Auto-generated method stub
53 ViewHolder holder;
54 if (arg1 == null) {
55 holder = new ViewHolder();
56 arg1 = View.inflate(context, R.layout.item_parallac_list, null);
57 holder.tv_del = (TextView) arg1.findViewById(R.id.tv_item_pardel);
58 holder.tv_name = (TextView) arg1
59 .findViewById(R.id.item_parallax_name);
60 holder.tv_fight = (TextView) arg1
61 .findViewById(R.id.item_parallax_fight);
62 holder.tv_call = (TextView) arg1.findViewById(R.id.tv_item_parcall);
63 arg1.setTag(holder);
64 } else {
65 holder = (ViewHolder) arg1.getTag();
66 }
67
68 SwipeLayout sLayout = (SwipeLayout) arg1;
69 sLayout.setSwipeLayoutListener(new OnSwipeLayoutListener() {
70
71 @Override
72 public void onStartOpen(SwipeLayout mSwipeLayout) {
73 // TODO Auto-generated method stub
74 // 要去開啟時,先遍歷所有已打開的條目,逐個關閉
75 for (SwipeLayout layout : opendItems) {
76 layout.close();
77 }
78 opendItems.clear();
79 }
80
81 @Override
82 public void onStartClose(SwipeLayout mSwipeLayout) {
83 // TODO Auto-generated method stub
84
85 }
86
87 @Override
88 public void onOpen(SwipeLayout mSwipeLayout) {
89 // TODO Auto-generated method stub
90 opendItems.add(mSwipeLayout);
91 }
92
93 @Override
94 public void onDraging(SwipeLayout mSwipeLayout) {
95 // TODO Auto-generated method stub
96
97 }
98
99 @Override
100 public void onClose(SwipeLayout mSwipeLayout) {
101 // TODO Auto-generated method stub
102 opendItems.remove(mSwipeLayout);
103 }
104 });
105 holder.tv_name.setText("名字為 :" + nameStrings[arg0]);
106 holder.tv_fight.setText("戰斗力: " + cost[arg0]);
107 holder.tv_del.setOnClickListener(new View.OnClickListener() {
108
109 @Override
110 public void onClick(View view) {
111 // TODO Auto-generated method stub
112 DensityUtil.showToast(context, "第" + arg0 + "個 為"
113 + nameStrings[arg0]);
114 }
115 });
116 holder.tv_call.setOnClickListener(new View.OnClickListener() {
117
118 @Override
119 public void onClick(View view) {
120 // TODO Auto-generated method stub
121 AlertDialog.Builder builder = new AlertDialog.Builder(context);
122 builder.setTitle("標題!!!");
123 builder.setCancelable(false);
124 builder.setMessage("設置警告,是否確定刪除,刪除是不可逆的奧");
125 builder.setPositiveButton("確定",
126 new DialogInterface.OnClickListener() {
127
128 @Override
129 public void onClick(DialogInterface perent, int arg1) {
130 // TODO Auto-generated method stub
131 DensityUtil.showToast(context,
132 nameStrings[arg0]);
133 }
134 });
135 builder.setNegativeButton("取消",
136 new DialogInterface.OnClickListener() {
137
138 @Override
139 public void onClick(DialogInterface arg0, int arg1) {
140 // TODO Auto-generated method stub
141
142 }
143 });
144 builder.create().show();
145 }
146 });
147 return arg1;
148 }
149
150 static class ViewHolder {
151 TextView tv_del;
152 TextView tv_name;
153 TextView tv_fight;
154 TextView tv_call;
155 }
156 }

手機APP創建桌面快捷方式,app創建快捷方式
手機APP創建桌面快捷方式,app創建快捷方式 預覽: 需要權限: 1 <uses-permission a
Android動態加載Dex機制解析
Android動態加載Dex機制解析 1.什麼是類加載器? 類加載器(class loader)是 Java?中的一個很重要的概念。類加載器負責加載 Java 類的字
小記:判斷設備是否聯網!,小記判斷設備聯網
小記:判斷設備是否聯網!,小記判斷設備聯網記住加權限: 1 package com.lixu.getInternet; 2 3 import android.a
Android仿美團切換城市
Android仿美團切換城市 最近一直關注一些比較有名的app,像美團、58、趕集網、淘寶等等。主要目的就是學習下目前一些常用的技術,模擬一下它們的比較