Android实现上下菜单双向滑动效果

这是研究了网上大神双向左右滑动后实现的上下双向滑动特效,有兴趣的朋友可以看下面代码,注释很详细,原理就是根据手指滑动的方向,来将上下两个布局进行显示与隐藏。主要用了onTouch方法,获取滑动的距离进行偏移。

import android.content.Context;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.view.View.OnTouchListener;
import android.widget.RelativeLayout; 

public class UpAndDownSlidinglayout extends RelativeLayout implements OnTouchListener{
  /**
   * 滚动显示和隐藏上侧布局时,手指滑动需要达到的速度。
   */
  public static final int SNAP_VELOCITY = 200; 

  /**
   * 滑动状态的一种,表示未进行任何滑动。
   */
  public static final int DO_NOTHING = 0;
  /**
   * 滑动状态的一种,表示正在滑出上侧菜单。
   */
  public static final int SHOW_UP_MENU = 1; 

  /**
   * 滑动状态的一种,表示正在滑出下侧菜单。
   */
  public static final int SHOW_DOWN_MENU = 2; 

  /**
   * 滑动状态的一种,表示正在隐藏上侧菜单。
   */
  public static final int HIDE_UP_MENU = 3; 

  /**
   * 滑动状态的一种,表示正在隐藏下侧菜单。
   */
  public static final int HIDE_DOWN_MENU = 4; 

  /**
   * 记录当前的滑动状态
   */
  private int slideState; 

  /**
   * 屏幕宽度值。
   */
  private int screenWidth;
  private int screenHeight; 

  /**
   * 在被判定为滚动之前用户手指可以移动的最大值。
   */
  private int touchSlop; 

  /**
   * 记录手指按下时的横坐标。
   */
  private float xDown; 

  /**
   * 记录手指按下时的纵坐标。
   */
  private float yDown; 

  /**
   * 记录手指移动时的横坐标。
   */
  private float xMove; 

  /**
   * 记录手指移动时的纵坐标。
   */
  private float yMove; 

  /**
   * 记录手机抬起时的纵坐标。
   */
  private float yUp;
  /**
   * 上侧菜单当前是显示还是隐藏。只有完全显示或隐藏时才会更改此值,滑动过程中此值无效。
   */
  private boolean isUpMenuVisible; 

  /**
   * 下侧菜单当前是显示还是隐藏。只有完全显示或隐藏时才会更改此值,滑动过程中此值无效。
   */
  private boolean isDownMenuVisible; 

  /**
   * 是否正在滑动。
   */
  private boolean isSliding; 

  /**
   * 上侧菜单布局对象。
   */
  private View upMenuLayout; 

  /**
   * 下侧菜单布局对象。
   */
  private View downMenuLayout; 

  /**
   * 内容布局对象。
   */
  private View contentLayout; 

  /**
   * 用于监听滑动事件的View。
   */
  private View mBindView; 

  /**
   * 上侧菜单布局的参数。
   */
  private MarginLayoutParams upMenuLayoutParams; 

  /**
   * 下侧菜单布局的参数。
   */
  private MarginLayoutParams downMenuLayoutParams; 

  /**
   * 内容布局的参数。
   */
  private RelativeLayout.LayoutParams contentLayoutParams; 

  /**
   * 用于计算手指滑动的速度。
   */
  private VelocityTracker mVelocityTracker; 

  public UpAndDownSlidinglayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    screenWidth = wm.getDefaultDisplay().getWidth();
    screenHeight = wm.getDefaultDisplay().getHeight();
    touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
  }
  /**
   * 绑定监听滑动事件的View。
   *
   * @param bindView
   *      需要绑定的View对象。
   */
  public void setScrollEvent(View bindView) {
    mBindView = bindView;
    mBindView.setOnTouchListener(this);
  }
  @Override
  public boolean onTouch(View v, MotionEvent event) {
    // TODO Auto-generated method stub
    createVelocityTracker(event);
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
      // 手指按下时,记录按下时的坐标
      xDown = event.getRawX();
      yDown = event.getRawY();
      // 将滑动状态初始化为DO_NOTHING
      slideState = DO_NOTHING;
      break;
    case MotionEvent.ACTION_MOVE:
      xMove = event.getRawX();
      yMove = event.getRawY();
      int moveDistanceX = (int) (xMove - xDown);
      int moveDistanceY = (int) (yMove - yDown);
      // 检查当前的滑动状态
      checkSlideState(moveDistanceX, moveDistanceY);
      switch (slideState) {
      case SHOW_UP_MENU:
        contentLayoutParams.bottomMargin = -moveDistanceY;
        checkUpMenuBorder();
        contentLayout.setLayoutParams(contentLayoutParams);
        break;
      case HIDE_UP_MENU:
        contentLayoutParams.bottomMargin = -upMenuLayoutParams.height - moveDistanceY;
        checkUpMenuBorder();
        contentLayout.setLayoutParams(contentLayoutParams);
      case SHOW_DOWN_MENU:
        contentLayoutParams.topMargin = moveDistanceY;
        checkDownMenuBorder();
        contentLayout.setLayoutParams(contentLayoutParams);
        break;
      case HIDE_DOWN_MENU:
        contentLayoutParams.topMargin = -downMenuLayoutParams.height + moveDistanceY;
        checkDownMenuBorder();
        contentLayout.setLayoutParams(contentLayoutParams);
      default:
        break;
      } 

      break;
    case MotionEvent.ACTION_UP:
      yUp = event.getRawY();
      int upDistanceY = (int) (yUp - yDown);
      if (isSliding) {
        // 手指抬起时,进行判断当前手势的意图
        switch (slideState) {
        case SHOW_UP_MENU:
          if (shouldScrollToUpMenu()) {
            scrollToUpMenu();
          } else {
            scrollToContentFromUpMenu();
          }
          break;
        case HIDE_UP_MENU:
          if (shouldScrollToContentFromUpMenu()) {
            scrollToContentFromUpMenu();
          } else {
            scrollToUpMenu();
          }
          break;
        case SHOW_DOWN_MENU:
          if (shouldScrollToDownMenu()) {
            scrollToDownMenu();
          } else {
            scrollToContentFromDownMenu();
          }
          break;
        case HIDE_DOWN_MENU:
          if (shouldScrollToContentFromDownMenu()) {
            scrollToContentFromDownMenu();
          } else {
            scrollToDownMenu();
          }
          break;
        default:
          break;
        }
      }else if (upDistanceY < touchSlop && isUpMenuVisible) {
        // 当上侧菜单显示时,如果用户点击一下内容部分,则直接滚动到内容界面
        scrollToContentFromUpMenu();
      } else if (upDistanceY < touchSlop && isDownMenuVisible) {
        // 当下侧菜单显示时,如果用户点击一下内容部分,则直接滚动到内容界面
        scrollToContentFromDownMenu();
      }
      recycleVelocityTracker();
      break;
    }
    return true;
  } 

  /**
   * 创建VelocityTracker对象,并将触摸事件加入到VelocityTracker当中。
   *
   * @param event
   *
   */
  private void createVelocityTracker(MotionEvent event) {
    if (mVelocityTracker == null) {
      mVelocityTracker = VelocityTracker.obtain();
    }
    mVelocityTracker.addMovement(event);
  } 

  /**
   * 根据手指移动的距离,判断当前用户的滑动意图,然后给slideState赋值成相应的滑动状态值。
   *
   * @param moveDistanceX
   *      横向移动的距离
   * @param moveDistanceY
   *      纵向移动的距离
   */
  private void checkSlideState(int moveDistanceX, int moveDistanceY) {
    if(isUpMenuVisible){
      if (!isSliding && Math.abs(moveDistanceY) >= touchSlop && moveDistanceY < 0) {
        isSliding = true;
        slideState = HIDE_UP_MENU;
      }
    }else if(isDownMenuVisible){
      if (!isSliding && Math.abs(moveDistanceY) >= touchSlop && moveDistanceY > 0) {
        isSliding = true;
        slideState = HIDE_DOWN_MENU;
      }
    }else{
      if (!isSliding && Math.abs(moveDistanceY) >= touchSlop && moveDistanceY > 0
          && Math.abs(moveDistanceX) < touchSlop) {
        isSliding = true;
        slideState = SHOW_UP_MENU;
        contentLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP, 0);
        contentLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        contentLayout.setLayoutParams(contentLayoutParams);
        // 如果用户想要滑动上侧菜单,将上侧菜单显示,下侧菜单隐藏
        upMenuLayout.setVisibility(View.VISIBLE);
        downMenuLayout.setVisibility(View.GONE);
      }else if(!isSliding && Math.abs(moveDistanceY) >= touchSlop && moveDistanceY < 0
          && Math.abs(moveDistanceX) < touchSlop){
        isSliding = true;
        slideState = SHOW_DOWN_MENU;
        contentLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, 0);
        contentLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
        contentLayout.setLayoutParams(contentLayoutParams);
        // 如果用户想要滑动下侧菜单,将下侧菜单显示,上侧菜单隐藏
        upMenuLayout.setVisibility(View.GONE);
        downMenuLayout.setVisibility(View.VISIBLE);
      }
    }
  } 

  /**
   * 在滑动过程中检查上侧菜单的边界值,防止绑定布局滑出屏幕。
   */
  private void checkUpMenuBorder() {
    if (contentLayoutParams.bottomMargin > 0) {
      contentLayoutParams.bottomMargin = 0;
    } else if (contentLayoutParams.bottomMargin < -upMenuLayoutParams.height) {
      contentLayoutParams.bottomMargin = -upMenuLayoutParams.height;
    }
  }
  /**
   * 在滑动过程中检查下侧菜单的边界值,防止绑定布局滑出屏幕。
   */
  private void checkDownMenuBorder() {
    if (contentLayoutParams.topMargin > 0) {
      contentLayoutParams.topMargin = 0;
    } else if (contentLayoutParams.topMargin < -downMenuLayoutParams.height) {
      contentLayoutParams.topMargin = -downMenuLayoutParams.height;
    }
  }
  /**
   * 判断是否应该滚动将上侧菜单展示出来。如果手指移动距离大于上侧菜单宽度的1/2,或者手指移动速度大于SNAP_VELOCITY,
   * 就认为应该滚动将上侧菜单展示出来。
   *
   * @return 如果应该将上侧菜单展示出来返回true,否则返回false。
   */
  private boolean shouldScrollToUpMenu() {
    return yUp - yDown > upMenuLayoutParams.height / 2 || getScrollVelocity() > SNAP_VELOCITY;
  } 

  /**
   * 判断是否应该滚动将下侧菜单展示出来。如果手指移动距离大于下侧菜单宽度的1/2,或者手指移动速度大于SNAP_VELOCITY,
   * 就认为应该滚动将下侧菜单展示出来。
   *
   * @return 如果应该将下侧菜单展示出来返回true,否则返回false。
   */
  private boolean shouldScrollToDownMenu() {
    return yDown - yUp > downMenuLayoutParams.height / 2 || getScrollVelocity() > SNAP_VELOCITY;
  } 

  /**
   * 判断是否应该从上侧菜单滚动到内容布局,如果手指移动距离大于上侧菜单宽度的1/2,或者手指移动速度大于SNAP_VELOCITY,
   * 就认为应该从上侧菜单滚动到内容布局。
   *
   * @return 如果应该从上侧菜单滚动到内容布局返回true,否则返回false。
   */
  private boolean shouldScrollToContentFromUpMenu() {
    return yDown - yUp > upMenuLayoutParams.height / 2 || getScrollVelocity() > SNAP_VELOCITY;
  } 

  /**
   * 判断是否应该从下侧菜单滚动到内容布局,如果手指移动距离大于下侧菜单宽度的1/2,或者手指移动速度大于SNAP_VELOCITY,
   * 就认为应该从下侧菜单滚动到内容布局。
   *
   * @return 如果应该从下侧菜单滚动到内容布局返回true,否则返回false。
   */
  private boolean shouldScrollToContentFromDownMenu() {
    return yUp - yDown > downMenuLayoutParams.height / 2 || getScrollVelocity() > SNAP_VELOCITY;
  }
  /**
   * 获取手指在绑定布局上的滑动速度。
   *
   * @return 滑动速度,以每秒钟移动了多少像素值为单位。
   */
  private int getScrollVelocity() {
    mVelocityTracker.computeCurrentVelocity(1000);
    int velocity = (int) mVelocityTracker.getXVelocity();
    return Math.abs(velocity);
  } 

  class UpMenuScrollTask extends AsyncTask<Integer, Integer, Integer> { 

    @Override
    protected Integer doInBackground(Integer... speed) {
      int bottomMargin = contentLayoutParams.bottomMargin;
      // 根据传入的速度来滚动界面,当滚动到达边界值时,跳出循环。
      while (true) {
        bottomMargin = bottomMargin + speed[0];
        if (bottomMargin < -upMenuLayoutParams.height) {
          bottomMargin = -upMenuLayoutParams.height;
          break;
        }
        if (bottomMargin > 0) {
          bottomMargin = 0;
          break;
        }
        publishProgress(bottomMargin);
        // 为了要有滚动效果产生,每次循环使线程睡眠一段时间,这样肉眼才能够看到滚动动画。
        sleep(15);
      }
      if (speed[0] > 0) {
        isUpMenuVisible = false;
      } else {
        isUpMenuVisible = true;
      }
      isSliding = false;
      return bottomMargin;
    } 

    @Override
    protected void onProgressUpdate(Integer... bottomMargin) {
      contentLayoutParams.bottomMargin = bottomMargin[0];
      contentLayout.setLayoutParams(contentLayoutParams);
      unFocusBindView();
    } 

    @Override
    protected void onPostExecute(Integer bottomMargin) {
      contentLayoutParams.bottomMargin = bottomMargin;
      contentLayout.setLayoutParams(contentLayoutParams);
    }
  } 

  class DownMenuScrollTask extends AsyncTask<Integer, Integer, Integer> { 

    @Override
    protected Integer doInBackground(Integer... speed) {
      int topMargin = contentLayoutParams.topMargin;
      // 根据传入的速度来滚动界面,当滚动到达边界值时,跳出循环。
      while (true) {
        topMargin = topMargin + speed[0];
        if (topMargin < -downMenuLayoutParams.height) {
          topMargin = -downMenuLayoutParams.height;
          break;
        }
        if (topMargin > 0) {
          topMargin = 0;
          break;
        }
        publishProgress(topMargin);
        // 为了要有滚动效果产生,每次循环使线程睡眠一段时间,这样肉眼才能够看到滚动动画。
        sleep(15);
      }
      if (speed[0] > 0) {
        isDownMenuVisible = false;
      } else {
        isDownMenuVisible = true;
      }
      isSliding = false;
      return topMargin;
    } 

    @Override
    protected void onProgressUpdate(Integer... topMargin) {
      contentLayoutParams.topMargin = topMargin[0];
      contentLayout.setLayoutParams(contentLayoutParams);
      unFocusBindView();
    } 

    @Override
    protected void onPostExecute(Integer topMargin) {
      contentLayoutParams.topMargin = topMargin;
      contentLayout.setLayoutParams(contentLayoutParams);
    }
  }
  /**
   * 使当前线程睡眠指定的毫秒数。
   *
   * @param millis
   *      指定当前线程睡眠多久,以毫秒为单位
   */
  private void sleep(long millis) {
    try {
      Thread.sleep(millis);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
  /**
   * 使用可以获得焦点的控件在滑动的时候失去焦点。
   */
  private void unFocusBindView() {
    if (mBindView != null) {
      mBindView.setPressed(false);
      mBindView.setFocusable(false);
      mBindView.setFocusableInTouchMode(false);
    }
  } 

  /**
   * 将界面滚动到上侧菜单界面,滚动速度设定为-30.
   */
  public void scrollToUpMenu() {
    new UpMenuScrollTask().execute(-30);
  } 

  /**
   * 将界面滚动到下侧菜单界面,滚动速度设定为-30.
   */
  public void scrollToDownMenu() {
    new DownMenuScrollTask().execute(-30);
  } 

  /**
   * 将界面从上侧菜单滚动到内容界面,滚动速度设定为30.
   */
  public void scrollToContentFromUpMenu() {
    new UpMenuScrollTask().execute(30);
  } 

  /**
   * 将界面从下侧菜单滚动到内容界面,滚动速度设定为30.
   */
  public void scrollToContentFromDownMenu() {
    new DownMenuScrollTask().execute(30);
  } 

  /**
   * 上侧菜单是否完全显示出来,滑动过程中此值无效。
   *
   * @return 上侧菜单完全显示返回true,否则返回false。
   */
  public boolean isUpLayoutVisible() {
    return isUpMenuVisible;
  } 

  /**
   * 下侧菜单是否完全显示出来,滑动过程中此值无效。
   *
   * @return 下侧菜单完全显示返回true,否则返回false。
   */
  public boolean isDownLayoutVisible() {
    return isDownMenuVisible;
  } 

  /**
   * 在onLayout中重新设定上侧菜单、下侧菜单、以及内容布局的参数。
   */
  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    super.onLayout(changed, l, t, r, b);
    if (changed) {
      // 获取上侧菜单布局对象
      upMenuLayout = getChildAt(0);
      upMenuLayoutParams = (MarginLayoutParams) upMenuLayout.getLayoutParams();
      // 获取下侧菜单布局对象
      downMenuLayout = getChildAt(1);
      downMenuLayoutParams = (MarginLayoutParams) downMenuLayout.getLayoutParams();
      // 获取内容布局对象
      contentLayout = getChildAt(2);
      contentLayoutParams = (RelativeLayout.LayoutParams) contentLayout.getLayoutParams();
      contentLayoutParams.height = screenHeight;
      contentLayout.setLayoutParams(contentLayoutParams);
    }
  }
  /**
   * 回收VelocityTracker对象。
   */
  private void recycleVelocityTracker() {
    mVelocityTracker.recycle();
    mVelocityTracker = null;
  }
} 

下面是使用实例:

import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.app.Activity; 

/**
 * 滑动菜单Demo主Activity
 *
 * @author guolin
 */
public class MainActivity2 extends Activity { 

  /**
   * 双向滑动菜单布局
   */
  private UpAndDownSlidinglayout updownSldingLayout; 

  /**
   * 在内容布局上显示的ListView
   */
  private ListView contentList;
  private LinearLayout ll;
  /**
   * ListView的适配器
   */
  private ArrayAdapter<String> contentListAdapter; 

  /**
   * 用于填充contentListAdapter的数据源。
   */
  private String[] contentItems = { "Content Item 1", "Content Item 2", "Content Item 3",
      "Content Item 4", "Content Item 5", "Content Item 6", "Content Item 7",
      "Content Item 8", "Content Item 9", "Content Item 10", "Content Item 11",
      "Content Item 12", "Content Item 13", "Content Item 14", "Content Item 15",
      "Content Item 16" }; 

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main2);
    ll = (LinearLayout) findViewById(R.id.content);
    updownSldingLayout = (UpAndDownSlidinglayout) findViewById(R.id.updown_sliding_layout);
    contentList = (ListView) findViewById(R.id.contentList);
    contentListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,
        contentItems);
    contentList.setAdapter(contentListAdapter);
    updownSldingLayout.setScrollEvent(ll);
  } 

} 

布局文件:

<com.example.UpAndDownSlidinglayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:id="@+id/updown_sliding_layout"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent" > 

  <RelativeLayout
    android:id="@+id/up_menu"
    android:layout_width="fill_parent"
    android:layout_height="300dp"
    android:layout_alignParentTop="true"
    android:background="#00ccff"
    android:visibility="invisible" > 

    <TextView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerInParent="true"
      android:text="This is up menu"
      android:textColor="#000000"
      android:textSize="28sp" />
  </RelativeLayout> 

  <RelativeLayout
    android:id="@+id/down_menu"
    android:layout_width="fill_parent"
    android:layout_height="300dp"
    android:layout_alignParentBottom="true"
    android:background="#00ffcc"
    android:visibility="invisible" > 

    <TextView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerInParent="true"
      android:text="This is down menu"
      android:textColor="#000000"
      android:textSize="28sp" />
  </RelativeLayout> 

  <LinearLayout
    android:id="@+id/content"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center"
    android:background="#e9e9e9" > 

    <ListView
      android:id="@+id/contentList"
      android:layout_width="fill_parent"
      android:layout_height="500dp"
      android:scrollbars="none"
      android:cacheColorHint="#00000000" >
    </ListView>
  </LinearLayout> 

</com.example.UpAndDownSlidinglayout>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

您可能感兴趣的文章:

  • Android实现顶部导航菜单左右滑动效果
  • Android滑动优化高仿QQ6.0侧滑菜单(滑动优化)
  • Android仿微信滑动弹出编辑、删除菜单效果、增加下拉刷新功能
  • Android实现自定义滑动式抽屉效果菜单
  • Android仿QQ滑动弹出菜单标记已读、未读消息
  • android RecyclerView侧滑菜单,滑动删除,长按拖拽,下拉刷新上拉加载
  • Android程序开发之使用Design包实现QQ动画侧滑效果和滑动菜单导航
  • Android模仿美团顶部的滑动菜单实例代码
  • Android侧滑菜单和轮播图之滑动冲突问题
  • Android解决viewpager嵌套滑动冲突并保留侧滑菜单功能
(0)

相关推荐

  • Android实现顶部导航菜单左右滑动效果

    本文给大家介绍在Android中如何实现顶部导航菜单左右滑动效果,具体内容如下 第一种解决方案: 实现原理是使用android-support-v4.jar包中ViewPager控件,在ViewPager控件中设置流布局,再在流布局中设置几项TextView,给每一个TextView设置相关参数,事件等.关于ViewPager控件可以设置全屏幕滑动效果,当然也可以实现局部滑动效果,下面介绍导航菜单. 关于导航菜单,相信大家对它并不陌生,比如在新闻客户端中就经常使用左右滑动菜单来显示不同类别的新闻

  • Android侧滑菜单和轮播图之滑动冲突问题

    接手一个项目,有一个问题需要修改:轮播图不能手动滑动,手动滑动轮播图只会触发侧滑菜单. 猜测:viewpager控件(轮播图)的触摸事件被SlidingMenu控件(侧滑菜单,非第三方项目,乃是上个开发人员自定义的)拦截了. 基于这个猜测,我自定义一个ViewPager,重写dispatchTouchEvent.onInterceptTouchEvent和onTouchEvent,分别在这三个方法中打印log: 重写SlidingMenu的dispatchTouchEvent.onInterce

  • Android程序开发之使用Design包实现QQ动画侧滑效果和滑动菜单导航

    Google在2015的IO大会上,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的Android Design Support Library,在这个support库里面,Google给我们提供了更加规范的MD设计风格的控件.最重要的是,Android Design Support Library的兼容性更广,直接可以向下兼容到Android 2.2.这不得不说是一个良心之作. 使用方法很简单,只需要添加一句依赖 compile 'com.android

  • Android模仿美团顶部的滑动菜单实例代码

    前言 本文主要给大家介绍了关于Android模仿美团顶部滑动菜单的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 先来看下效果图: 实现方法 这是通过 ViewPager 和 GridView 相结合做出来的效果,每一个 ViewPager 页面都是一个 GridView,底部的每个滑动指示圆点都是从布局文件中 inflate 出来的 首先需要一个代表每个活动主题的 JavaBean /** * Created by CZY on 2017/6/23. */ publ

  • Android解决viewpager嵌套滑动冲突并保留侧滑菜单功能

    重写子pagerview的dispatchTouchEvent方法,在返回前添加一句getParent().requestDisallowInterceptTouchEvent(true)中断掉事件的传递,类如下 public class SupperViewPager extends ViewPager { private int screenWidth;//屏幕宽度 public SupperViewPager(Context context) { super(context); } pub

  • Android实现自定义滑动式抽屉效果菜单

    在Andoird使用Android自带的那些组件,像SlidingDrawer和DrawerLayout都是抽屉效果的菜单,但是在项目很多要实现的功能都收到Android这些自带组件的限制,导致很难完成项目的需求,自定义的组件,各方面都在自己的控制之下,从而根据需求做出调整.想要实现好的效果,基本上都的基于Android的OnTouch事件自己实现响应的功能. 首先,给大家先看一下整体的效果: 滑动的加速度效果都是有的,具体的体验,只能安装后才能查看. 接下来,看代码: 代码从MainActiv

  • Android仿微信滑动弹出编辑、删除菜单效果、增加下拉刷新功能

    如何为不同的list item呈现不同的菜单,本文实例就为大家介绍了Android仿微信或QQ滑动弹出编辑.删除菜单效果.增加下拉刷新等功能的实现,分享给大家供大家参考,具体内容如下 效果图: 1. 下载开源项目,并将其中的liberary导入到自己的项目中: 2. 使用SwipeMenuListView代替ListView,在页面中布局: <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swipeRefresh

  • android RecyclerView侧滑菜单,滑动删除,长按拖拽,下拉刷新上拉加载

    本文介绍的库中的侧滑效果借鉴自SwipeMenu,并对SipwMenu的源码做了修改与Bug修复,然后才开发出的SwipeRecyclerView. 需要说明的是,本库没有对RecyclerView做大的修改,只是ItemView的封装.看起来是对RecyclerView的修改,其实仅仅是为RecyclerView添加了使用的方法API而已. 本库已经更新了三个版本了,会一直维护下去,根据小伙伴的要求,以后也会添加一些其它功能. SwipeRecyclerView将完美解决这些问题: 以下功能全

  • Android滑动优化高仿QQ6.0侧滑菜单(滑动优化)

     推荐阅读:Android使用ViewDragHelper实现仿QQ6.0侧滑界面(一) 但是之前的实现,只是简单的可以显示和隐藏左侧的菜单,但是特别生硬,而且没有任何平滑的趋势,那么今天就来优化一下吧,加上平滑效果,而且可以根据手势滑动的方向来判断是否是显示和隐藏. 首先先来实现手势判断是否隐藏和显示 这里就要用到了一个方法了,如下: 这个是ViewDradHelper里面的方法: /** * 当view被释放的时候处理的事情(松手) * * @param releasedChild 被释放的

  • Android仿QQ滑动弹出菜单标记已读、未读消息

    在上一篇<Android仿微信滑动弹出编辑.删除菜单效果.增加下拉刷新功能>里,已经带着大家学习如何使用SwipeMenuListView这一开源库实现滑动列表弹出菜单,接下来,将进一步学习,如何为不同的list item呈现不同的菜单,此处我们做一个实例:Android 高仿QQ滑动弹出菜单标记已读.未读消息,看下效果图: 1. 创建项目,并导入SwipeMenuListView类库 2. 创建消息实体bean: public class Msg { public int id; publi

随机推荐