編輯:關於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 }<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ImageView android:id="@+id/iv" android:layout_width="match_parent" android:layout_height="200dp" android:contentDescription="@null" android:scaleType="centerCrop" android:src="@drawable/d" /> </LinearLayout> View Code
重寫的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 }<?xml version="1.0" encoding="utf-8"?> <com.demo.sb.adapter.SwipeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/sl" android:layout_width="match_parent" android:layout_height="80dp" android:background="#4000" > <LinearLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="horizontal" > <TextView android:id="@+id/tv_item_parcall" android:layout_width="100dp" android:layout_height="match_parent" android:background="#666" android:gravity="center" android:text="call" android:textColor="#fff" /> <TextView android:id="@+id/tv_item_pardel" android:layout_width="100dp" android:layout_height="match_parent" android:background="#f00" android:gravity="center" android:text="Delete" android:textColor="#fff" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="#4fff" android:padding="5dp" > <ImageView android:id="@+id/item_view" android:layout_width="80dp" android:layout_height="80dp" android:contentDescription="@null" android:scaleType="fitXY" android:src="@drawable/a" /> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="10dp" > <TextView android:id="@+id/item_parallax_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#f00" android:textSize="20sp" /> <TextView android:id="@+id/item_parallax_fight" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="10dp" android:text="" android:textColor="#5000" android:textSize="16sp" /> </LinearLayout> </LinearLayout> </com.demo.sb.adapter.SwipeLayout> View Code
手機APP創建桌面快捷方式,app創建快捷方式 預覽: 需要權限: 1 <uses-permission a
Android動態加載Dex機制解析 1.什麼是類加載器? 類加載器(class loader)是 Java?中的一個很重要的概念。類加載器負責加載 Java 類的字
小記:判斷設備是否聯網!,小記判斷設備聯網記住加權限: 1 package com.lixu.getInternet; 2 3 import android.a
Android仿美團切換城市 最近一直關注一些比較有名的app,像美團、58、趕集網、淘寶等等。主要目的就是學習下目前一些常用的技術,模擬一下它們的比較