转载请标明出处:http://blog.csdn.net/sk719887916/article/details/40074663,作者:skay
     最近项目中遇到一个LIstview的拖动效果,github上一搜发现有叫DragListview的开源项目,然后自己再小手一搜拖动排序的GridView,却没发现什么很全很好的开源项目,后来在博客上发现有一遍比较好的拖动排序的文章,可是跟自己的期望的IOS Luncher效果一比,相差那甚远,因此就在别人的代码基础加以开发,好的利用,不好的摒弃。

一 UI和功能分析

    发现目前主流的安卓厂商的手机桌面应用已经实现了此效果,也有APP实现的,如有UC浏览器,但是他貌似无抖动效果。先就Ios的桌面效果作如下需求总结:
 我们可以把ios的luncher拆分一下
如下图:

 特此我们可以将两个fragment加入同一个activty中,当然也可以将两个gridview放到一个线性布局中,即可,先从上面的Gridview进行分析。
    1  GridView长按支持拖动排序,并支持Item实时交换。
     2  GridView长按Item出现有抖动效果。
     3 Item条目有抖动效果,时不需要长按点击就可以进行拖动效果。
      4 拖动的Item和被拖动的Item左标完全重合后可新建文件夹
      5 长按Item 出现删除按钮,此时点击删除按钮可以任意删除某一item
      6 GridView横竖屏排列列数改变,横屏的行数是竖屏幕的列数

分析完主要功能之后我们就开始代码实现策略,方便我们理清思路。


  1. 根据手指按下的X,Y坐标来获取我们在GridView上面点击的item位置
  2. 根据当前屏幕状态,动态设置gridview的列数。做到横竖屏展现不同个列数的效果。
  3. 长按手指达不到规定的时间阀值,将无法拖动状态。时间超过将松开手指后,将gridView的子控件一次开启抖动动画。
  4. 如果我们长按了item则隐藏item,然后使用WindowManager来添加一个item的镜像在屏幕用来代替刚刚隐藏的item
  5. 当我们手指在屏幕移动的时候,更新item镜像的位置,然后在根据手指移动的X,Y的坐标来确定当前镜像的位置。
  6. 到GridView的item过多的时候,可能一屏幕显示不完,我们手指拖动item镜像到屏幕下方,要触发GridView想上滚动,同理,当我们手指拖动item镜像到屏幕上面,触发GridView向下滚动
  7. GridView交换数据,刷新界面,移除item的镜像,显示被影藏的item.
  8. 当抖动效果出现,点击删除按钮时,为了赠加移动效果,将要删除的item和末位item交换,然后删除lastItem,通知适配器更新数据。
  9. 抖动效果出现后,如果Onclick,就视为可拖动状态。
   接下来就开始实现需求所列的效果了。为了实现上面需求,需要写一个Gridview,Adapter,和抖动动画。包括移动是的动画。


新建动画控制器

 
 1  item实现抖动效果
 
  新建一个抖动的动画效果,用于每个item进行抖动。
  
  1. /**
  2. * NeedShake
  3. * @return
  4. */
  5. public boolean isNeedShake() {
  6. return mNeedShake;
  7. }
  8.  
  9. /**
  10. * @param mNeedShake
  11. */
  12. public void setNeedShake(boolean mNeedShake) {
  13. this.mNeedShake = mNeedShake;
  14. }
  15.  
  16. /**
  17. * ShakeAnimation isRunning
  18. * @return
  19. */
  20. private boolean isShowShake() {
  21.  
  22. return mNeedShake && mStartShake;
  23.  
  24. }
  25.  
  26. /**
  27. * start shakeAnimation
  28. * @param v
  29. */
  30. private void shakeAnimation(final View v) {
  31. float rotate = 0;
  32. int c = mCount++ % 15;
  33. if (c == 0) {
  34. rotate = DEGREE_0;
  35. } else if (c == 1) {
  36. rotate = DEGREE_1;
  37. } else if (c == 2) {
  38. rotate = DEGREE_2;
  39. } else if (c == 3) {
  40. rotate = DEGREE_3;
  41. } else {
  42. rotate = DEGREE_4;
  43. }
  44. final RotateAnimation mra = new RotateAnimation(rotate, -rotate,
  45. ICON_WIDTH * mDensity / 4, ICON_HEIGHT * mDensity / 4);
  46. final RotateAnimation mrb = new RotateAnimation(-rotate, rotate,
  47. ICON_WIDTH * mDensity / 4, ICON_HEIGHT * mDensity / 4);
  48.  
  49. mra.setDuration(ANIMATION_DURATION);
  50. mrb.setDuration(ANIMATION_DURATION);
  51.  
  52. mra.setAnimationListener(new AnimationListener() {
  53. @Override
  54. public void onAnimationEnd(Animation animation) {
  55. if (mNeedShake && mStartShake) {
  56. mra.reset();
  57. v.startAnimation(mrb);
  58. }
  59. }
  60.  
  61. @Override
  62. public void onAnimationRepeat(Animation animation) {
  63.  
  64. }
  65.  
  66. @Override
  67. public void onAnimationStart(Animation animation) {
  68.  
  69. }
  70.  
  71. });
  72.  
  73. mrb.setAnimationListener(new AnimationListener() {
  74. @Override
  75. public void onAnimationEnd(Animation animation) {
  76. if (mNeedShake && mStartShake) {
  77. mrb.reset();
  78. v.startAnimation(mra);
  79. }
  80. }
  81.  
  82. @Override
  83. public void onAnimationRepeat(Animation animation) {
  84.  
  85. }
  86.  
  87. @Override
  88. public void onAnimationStart(Animation animation) {
  89.  
  90. }
  91.  
  92. });
  93. v.startAnimation(mra);
  94. }

2 创建item交换是的动画

 
   
  1. private AnimatorSet createTranslationAnimations(View view, float startX,
  2. float endX, float startY, float endY) {
  3. ObjectAnimator animX = ObjectAnimator.ofFloat(view, "translationX",
  4. startX, endX);
  5. ObjectAnimator animY = ObjectAnimator.ofFloat(view, "translationY",
  6. startY, endY);
  7. AnimatorSet animSetXY = new AnimatorSet();
  8. animSetXY.playTogether(animX, animY);
  9. return animSetXY;
  10. }
  11.  
  12. /**
  13. * item的交换动画效果
  14. *
  15. * @param oldPosition
  16. * @param newPosition
  17. */
  18. private void animateReorder(final int oldPosition, final int newPosition) {
  19. boolean isForward = newPosition > oldPosition;
  20. List<Animator> resultList = new LinkedList<Animator>();
  21. if (isForward) {
  22. for (int pos = oldPosition; pos < newPosition; pos++) {
  23. View view = getChildAt(pos - getFirstVisiblePosition());
  24. System.out.println(pos);
  25.  
  26. if ((pos + 1) % mNumColumns == 0) {
  27. resultList.add(createTranslationAnimations(view,
  28. -view.getWidth() * (mNumColumns - 1), 0,
  29. view.getHeight(), 0));
  30. } else {
  31. resultList.add(createTranslationAnimations(view,
  32. view.getWidth(), 0, 0, 0));
  33. }
  34. }
  35. } else {
  36. for (int pos = oldPosition; pos > newPosition; pos--) {
  37. View view = getChildAt(pos - getFirstVisiblePosition());
  38. if ((pos + mNumColumns) % mNumColumns == 0) {
  39. resultList.add(createTranslationAnimations(view,
  40. view.getWidth() * (mNumColumns - 1), 0,
  41. -view.getHeight(), 0));
  42. } else {
  43. resultList.add(createTranslationAnimations(view,
  44. -view.getWidth(), 0, 0, 0));
  45. }
  46. }
  47. }
  48.  
  49. AnimatorSet resultSet = new AnimatorSet();
  50. resultSet.playTogether(resultList);
  51. resultSet.setDuration(300);
  52. resultSet.setInterpolator(new AccelerateDecelerateInterpolator());
  53. resultSet.addListener(new AnimatorListenerAdapter() {
  54. @Override
  55. public void onAnimationStart(Animator animation) {
  56. mAnimationEnd = false;
  57. }
  58.  
  59. @Override
  60. public void onAnimationEnd(Animator animation) {
  61. mAnimationEnd = true;
  62. }
  63. });
  64. resultSet.start();
  65. }


建立Adapter自定义监听器

 
    新建的Adapter用于Item的删除,隐藏,排序等,除了以上方法,也承担adapter适配数据源到grifView上的功能。
  1. ublic interface DragGridListener {
  2. /**
  3. * 重新排列数据
  4. * @param oldPosition
  5. * @param newPosition
  6. */
  7. public void reorderItems(int oldPosition, int newPosition);
  8.  
  9. /**
  10. * 设置某个item隐藏
  11. * @param hidePosition
  12. */
  13. public void setHideItem(int hidePosition);
  14.  
  15. /**
  16. * 删除某个item
  17. * @param hidePosition
  18. */
  19. public void removeItem(int hidePosition);
  20.  
  21. }

当然本次还未实现两个item建立文件夹,因此此接口后面还会陆续加入其扩展方法。


 adpter
 
    用来控制Item的添加和删除,已经隐藏交换等。
  1. public class DragAdapter extends BaseAdapter implements DragGridListener{
  2. private List<HashMap<String, Object>> list;
  3. private LayoutInflater mInflater;
  4. private int mHidePosition = -1;
  5.  
  6. public DragAdapter(Context context, List<HashMap<String, Object>> list){
  7. this.list = list;
  8. mInflater = LayoutInflater.from(context);
  9. }
  10.  
  11. @Override
  12. public int getCount() {
  13. return list.size();
  14. }
  15.  
  16. @Override
  17. public Object getItem(int position) {
  18. return list.get(position);
  19. }
  20.  
  21. @Override
  22. public long getItemId(int position) {
  23. return position;
  24. }
  25.  
  26. /**
  27. * 由于复用convertView导致某些item消失了,所以这里不复用item,
  28. */
  29. @Override
  30. public View getView(final int position, View convertView, ViewGroup parent) {
  31. convertView = mInflater.inflate(R.layout.grid_item, null);
  32. ImageView mImageView = (ImageView) convertView.findViewById(R.id.item_image);
  33. TextView mTextView = (TextView) convertView.findViewById(R.id.item_text);
  34.  
  35. mImageView.setImageResource((Integer) list.get(position).get("item_image"));
  36. mTextView.setText((CharSequence) list.get(position).get("item_text"));
  37.  
  38. if(position == mHidePosition){
  39. convertView.setVisibility(View.INVISIBLE);
  40. }
  41.  
  42. return convertView;
  43. }
  44.  
  45. @Override
  46. public void reorderItems(int oldPosition, int newPosition) {
  47. HashMap<String, Object> temp = list.get(oldPosition);
  48. if(oldPosition < newPosition){
  49. for(int i=oldPosition; i<newPosition; i++){
  50. Collections.swap(list, i, i+1);
  51. }
  52. }else if(oldPosition > newPosition){
  53. for(int i=oldPosition; i>newPosition; i--){
  54. Collections.swap(list, i, i-1);
  55. }
  56. }
  57.  
  58. list.set(newPosition, temp);
  59. }
  60.  
  61. @Override
  62. public void setHideItem(int hidePosition) {
  63. this.mHidePosition = hidePosition;
  64. notifyDataSetChanged();
  65. }
  66.  
  67. @Override
  68. public void removeItem(int deletePosition) {
  69.  
  70. list.remove(deletePosition);
  71. notifyDataSetChanged();
  72. }


GridVIew

 
 1 自定义DragridView继承GridView,重写onMueause()用来重新测量和根据横竖屏设置不同的列数
  
  1. @Override
  2. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  3.  
  4. if (mNumColumns == AUTO_FIT){
  5. if (isLandscape(getContext())) {
  6. mPaddingTopInit = (int) getResources().getDimension(R.dimen.HriontalPaddingTop);
  7. setNumColumns(mColumnNum_Hriztal);
  8.  
  9. } else {
  10. setNumColumns(mColumnNum);
  11. }
  12. }
  13.  
  14. setPadding(mPaddingLeftInit, mPaddingTopInit, mPaddingRightInit, mPaddingBottomInit);
  15. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  16. }

 
     2  重写dispatchTouchEvent()
 
      安卓事件是在dispatchTouchEvent()进行分发的,因此我们在这里拦截按下和移动,以及按键弹起等事件,在按下事件里获取按下的坐标,以及按了哪个item, 去获取当前itemview,并开启一个延时Runnable,用来控制抖动生效的阀值,当时间达到此阀值使拖动状态可用,同时也截取当前itemView保存为镜像图片。用于手指Move时充当window视图。手势松开时候许注销此定时器。
 mScrollRunnable是用来作为超出边界执行的定时器, 
 触发GridView向下滚动 或向上滚动。而我们这里还需要isShowShake是用来判断当前是否需要显示抖动效果,如果目前已经在抖动了,并且删除按钮可用的状态,长按的阀值将会设置为最小值,用来实现不用长按即可拖动Item的目的。
  1. @Override
  2. public boolean dispatchTouchEvent(MotionEvent ev) {
  3. switch (ev.getAction()) {
  4. case MotionEvent.ACTION_DOWN:
  5. mDownX = (int) ev.getX();
  6. mDownY = (int) ev.getY();
  7.  
  8. // 根据按下的X,Y坐标获取所点击item的position
  9. mDragPosition = pointToPosition(mDownX, mDownY);
  10.  
  11. if (mDragPosition == AdapterView.INVALID_POSITION) {
  12. return super.dispatchTouchEvent(ev);
  13. }
  14.  
  15. mStartDragItemView = getChildAt(mDragPosition
  16. - getFirstVisiblePosition());
  17.  
  18. //
  19. //performLongClick();
  20. if (isShowShake() && isShowDelele()) {
  21. dragResponseMS = dragResponseCT;
  22. }
  23. else {
  24. dragResponseMS = 1000 ;
  25. }
  26.  
  27. // 使用Handler延迟dragResponseMS执行mLongClickRunnable
  28. mHandler.postDelayed(mLongClickRunnable, dragResponseMS);
  29.  
  30. mPoint2ItemTop = mDownY - mStartDragItemView.getTop();
  31. mPoint2ItemLeft = mDownX - mStartDragItemView.getLeft();
  32.  
  33. mOffset2Top = (int) (ev.getRawY() - mDownY);
  34. mOffset2Left = (int) (ev.getRawX() - mDownX);
  35.  
  36. // 获取DragGridView自动向上滚动的偏移量,小于这个值,DragGridView向下滚动
  37. mDownScrollBorder = getHeight() / 5;
  38. // 获取DragGridView自动向下滚动的偏移量,大于这个值,DragGridView向上滚动
  39. mUpScrollBorder = getHeight() * 4 / 5;
  40.  
  41. // 开启mDragItemView绘图缓存
  42. mStartDragItemView.setDrawingCacheEnabled(true);
  43. // 获取mDragItemView在缓存中的Bitmap对象
  44. mDragBitmap = Bitmap.createBitmap(mStartDragItemView
  45. .getDrawingCache());
  46. // 这一步很关键,释放绘图缓存,避免出现重复的镜像
  47. mStartDragItemView.destroyDrawingCache();
  48.  
  49. break;
  50. case MotionEvent.ACTION_MOVE:
  51. int moveX = (int) ev.getX();
  52. int moveY = (int) ev.getY();
  53. if (!isTouchInItem(mStartDragItemView, moveX, moveY)) {
  54.  
  55. mHandler.removeCallbacks(mLongClickRunnable);
  56. }
  57. break;
  58. case MotionEvent.ACTION_UP:
  59. mHandler.removeCallbacks(mLongClickRunnable);
  60. mHandler.removeCallbacks(mScrollRunnable);
  61.  
  62. break;
  63. }
  64. return super.dispatchTouchEvent(ev);
  65. }

2 onTuch()

      主要用来处理当前手势,按下移动时就开始执行拖动,并执行抖动效果,弹起停止拖动效果,继续开启抖动动画,重新排列gridview

  1. @Override
  2. public boolean onTouchEvent(MotionEvent ev) {
  3. if (isDrag && mDragImageView != null) {
  4. switch (ev.getAction()) {
  5. case MotionEvent.ACTION_MOVE:
  6. moveX = (int) ev.getX();
  7. moveY = (int) ev.getY();
  8. onDragItem(moveX, moveY);
  9. onStartAnimation();
  10. break;
  11. case MotionEvent.ACTION_UP:
  12. onStopDrag();
  13. isDrag = false;
  14. onStartAnimation();
  15.  
  16. break;
  17. }
  18. return true;
  19. }
  20. return super.onTouchEvent(ev);
  21. }
 
 拖动某一个Item时 根据移动的x,y来实时更新当前截取的item镜像窗体位置位置。
  1. /**
  2. * 拖动item,在里面实现了item镜像的位置更新,item的相互交换以及GridView的自行滚动
  3. *
  4. * @param x
  5. * @param y
  6. */
  7. private void onDragItem(int moveX, int moveY) {
  8.  
  9. mDragAdapter.setHideItem(mDragPosition);
  10. //setHideSartItemView();
  11. mWindowLayoutParams.x = moveX - mPoint2ItemLeft + mOffset2Left;
  12. mWindowLayoutParams.y = moveY - mPoint2ItemTop + mOffset2Top
  13. - mStatusHeight;
  14. if (mDragImageView != null) {
  15. mWindowManager.updateViewLayout(mDragImageView, mWindowLayoutParams); // 更新镜像的位置
  16. }
  17. onSwapItem(moveX, moveY);
  18.  
  19. // GridView自动滚动
  20. mHandler.post(mScrollRunnable);
  21. }

手指弹起时,将镜像移除,将移动本身item设置为可见状态,

  1. /**
  2. * 停止拖拽我们将之前隐藏的item显示出来,并将镜像移除
  3. */
  4. private void onStopDrag() {
  5. View view = getChildAt(mDragPosition - getFirstVisiblePosition());
  6. if (view != null) {
  7. view.setVisibility(View.VISIBLE);
  8. }
  9. mDragAdapter.setHideItem(-1);
  10. removeDragImage();
  11. }

3 监听返回键 

 
 如果当前为抖动状态,并且删除按钮可见,就停止抖动动画,并影藏item的删除按钮。如果不在抖动状态,则直接退出。
 
  1. @Override
  2. public boolean onKeyDown(int keyCode, KeyEvent event) {
  3. if (keyCode == KeyEvent.KEYCODE_BACK) {
  4. pressAgainExit();
  5. return true;
  6. }
  7.  
  8. return super.onKeyDown(keyCode, event);
  9. }
  10.  
  11. /**
  12. * pressAgainExit
  13. */
  14. private void pressAgainExit() {
  15.  
  16. if (mEMrg.isExit() || mDeleteButton ==null ) {
  17. System.exit(0);
  18. } else {
  19. setHideDeleltButton();
  20.  
  21. if (mStartShake && mNeedShake) {
  22.  
  23. onStopAnimation();
  24. }
  25.  
  26. mEMrg.doExitInOneSecond();
  27. }
  28.  
  29. }

由于代码比较多 因此不一一做说明

具体代码如下详见开源地址:https://github.com/NeglectedByBoss/IOS_DragGridView


Activity

 
   用于初始化数据等,这里不做详细说明。
  1. /**
  2. *
  3. *
  4. * @author lyk
  5. *
  6. */
  7. public class DemoMainActivity extends Activity implements OnItemClickListener{
  8. private List<HashMap<String, Object>> dataSourceList = new ArrayList<HashMap<String, Object>>();
  9.  
  10. /**
  11. * 一页可见提条目数
  12. */
  13. private static final int VISIBIY_NUMS = 24;
  14. private DragAdapter mDragAdapter;
  15. @Override
  16. protected void onCreate(Bundle savedInstanceState) {
  17. super.onCreate(savedInstanceState);
  18. setContentView(R.layout.activity_main);
  19.  
  20. DragGridView mDragGridView = (DragGridView)findViewById(R.id.dragGridView);
  21. mDragGridView.setOnItemClickListener(this);
  22.  
  23. for (int i = 0; i < VISIBIY_NUMS; i++) {
  24. HashMap<String, Object> itemHashMap = new HashMap<String, Object>();
  25. Random random =new Random();
  26.  
  27. if (random.nextInt(3) == 1) {
  28. itemHashMap.put("item_image",R.drawable.ic_icon);
  29. }
  30.  
  31. if (random.nextInt(3) == 0) {
  32. itemHashMap.put("item_image",R.drawable.icon);
  33. }
  34.  
  35. else {
  36. itemHashMap.put("item_image",R.drawable.icon4);
  37. }
  38. itemHashMap.put("item_text", "icon" + Integer.toString(i));
  39. dataSourceList.add(itemHashMap);
  40. }
  41. mDragAdapter = new DragAdapter(this, dataSourceList);
  42.  
  43. mDragGridView.setAdapter(mDragAdapter);
  44. //设置需要抖动
  45. mDragGridView.setNeedShake(true);
  46. }
  47. @Override
  48. public void onItemClick(AdapterView<?> parent, View view, int position,
  49. long id) {
  50.  
  51. Toast.makeText(this, "onClick:" + position,
  52. Toast.LENGTH_SHORT).show();
  53. }
  54.  
  55. }

效果:

动态效果参考iphone桌面luncher效果。


 
    结束语:
 
   通过上面的实现方式我们简单的实现了需求中的以下几点:

    1  GridView长按支持拖动排序,并支持Item实时交换。
     2  GridView长按Item出现有抖动效果。
     3 Item条目有抖动效果,时不需要长按点击就可以进行拖动效果。
      5 长按Item 出现删除按钮,此时点击删除按钮可以任意删除某一item
      6 GridView横竖屏排列列数改变,横屏的行数是竖屏幕的列数
 对于建立文件夹,点击文件夹显示子集合view的暂未实现,包括一屏放置两个gridview并且互相拖动交换的功能也暂未实现,接下来的文章将会继续完善一下功能
欢迎阅读
如果你觉得此实现方式有欠缺的地方可以直接在gtihub上进行进一步完善,将自己的技术继续分享出来。谢谢你的阅读和支持
 参考博文:http://blog.csdn.net/xiaanming/article/details/17718579
  




Android 实现高仿iOS桌面效果之可拖动的GridView(上)的更多相关文章

  1. Android仿IOS回弹效果 ScrollView回弹 总结

    Android仿IOS回弹效果  ScrollView回弹 总结 应项目中的需求  须要仿IOS 下拉回弹的效果 , 我在网上搜了非常多 大多数都是拿scrollview 改吧改吧 试了一些  发现总 ...

  2. android版高仿淘宝客户端源码V2.3

    android版高仿淘宝客户端源码V2.3,这个版本我已经更新到2.3了,源码也上传到源码天堂那里了,大家可以看一下吧,该应用实现了我们常用的购物功能了,也就是在手机上进行网购的流程的,如查看产品(浏 ...

  3. 高仿IOS下拉刷新的粘虫效果

    最近看需要做一款下拉刷新的效果,由于需要和Ios界面保持一致,所以这用安卓的方式实现了ios下的下拉刷新的粘虫效果. 最新的安卓手机版本的QQ也有这种类似的效果,就是拖动未读信息的那个红色圆圈,拖动近 ...

  4. Android实现高仿QQ附近的人搜索展示

    本文主要实现了高仿QQ附近的人搜索展示,用到了自定义控件的方法 最终效果如下 1.下面展示列表我们可以使用ViewPager来实现(当然如果你不觉得麻烦,你也可以用HorizontalScrollVi ...

  5. Android DrawerLayout 高仿QQ5.2双向侧滑菜单

    1.概述 之前写了一个Android 高仿 QQ5.0 侧滑菜单效果 自定义控件来袭 ,恰逢QQ5.2又加了一个右侧菜单,刚好看了下DrawerLayout,一方面官方的东西,我都比较感兴趣:另一方面 ...

  6. 高仿ios版美团框架项目源码

    高仿美团框架基本已搭好.代码简单易懂,适合新人.适合新人.新人. <ignore_js_op>     源码你可以到ios教程网那里下载吧,这里我就不上传了,http://ios.662p ...

  7. 分享一个android仿ios桌面卸载的图标抖动动画

    直接上代码,如有更好的,还请不吝赐教 <span style="font-size:18px;"><?xml version="1.0" en ...

  8. android开发学习 ------- 仿QQ侧滑效果的实现

    需要做一个仿QQ侧滑删除的一个效果: 一开始是毫无头绪,百度找思路,找到  https://blog.csdn.net/xiaxiazaizai01/article/details/53036994  ...

  9. Swift高仿iOS网易云音乐Moya+RxSwift+Kingfisher+MVC+MVVM

    效果 列文章目录 因为目录比较多,每次更新这里比较麻烦,所以推荐点击到主页,然后查看iOS Swift云音乐专栏. 目简介 这是一个使用Swift(还有OC版本)语言,从0开发一个iOS平台,接近企业 ...

随机推荐

  1. Android 在 SElinux下 如何获得对一个内核节点的访问权限

    点击打开链接 Android 5.0下,因为采取了SEAndroid/SElinux的安全机制,即使拥有root权限,或者对某内核节点设置为777的权限,仍然无法在JNI层访问. 本文将以用户自定义的 ...

  2. android连接打印机

    android连接  网络打印,主要使用socket连接设备,发送指令给设备. 首先要有设备的IP,端口号一般默认的是9100 //打印设备网络IP etIp.setText("192.16 ...

  3. Android简易实战教程--第十三话《短信备份和还原~三》

    之前写过短信备份的小案例,哪里仅仅是虚拟了几条短信信息.本篇封装一个业务类,且直接通过内容提供者,访问本系统的短信信息,再提供对外接口.如果想要短信备份和短信还原,直接复制这段代码即可.对于您调用这个 ...

  4. ubuntu安装水星MW150US无线网卡8188eu驱动

    买了一个无线网卡插在ubuntu系统的电脑上,却不能识别出来.lsusb,可以看到下面的结果: Bus 002 Device 002: ID 0bda:8179 Realtek Semiconduct ...

  5. NoSQL数据库之Redis数据库:Redis的介绍与安装部署

     NoSQL(NoSQL = Not Only SQL),它指的是非关系型的数据库.随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的w ...

  6. Unity插件 - MeshEditor(一) 3D线段作画 & 模型网格编辑器

    之前,因为工作需要,项目中需要动态生成很多的电线,不能事先让模型做好,更不能用LineRenderer之类的,因为画出来没有3D的效果,最主要是拐角的时候还容易破面,而我们要的是真真实实纯3D的电线, ...

  7. #include <iostream>与#include <iostream.h>的区别

    在新的C++标准中,生成新头文件的方法仅仅是将现有C++头文件名中的   .h   去掉.例如,<iostream.h> 变成了<iostream> ,<complex. ...

  8. Volley请求

    1. Volley简介 我们平时在开发Android应用的时候不可避免地都需要用到网络技术,而多数情况下应用程序都会使用HTTP协议来发送和接收网络数据.Android系统中主要提供了两种方式来进行H ...

  9. 敏捷测试(7)--基于story的敏捷基础知识

    基于story的敏捷基础知识----迭代启动会.迭代回顾会 除需求讲解意外,需要所有团队成员参加的会议仅有两个,分别是"迭代启动会"和"迭代回顾会". (1)迭 ...

  10. MinerBean.java 数据库表 miner bean

    MinerBean.java 数据库表 miner bean package com.iteye.injavawetrust.miner; import java.util.Date; /** * 数 ...