iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >怎么在Android应用中实现一个抽屉效果
  • 263
分享到

怎么在Android应用中实现一个抽屉效果

androidroi 2023-05-31 08:05:35 263人浏览 八月长安
摘要

怎么在Android应用中实现一个抽屉效果?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。实现原理其实单就一个SwipeLayout的实现原理来讲的话,还是很简单

怎么在Android应用中实现一个抽屉效果?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

实现原理

其实单就一个SwipeLayout的实现原理来讲的话,还是很简单的,实际上单个SwipeLayout隐藏抽屉状态时,应该是这样的:

怎么在Android应用中实现一个抽屉效果

也就是说,最初的隐藏状态,实际上是将hide view区域layout到conten view的右边,达到隐藏效果,而后显示则是根据拖拽的x值变化来动态的layout 2个view,从而达到一个滑动抽屉效果。
当然,直接重写view的onTouchEvent来动态的layout 2个view是可以实现我们需要的效果的,但是有更好的方法来实现,就是同过ViewDragHelper。
ViewDragHelper是Google官方提供的一个专门用于手势分析处理的类,关于ViewDragHelper的基本使用,网上有一大堆的资源。具体的ViewDragHelper介绍以及基本使用方法,本文就不重复造轮子了,此处推荐鸿洋大神的一篇微博:Android ViewDragHelper完全解析 自定义ViewGroup神器。

具体实现

下面我们开始具体的实现。
布局比较简单,这里就不贴代码了,最后会贴上本demo的完整代码地址。

首先我们实现一个继承FrameLayout的自定义SwipeLauout,重写onFinishInflate方法:
这里我们只允许SwipeLayout设置2个子View,ContentLayout是继承LinearLayout的自定义layout,后面会讲到这个,此处先略过;

 @Override protected void onFinishInflate() {  super.onFinishInflate();  if (getChildCount() != 2) {   throw new IllegalStateException("Must 2 views in SwipeLayout");  }  contentView = getChildAt(0);  hideView = getChildAt(1);  if (contentView instanceof ContentLayout)   ((ContentLayout) contentView).setSwipeLayout(this);  else {   throw new IllegalStateException("content view must be an instanceof FrontLayout");  } }

接着重写onSizeChanged,onLayout,onInterceptTouchEvent方法:

 @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {  super.onSizeChanged(w, h, oldw, oldh);  hideViewHeight = hideView.getMeasuredHeight();  hideViewWidth = hideView.getMeasuredWidth();  contentWidth = contentView.getMeasuredWidth(); } @Override protected void onLayout(boolean changed, int left, int top, int right,       int bottom) {  // super.onLayout(changed, left, top, right, bottom);  contentView.layout(0, 0, contentWidth, hideViewHeight);  hideView.layout(contentView.getRight(), 0, contentView.getRight()    + hideViewWidth, hideViewHeight); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) {  boolean result = viewDragHelper.shouldInterceptTouchEvent(ev);  //  Log.e("SwipeLayout", "-----onInterceptTouchEvent-----");  return result; }

然后是比较关键的,重写onTouchEvent方法以及ViewDragHelper.Callback回调,我们定了一个enum来判断SwipeLayout的三种状态。在onViewPositionChanged中,有2种方法实现content view和hide view的伴随移动,一种是直接offset view的横向变化量,还有一种就是直接通过layout的方式,两种方式都可以。

 public enum SwipeState {  Open, Swiping, Close; } @Override public boolean onTouchEvent(MotionEvent event) {  //  Log.e("SwipeLayout", "-----onTouchEvent-----");  switch (event.getAction()) {   case MotionEvent.ACTION_DOWN:    downX = event.getX();    downY = event.getY();    break;   case MotionEvent.ACTION_MOVE:    // 1.获取x和y方向移动的距离    float moveX = event.getX();    float moveY = event.getY();    float delatX = moveX - downX;// x方向移动的距离    float delatY = moveY - downY;// y方向移动的距离    if (Math.abs(delatX) > Math.abs(delatY)) {     // 表示移动是偏向于水平方向,那么应该SwipeLayout应该处理,请求listview不要拦截     this.requestDisallowInterceptTouchEvent(true);    }    // 更新downX,downY    downX = moveX;    downY = moveY;    break;   case MotionEvent.ACTION_UP:    break;  }  viewDragHelper.processTouchEvent(event);  return true; } private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {  @Override  public boolean tryCaptureView(View child, int pointerId) {   return child == contentView || child == hideView;  }  @Override  public int getViewHorizontalDragRange(View child) {   return hideViewWidth;  }  @Override  public int clampViewPositionHorizontal(View child, int left, int dx) {   if (child == contentView) {    if (left > 0)     left = 0;    if (left < -hideViewWidth)     left = -hideViewWidth;   } else if (child == hideView) {    if (left > contentWidth)     left = contentWidth;    if (left < (contentWidth - hideViewWidth))     left = contentWidth - hideViewWidth;   }   return left;  }  @Override  public void onViewPositionChanged(View changedView, int left, int top,           int dx, int dy) {   super.onViewPositionChanged(changedView, left, top, dx, dy);   if (changedView == contentView) {    // 如果手指滑动deleteView,那么也要讲横向变化量dx设置给contentView    hideView.offsetLeftAndRight(dx);   } else if (changedView == hideView) {    // 如果手指滑动contentView,那么也要讲横向变化量dx设置给deleteView    contentView.offsetLeftAndRight(dx);   }   //   if (changedView == contentView) {   //    // 手动移动deleteView   //    hideView.layout(hideView.getLeft() + dx,   //      hideView.getTop() + dy, hideView.getRight() + dx,   //      hideView.getBottom() + dy);   //   } else if (hideView == changedView) {   //    // 手动移动contentView   //    contentView.layout(contentView.getLeft() + dx,   //      contentView.getTop() + dy, contentView.getRight() + dx,   //      contentView.getBottom() + dy);   //   }   //实时更新当前状态   updateSwipeStates();   invalidate();  }  @Override  public void onViewReleased(View releasedChild, float xvel, float yvel) {   super.onViewReleased(releasedChild, xvel, yvel);   //根据用户滑动速度处理开关   //xvel: x方向滑动速度   //yvel: y方向滑动速度   //   Log.e("tag", "currentState = " + currentState);   //   Log.e("tag", "xvel = " + xvel);   if (xvel < -200 && currentState != SwipeState.Open) {    open();    return;   } else if (xvel > 200 && currentState != SwipeState.Close) {    close();    return;   }   if (contentView.getLeft() < -hideViewWidth / 2) {    // 打开    open();   } else {    // 关闭    close();   }  } };

open(),close()实现

 public void open() {  open(true); } public void close() {  close(true); }  public void open(boolean iSSMooth) {  if (isSmooth) {   viewDragHelper.smoothSlideViewTo(contentView, -hideViewWidth,     contentView.getTop());   ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);  } else {   contentView.offsetLeftAndRight(-hideViewWidth);//直接偏移View的位置   hideView.offsetLeftAndRight(-hideViewWidth);//直接偏移View的位置   //   contentView.layout(-hideViewWidth, 0, contentWidth - hideViewWidth, hideViewHeight);//直接通过坐标摆放   //   hideView.layout(contentView.getRight(), 0, hideViewWidth, hideViewHeight);//直接通过坐标摆放   invalidate();  } }  public void close(boolean isSmooth) {  if (isSmooth) {   viewDragHelper.smoothSlideViewTo(contentView, 0, contentView.getTop());   ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);  } else {   contentView.offsetLeftAndRight(hideViewWidth);   hideView.offsetLeftAndRight(hideViewWidth);   invalidate();   //contentView.layout(0, 0, contentWidth, hideViewHeight);//直接通过坐标摆放   //hideView.layout(contentView.getRight(), 0, hideViewWidth, hideViewHeight);//直接通过坐标摆放  } }

此上基本实现了单个SwipeLayout的抽屉滑动效果,但是将此SwipeLayout作为一个item布局设置给一个listView的时候,还需要做许多的判断。

由于listView的重用机制,我们这里并未针对listview做任何处理,所以一旦有一个item的SwipeLayout的状态是打开状态,不可避免的其它也必然有几个是打开状态,所以我们这里需要根据检测listView的滑动,当listView滑动时,关闭SwipeLayout。既然需要在外部控制SwipeLayout的开关,我们先定义一个SwipeLayoutManager用于管理SwipeLayout的控制。

public class SwipeLayoutManager { //记录打开的SwipeLayout集合 private HashSet<SwipeLayout> mUnClosedSwipeLayouts = new HashSet<SwipeLayout>(); private SwipeLayoutManager() { } private static SwipeLayoutManager mInstance = new SwipeLayoutManager(); public static SwipeLayoutManager getInstance() {  return mInstance; }  public void add(SwipeLayout layout) {  mUnClosedSwipeLayouts.add(layout); }  public void remove(SwipeLayout layout){  mUnClosedSwipeLayouts.remove(layout); }  public void closeUnCloseSwipeLayout() {  if(mUnClosedSwipeLayouts.size() == 0){   return;  }  for(SwipeLayout l : mUnClosedSwipeLayouts){   l.close(true);  }  mUnClosedSwipeLayouts.clear(); }  public void closeUnCloseSwipeLayout(boolean isSmooth) {  if(mUnClosedSwipeLayouts.size() == 0){   return;  }  for(SwipeLayout l : mUnClosedSwipeLayouts){   l.close(isSmooth);  }  mUnClosedSwipeLayouts.clear(); }}

这样就可以监听listView的滑动,然后在listView滑动的时候,关闭所有的抽屉View。

 listView.setOnScrollListener(new OnScrollListener() {   @Override   public void onScrollStateChanged(AbsListView view, int scrollState) {    swipeLayoutManager.closeUnCloseSwipeLayout();   }   @Override   public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {   }  });

考虑到大多数时候,在我们打开抽屉View和关闭抽屉View的时候,外部需要知道SwipeLayout的状态值,所以我们需要在SwipeLayout中增加几个接口,告诉外部当前SwipeLayout的状态值:

SwipeLayout.java

---------------- private void updateSwipeStates() {  SwipeState lastSwipeState = currentState;  SwipeState swipeState = getCurrentState();  if (listener == null) {   try {    throw new Exception("please setOnSwipeStateChangeListener first!");   } catch (Exception e) {    e.printStackTrace();   }   return;  }  if (swipeState != currentState) {   currentState = swipeState;   if (currentState == SwipeState.Open) {    listener.onOpen(this);    // 当前的Swipelayout已经打开,需要让Manager记录    swipeLayoutManager.add(this);   } else if (currentState == SwipeState.Close) {    listener.onClose(this);    // 说明当前的SwipeLayout已经关闭,需要让Manager移除    swipeLayoutManager.remove(this);   } else if (currentState == SwipeState.Swiping) {    if (lastSwipeState == SwipeState.Open) {     listener.onStartClose(this);    } else if (lastSwipeState == SwipeState.Close) {     listener.onStartOpen(this);     //hideView准备显示之前,先将之前打开的的SwipeLayout全部关闭     swipeLayoutManager.closeUnCloseSwipeLayout();     swipeLayoutManager.add(this);    }   }  } else {   currentState = swipeState;  } }  public SwipeState getCurrentState() {  int left = contentView.getLeft();  //  Log.e("tag", "contentView.getLeft() = " + left);  //  Log.e("tag", "hideViewWidth = " + hideViewWidth);  if (left == 0) {   return SwipeState.Close;  }  if (left == -hideViewWidth) {   return SwipeState.Open;  }  return SwipeState.Swiping; } private OnSwipeStateChangeListener listener; public void setOnSwipeStateChangeListener(   OnSwipeStateChangeListener listener) {  this.listener = listener; } public View getContentView() {  return contentView; } public interface OnSwipeStateChangeListener {  void onOpen(SwipeLayout swipeLayout);  void onClose(SwipeLayout swipeLayout);  void onStartOpen(SwipeLayout swipeLayout);  void onStartClose(SwipeLayout swipeLayout); }

然后接下来是写一个为listView设置的SwipeAdapter

SwipeAdapter.java

------------public class SwipeAdapter extends BaseAdapter implements OnSwipeStateChangeListener { private Context mContext; private List<String> list; private MyClickListener myClickListener; private SwipeLayoutManager swipeLayoutManager; public SwipeAdapter(Context mContext) {  super();  this.mContext = mContext;  init(); } private void init() {  myClickListener = new MyClickListener();  swipeLayoutManager = SwipeLayoutManager.getInstance(); } public void setList(List<String> list){  this.list = list;  notifyDataSetChanged(); } @Override public int getCount() {  return list.size(); } @Override public Object getItem(int position) {  return list.get(position); } @Override public long getItemId(int position) {  return position; } @Override public View getView(final int position, View convertView, ViewGroup parent) {  if (convertView == null) {   convertView = UIUtils.inflate(R.layout.list_item_swipe);  }  ViewHolder holder = ViewHolder.getHolder(convertView);  holder.tv_content.setText(list.get(position));  holder.tv_overhead.setOnClickListener(myClickListener);  holder.tv_overhead.setTag(position);  holder.tv_delete.setOnClickListener(myClickListener);  holder.tv_delete.setTag(position);  holder.sv_layout.setOnSwipeStateChangeListener(this);  holder.sv_layout.setTag(position);  holder.sv_layout.getContentView().setOnClickListener(new View.OnClickListener() {   @Override   public void onClick(View v) {    ToastUtils.showToast("item click : " + position);    swipeLayoutManager.closeUnCloseSwipeLayout();   }  });  return convertView; } static class ViewHolder {  TextView tv_content, tv_overhead, tv_delete;  SwipeLayout sv_layout;  public ViewHolder(View convertView) {   tv_content = (TextView) convertView.findViewById(R.id.tv_content);   tv_overhead = (TextView) convertView.findViewById(R.id.tv_overhead);   tv_delete = (TextView) convertView.findViewById(R.id.tv_delete);   sv_layout = (SwipeLayout) convertView.findViewById(R.id.sv_layout);  }  public static ViewHolder getHolder(View convertView) {   ViewHolder holder = (ViewHolder) convertView.getTag();   if (holder == null) {    holder = new ViewHolder(convertView);    convertView.setTag(holder);   }   return holder;  } } class MyClickListener implements View.OnClickListener {  @Override  public void onClick(View v) {   Integer position = (Integer) v.getTag();   switch (v.getId()) {    case R.id.tv_overhead:     //ToastUtils.showToast("position : " + position + " overhead is clicked.");     }     break;    case R.id.tv_delete:     //ToastUtils.showToast("position : " + position + " delete is clicked.");     }     break;    default:     break;   }  } } @Override public void onOpen(SwipeLayout swipeLayout) {  //ToastUtils.showToast(swipeLayout.getTag() + "onOpen."); } @Override public void onClose(SwipeLayout swipeLayout) {  //ToastUtils.showToast(swipeLayout.getTag() + "onClose."); } @Override public void onStartOpen(SwipeLayout swipeLayout) {  //   ToastUtils.showToast("onStartOpen."); } @Override public void onStartClose(SwipeLayout swipeLayout) {  //   ToastUtils.showToast("onStartClose."); }}

此时已经基本实现了我们需要的大部分功能了,但是当我们滑动的时候,又发现新的问题,我们的SwipeLayout和listview滑动判断有问题。由于前面我们仅仅是将touch拦截事件简简单单的丢给了viewDragHelper.shouldInterceptTouchEvent(ev)来处理,导致SwipeLayout和listview拦截touch事件时的处理存在一定的问题,这里我们要提到一个知识点:Android view事件的传递。
(1)首先由Activity分发,分发给根View,也就是DecorView(DecorView为整个Window界面的最顶层View)
(2)然后由根View分发到子的View

view事件拦截如下图所示:

怎么在Android应用中实现一个抽屉效果

view事件的消费如下图所示:

怎么在Android应用中实现一个抽屉效果

注:以上2张图借鉴网上总结的比较经典的图

所以这里我们就要谈到一开始出现的ContentLayout,主要重写了onInterceptTouchEvent和onTouchEvent。

public class ContentLayout extends LinearLayout { SwipeLayoutInterface mISwipeLayout; public ContentLayout(Context context) {  super(context); } public ContentLayout(Context context, AttributeSet attrs) {  super(context, attrs); } public ContentLayout(Context context, AttributeSet attrs, int defStyleAttr) {  super(context, attrs, defStyleAttr); } public void setSwipeLayout(SwipeLayoutInterface iSwipeLayout) {  this.mISwipeLayout = iSwipeLayout; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) {//  Log.e("ContentLayout", "-----onInterceptTouchEvent-----");  if (mISwipeLayout.getCurrentState() == SwipeState.Close) {   return super.onInterceptTouchEvent(ev);  } else {   return true;  } } @Override public boolean onTouchEvent(MotionEvent ev) {//  Log.e("ContentLayout", "-----onTouchEvent-----");  if (mISwipeLayout.getCurrentState() == SwipeState.Close) {   return super.onTouchEvent(ev);  } else {   if (ev.getActionMasked() == MotionEvent.ACTION_UP) {    mISwipeLayout.close();   }   return true;  } }}

另外由于在ContentLayout中需要拿到父View SwipeLayout的开关状态以及控制SwipeLayout的关闭,因此在再写一个接口,用于ContentLayout获取SwipeLayout的开关状态以及更新SwipeLayout。

public interface SwipeLayoutInterface { SwipeState getCurrentState(); void open(); void close();}

然后接着的是完善SwipeLayout的onInterceptTouchEvent,我们在这里增加一个GestureDetectorCompat处理手势识别:

 private void init(Context context) {  viewDragHelper = ViewDragHelper.create(this, callback);  mGestureDetector = new GestureDetectorCompat(context, mOnGestureListener);  swipeLayoutManager = SwipeLayoutManager.getInstance(); } private SimpleOnGestureListener mOnGestureListener = new SimpleOnGestureListener() {  @Override  public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {   // 当横向移动距离大于等于纵向时,返回true   return Math.abs(distanceX) >= Math.abs(distanceY);  } };  @Override public boolean onInterceptTouchEvent(MotionEvent ev) {  boolean result = viewDragHelper.shouldInterceptTouchEvent(ev) & mGestureDetector.onTouchEvent(ev);  //  Log.e("SwipeLayout", "-----onInterceptTouchEvent-----");  return result; }

如此下来,整个View不管是上下拖动,还是SwipeLayout的开关滑动,都已经实现完成了。最后增加对应overhead,delete以及item的点击事件,此处完善SwipeAdapter的代码之后如下。

 class MyClickListener implements View.OnClickListener {  @Override  public void onClick(View v) {   Integer position = (Integer) v.getTag();   switch (v.getId()) {    case R.id.tv_overhead:     //ToastUtils.showToast("position : " + position + " overhead is clicked.");     swipeLayoutManager.closeUnCloseSwipeLayout(false);     if(onSwipeControlListener != null){      onSwipeControlListener.onOverhead(position, list.get(position));     }     break;    case R.id.tv_delete:     //ToastUtils.showToast("position : " + position + " delete is clicked.");     swipeLayoutManager.closeUnCloseSwipeLayout(false);     if(onSwipeControlListener != null){      onSwipeControlListener.onDelete(position, list.get(position));     }     break;    default:     break;   }  } } private OnSwipeControlListener onSwipeControlListener; public void setOnSwipeControlListener(OnSwipeControlListener onSwipeControlListener){  this.onSwipeControlListener = onSwipeControlListener; }  public interface OnSwipeControlListener{  void onOverhead(int position, String itemTitle);  void onDelete(int position, String itemTitle); }

最后贴上MainActivity代码,此处通过OnSwipeControlListener接口回调实现item的删除和置顶:

public class MainActivity extends Activity implements OnSwipeControlListener { private ListView listView; private List<String> list = new ArrayList<String>(); private SwipeLayoutManager swipeLayoutManager; private SwipeAdapter swipeAdapter; protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);  initData();  initView(); } private void initData() {  for (int i = 0; i < 50; i++) {   list.add("content - " + i);  } } private void initView() {  swipeLayoutManager = SwipeLayoutManager.getInstance();  swipeAdapter = new SwipeAdapter(this);  swipeAdapter.setList(list);  listView = (ListView) findViewById(R.id.list_view);  listView.setAdapter(swipeAdapter);  listView.setOnScrollListener(new OnScrollListener() {   @Override   public void onScrollStateChanged(AbsListView view, int scrollState) {    swipeLayoutManager.closeUnCloseSwipeLayout();   }   @Override   public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {   }  });  swipeAdapter.setOnSwipeControlListener(this); } @Override public void onOverhead(int position, String itemTitle) {  setItemOverhead(position, itemTitle); } @Override public void onDelete(int position, String itemTitle) {  removeItem(position, itemTitle); }  private void setItemOverhead(int position, String itemTitle) {  // ToastUtils.showToast("position : " + position + " overhead.");  ToastUtils.showToast("overhead ---" + itemTitle + "--- success.");  String newTitle = itemTitle;  list.remove(position);//删除要置顶的item  list.add(0, newTitle);//根据adapter传来的Title数据在list 0位置插入title字符串,达到置顶效果  swipeAdapter.setList(list);//重新给Adapter设置list数据并更新  UIUtils.runOnUIThread(new Runnable() {   @Override   public void run() {    listView.setSelection(0);//listview选中第0项item   }  }); }  private void removeItem(int position, String itemTitle) {  //  ToastUtils.showToast("position : " + position + " delete.");  ToastUtils.showToast("delete ---" + itemTitle + "--- success.");  list.remove(position);  swipeAdapter.setList(list);//重新给Adapter设置list数据并更新 }}

至此整个demo基本完成,本次完成的功能基本能够直接放到项目中使用。其实最麻烦的地方就在于view的touch事件拦截和处理,不过将本demo的log打开看一下对比之后,也就能够理解整个传递过程了。

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网精选频道,感谢您对编程网的支持。

--结束END--

本文标题: 怎么在Android应用中实现一个抽屉效果

本文链接: https://www.lsjlt.com/news/224465.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么在Android应用中实现一个抽屉效果
    怎么在Android应用中实现一个抽屉效果?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。实现原理其实单就一个SwipeLayout的实现原理来讲的话,还是很简单...
    99+
    2023-05-31
    android roi
  • Android应用中怎么实现一个抽屉效果
    这篇文章将为大家详细讲解有关Android应用中怎么实现一个抽屉效果,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。首先在layout 下设置xml布局文件<&#63;xml v...
    99+
    2023-05-31
    android roi
  • 怎么在Android中通过自定义View实现一个抽屉效果
    怎么在Android中通过自定义View实现一个抽屉效果?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Android 自定义View实现抽屉效果说明这个自定义V...
    99+
    2023-05-31
    android view roi
  • 使用CSS3怎么实现一个图片抽屉式效果
    这篇文章将为大家详细讲解有关使用CSS3怎么实现一个图片抽屉式效果,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。HTML代码:<div>   &nb...
    99+
    2023-06-08
  • 怎么在Android应用中实现一个动画效果
    本篇文章给大家分享的是有关怎么在Android应用中实现一个动画效果,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。Android 三种动画详解帧动画一张张图片不断的切换,形成动...
    99+
    2023-05-31
    android roi
  • 怎么在android应用中实现一个RecyclerView悬浮吸顶效果
    本篇文章为大家展示了怎么在android应用中实现一个RecyclerView悬浮吸顶效果,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。MultiType-Adapter打造悬浮吸顶效果注:当前版本...
    99+
    2023-05-31
    android recyclerview recycle
  • Android应用中怎么实现一个图片平铺效果
    这期内容当中小编将会给大家带来有关Android应用中怎么实现一个图片平铺效果,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1)第一种利用系统提供的api实现Bitmap bitmap = BitmapF...
    99+
    2023-05-31
    android roi
  • Android应用中怎么实现一个跟踪布局效果
    这篇文章给大家介绍Android应用中怎么实现一个跟踪布局效果,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。首页Activitypublic class TraceActivity extends AppCompatA...
    99+
    2023-05-31
    android roi
  • 怎么在Android应用中利用CoordinatorLayout实现一个标题滚动效果
    本篇文章为大家展示了怎么在Android应用中利用CoordinatorLayout实现一个标题滚动效果,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。在Material Design里,Coordi...
    99+
    2023-05-31
    coordinatorlayout android roi
  • 怎么在android应用中利用ViewPager实现一个滑动翻页效果
    这期内容当中小编将会给大家带来有关怎么在android应用中利用ViewPager实现一个滑动翻页效果,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。实现ViewPager的滑动翻页效果可以使用ViewPa...
    99+
    2023-05-31
    viewpager android age
  • 怎么在Android应用中利用Bitmap实现一个位图旋转效果
    怎么在Android应用中利用Bitmap实现一个位图旋转效果?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。位图的旋转也可以借助Matrix或者Canvas来实现。通过po...
    99+
    2023-05-31
    android bitmap roi
  • 怎么在android中利用ProgressDialog实现一个全屏效果
    怎么在android中利用ProgressDialog实现一个全屏效果?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。ProgressDialog的创建方式有两种,一种是ne...
    99+
    2023-05-30
  • 怎么在android中利用ProgressDialog实现一个加载效果
    怎么在android中利用ProgressDialog实现一个加载效果?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。先自定义一个类继承ProgressDialogpubli...
    99+
    2023-05-31
    android progressdialog gr
  • 怎么在Android中利用view实现一个太极效果
    怎么在Android中利用view实现一个太极效果?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Android自定义view实现太极效果实例代码之前一直想要个加载的load...
    99+
    2023-05-31
    android view roi
  • 如何在Android应用中实现一个Gallery画廊效果
    这期内容当中小编将会给大家带来有关如何在Android应用中实现一个Gallery画廊效果,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。画廊 使用Gallery表示,按水平方向显示内容,并且可以用手指直接...
    99+
    2023-05-31
    android gallery roi
  • 怎么在Android中实现一个花瓣飘落效果
    这篇文章给大家介绍怎么在Android中实现一个花瓣飘落效果,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Android是什么Android是一种基于Linux内核的自由及开放源代码的操作系统,主要使用于移动设备,如智...
    99+
    2023-06-14
  • 怎么在Android应用中实现一个加载数据帧动画效果
    这期内容当中小编将会给大家带来有关怎么在Android应用中实现一个加载数据帧动画效果,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。实现步骤:1、xml布局<&#63;xml version...
    99+
    2023-05-31
    android roi
  • Android应用中怎么实现一个导航键透明效果
    这期内容当中小编将会给大家带来有关Android应用中怎么实现一个导航键透明效果,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。MainActivity代码public class Ma...
    99+
    2023-05-31
    android roi
  • 怎么在Android中利用TextView实现一个跑马灯效果
    这期内容当中小编将会给大家带来有关怎么在Android中利用TextView实现一个跑马灯效果,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。TextView的跑马灯效果也就是指当你只想让TextView单...
    99+
    2023-05-31
    textview android roi
  • 如何在Android应用中实现一个列表悬浮效果
    这期内容当中小编将会给大家带来有关如何在Android应用中实现一个列表悬浮效果,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。具体方法如下:package com.xiaos.view;import an...
    99+
    2023-05-31
    android roi
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作