MainActivity.java:
package com.example.slidinglayout;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
/**
* 侧滑布局对象,用于通过手指滑动将左侧的菜单布局进行显示或隐藏。
*/
private SlidingLayout slidingLayout;
/**
* menu按钮,点击按钮展示左侧布局,再点击一次隐藏左侧布局。
*/
private Button menuButton;
//测试TextView
private TextView mytv;
/**
* 放在content布局中的ListView。
*/
private ListView contentListView;
/**
* 作用于contentListView的适配器。
*/
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_main);
slidingLayout = (SlidingLayout) findViewById(R.id.slidingLayout);
menuButton = (Button) findViewById(R.id.menuButton);
mytv = (TextView) findViewById(R.id.mytv);
contentListView = (ListView) findViewById(R.id.contentList);
contentListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,
contentItems);
contentListView.setAdapter(contentListAdapter);
// 将监听滑动事件绑定在contentListView上
slidingLayout.setScrollEvent(contentListView);
menuButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (slidingLayout.isLeftLayoutVisible()) {
slidingLayout.scrollToRightLayout();
} else {
if (slidingLayout.getLeftLayout().getVisibility() != View.VISIBLE) {
slidingLayout.getLeftLayout().setVisibility(View.VISIBLE);
}
slidingLayout.scrollToLeftLayout();
}
}
});
mytv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "点击TextView",Toast.LENGTH_SHORT).show();
}
});
contentListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String text = contentItems[position];
Toast.makeText(MainActivity.this, text, Toast.LENGTH_SHORT).show();
}
});
}
}
activity_main.xml:
<com.example.slidinglayout.SlidingLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/slidingLayout" android:layout_width="fill_parent" android:layout_height="fill_parent" > <RelativeLayout android:id="@+id/menu" android:layout_width="270dip" android:layout_height="fill_parent" android:layout_alignParentLeft="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 menu" android:textColor="#000000" android:textSize="28sp" /> </RelativeLayout> <LinearLayout android:id="@+id/content" android:layout_width="320dip" android:layout_height="fill_parent" android:layout_alignParentRight="true" android:background="#e9e9e9" android:orientation="vertical" android:visibility="visible" > <Button android:id="@+id/menuButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Menu" /> <TextView android:id="@+id/mytv" android:textSize="18sp" android:layout_width="wrap_content" android:textColor="#000000" android:text="我的测试" android:layout_marginLeft="10dp" android:layout_height="wrap_content" /> <ListView android:id="@+id/contentList" android:layout_width="fill_parent" android:layout_height="fill_parent" android:cacheColorHint="#00000000" > </ListView> </LinearLayout> </com.example.slidinglayout.SlidingLayout>
SlidingLayout.java:
package com.example.slidinglayout; 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.View.OnTouchListener; import android.view.WindowManager; import android.widget.RelativeLayout; public class SlidingLayout extends RelativeLayout implements OnTouchListener { /** * 滚动显示和隐藏左侧布局时,手指滑动需要达到的速度。 */ public static final int SNAP_VELOCITY = 200; /** * 屏幕宽度值。 */ private int screenWidth; /** * 右侧布局最多可以滑动到的左边缘。 */ private int leftEdge = 0; /** * 右侧布局最多可以滑动到的右边缘。 */ private int rightEdge = 0; /** * 在被判定为滚动之前用户手指可以移动的最大值。 */ private int touchSlop; /** * 记录手指按下时的横坐标。 */ private float xDown; /** * 记录手指按下时的纵坐标。 */ private float yDown; /** * 记录手指移动时的横坐标。 */ private float xMove; /** * 记录手指移动时的纵坐标。 */ private float yMove; /** * 记录手机抬起时的横坐标。 */ private float xUp; /** * 左侧布局当前是显示还是隐藏。只有完全显示或隐藏时才会更改此值,滑动过程中此值无效。 */ private boolean isLeftLayoutVisible; /** * 是否正在滑动。 */ private boolean isSliding; /** * 左侧布局对象。 */ private View leftLayout; /** * 右侧布局对象。 */ private View rightLayout; /** * 用于监听侧滑事件的View。 */ private View mBindView; /** * 左侧布局的参数,通过此参数来重新确定左侧布局的宽度,以及更改leftMargin的值。 */ private MarginLayoutParams leftLayoutParams; /** * 右侧布局的参数,通过此参数来重新确定右侧布局的宽度。 */ private MarginLayoutParams rightLayoutParams; /** * 用于计算手指滑动的速度。 */ private VelocityTracker mVelocityTracker; /** * 重写SlidingLayout的构造函数,其中获取了屏幕的宽度。 * * @param context * @param attrs */ public SlidingLayout(Context context, AttributeSet attrs) { super(context, attrs); WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); screenWidth = wm.getDefaultDisplay().getWidth(); touchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); } public View getLeftLayout() { return leftLayout; } /** * 绑定监听侧滑事件的View,即在绑定的View进行滑动才可以显示和隐藏左侧布局。 * * @param bindView * 需要绑定的View对象。 */ public void setScrollEvent(View bindView) { mBindView = bindView; mBindView.setOnTouchListener(this); } /** * 将屏幕滚动到左侧布局界面,滚动速度设定为-30. */ public void scrollToLeftLayout() { new ScrollTask().execute(-30); } /** * 将屏幕滚动到右侧布局界面,滚动速度设定为30. */ public void scrollToRightLayout() { new ScrollTask().execute(30); } /** * 左侧布局是否完全显示出来,或完全隐藏,滑动过程中此值无效。 * * @return 左侧布局完全显示返回true,完全隐藏返回false。 */ public boolean isLeftLayoutVisible() { return isLeftLayoutVisible; } /** * 在onLayout中重新设定左侧布局和右侧布局的参数。 */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if (changed) { // 获取左侧布局对象 leftLayout = getChildAt(0); leftLayoutParams = (MarginLayoutParams) leftLayout .getLayoutParams(); leftLayoutParams.width = (int) (screenWidth * 0.8); // 设置左侧为屏幕宽度的0.8倍 rightEdge = -leftLayoutParams.width; // 获取右侧布局对象 rightLayout = getChildAt(1); rightLayoutParams = (MarginLayoutParams) rightLayout .getLayoutParams(); rightLayoutParams.width = screenWidth; rightLayout.setLayoutParams(rightLayoutParams); } } @Override public boolean onTouch(View v, MotionEvent event) { createVelocityTracker(event); if (leftLayout.getVisibility() != View.VISIBLE) { leftLayout.setVisibility(View.VISIBLE); } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 手指按下时,记录按下时的横坐标 xDown = event.getRawX(); yDown = event.getRawY(); break; case MotionEvent.ACTION_MOVE: // 手指移动时,对比按下时的横坐标,计算出移动的距离,来调整右侧布局的leftMargin值,从而显示和隐藏左侧布局 xMove = event.getRawX(); yMove = event.getRawY(); int moveDistanceX = (int) (xMove - xDown); int distanceY = (int) (yMove - yDown); if (!isLeftLayoutVisible && moveDistanceX >= touchSlop && (isSliding || Math.abs(distanceY) <= touchSlop)) { isSliding = true; rightLayoutParams.rightMargin = -moveDistanceX; if (rightLayoutParams.rightMargin < rightEdge) { rightLayoutParams.rightMargin = rightEdge; } rightLayout.setLayoutParams(rightLayoutParams); } if (isLeftLayoutVisible && -moveDistanceX >= touchSlop) { isSliding = true; rightLayoutParams.rightMargin = rightEdge - moveDistanceX; if (rightLayoutParams.rightMargin > leftEdge) { rightLayoutParams.rightMargin = leftEdge; } rightLayout.setLayoutParams(rightLayoutParams); } break; case MotionEvent.ACTION_UP: xUp = event.getRawX(); int upDistanceX = (int) (xUp - xDown); if (isSliding) { // 手指抬起时,进行判断当前手势的意图,从而决定是滚动到左侧布局,还是滚动到右侧布局 if (wantToShowLeftLayout()) { if (shouldScrollToLeftLayout()) { scrollToLeftLayout(); } else { scrollToRightLayout(); } } else if (wantToShowRightLayout()) { if (shouldScrollToRightLayout()) { scrollToRightLayout(); } else { scrollToLeftLayout(); } } } else if (upDistanceX < touchSlop && isLeftLayoutVisible) { scrollToRightLayout(); } recycleVelocityTracker(); break; } if (v.isEnabled()) { if (isSliding) { unFocusBindView(); return true; } if (isLeftLayoutVisible) { return true; } return false; } return true; } /** * 判断当前手势的意图是不是想显示右侧布局。如果手指移动的距离是负数,且当前左侧布局是可见的,则认为当前手势是想要显示右侧布局。 * * @return 当前手势想显示右侧布局返回true,否则返回false。 */ private boolean wantToShowRightLayout() { return xUp - xDown < 0 && isLeftLayoutVisible; } /** * 判断当前手势的意图是不是想显示左侧布局。如果手指移动的距离是正数,且当前左侧布局是不可见的,则认为当前手势是想要显示左侧布局。 * * @return 当前手势想显示左侧布局返回true,否则返回false。 */ private boolean wantToShowLeftLayout() { return xUp - xDown > 0 && !isLeftLayoutVisible; } /** * 判断是否应该滚动将左侧布局展示出来。如果手指移动距离大于屏幕的1/2,或者手指移动速度大于SNAP_VELOCITY, * 就认为应该滚动将左侧布局展示出来。 * * @return 如果应该滚动将左侧布局展示出来返回true,否则返回false。 */ private boolean shouldScrollToLeftLayout() { return xUp - xDown > leftLayoutParams.width / 2 || getScrollVelocity() > SNAP_VELOCITY; } /** * 判断是否应该滚动将右侧布局展示出来。如果手指移动距离加上leftLayoutPadding大于屏幕的1/2, * 或者手指移动速度大于SNAP_VELOCITY, 就认为应该滚动将右侧布局展示出来。 * * @return 如果应该滚动将右侧布局展示出来返回true,否则返回false。 */ private boolean shouldScrollToRightLayout() { return xDown - xUp > leftLayoutParams.width / 2 || getScrollVelocity() > SNAP_VELOCITY; } /** * 创建VelocityTracker对象,并将触摸事件加入到VelocityTracker当中。 * * @param event * 右侧布局监听控件的滑动事件 */ private void createVelocityTracker(MotionEvent event) { if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } mVelocityTracker.addMovement(event); } /** * 获取手指在右侧布局的监听View上的滑动速度。 * * @return 滑动速度,以每秒钟移动了多少像素值为单位。 */ private int getScrollVelocity() { mVelocityTracker.computeCurrentVelocity(1000); int velocity = (int) mVelocityTracker.getXVelocity(); return Math.abs(velocity); } /** * 回收VelocityTracker对象。 */ private void recycleVelocityTracker() { mVelocityTracker.recycle(); mVelocityTracker = null; } /** * 使用可以获得焦点的控件在滑动的时候失去焦点。 */ private void unFocusBindView() { if (mBindView != null) { mBindView.setPressed(false); mBindView.setFocusable(false); mBindView.setFocusableInTouchMode(false); } } class ScrollTask extends AsyncTask<Integer, Integer, Integer> { @Override protected Integer doInBackground(Integer... speed) { int rightMargin = rightLayoutParams.rightMargin; // 根据传入的速度来滚动界面,当滚动到达左边界或右边界时,跳出循环。 while (true) { rightMargin = rightMargin + speed[0]; if (rightMargin < rightEdge) { rightMargin = rightEdge; break; } if (rightMargin > leftEdge) { rightMargin = leftEdge; break; } publishProgress(rightMargin); // 为了要有滚动效果产生,每次循环使线程睡眠20毫秒,这样肉眼才能够看到滚动动画。 sleep(15); } if (speed[0] > 0) { isLeftLayoutVisible = false; } else { isLeftLayoutVisible = true; } isSliding = false; return rightMargin; } @Override protected void onProgressUpdate(Integer... rightMargin) { rightLayoutParams.rightMargin = rightMargin[0]; rightLayout.setLayoutParams(rightLayoutParams); unFocusBindView(); } @Override protected void onPostExecute(Integer rightMargin) { rightLayoutParams.rightMargin = rightMargin; rightLayout.setLayoutParams(rightLayoutParams); } } /** * 使当前线程睡眠指定的毫秒数。 * * @param millis * 指定当前线程睡眠多久,以毫秒为单位 */ private void sleep(long millis) { try { Thread.sleep(millis); } catch (InterruptedException e) { e.printStackTrace(); } } }
相关推荐
android左侧或右侧可选滑动菜单
使用Toolbar工具来实现DrawerLayout左侧滑动菜单;Menu实现方式:PopupMenu
Android左侧滑动菜单右侧Content 一个简单的例子,可以做出像QQ和人人的UI设计中左侧可以滑动显示出隐藏的菜单,右侧的内容随之改变的效果 是eclipse工程文档,直接导入即可。
主要实现左右滑动菜单效果,他可以点击主界面上的按钮来显示左右菜单,也可以通过左右滑动来显示,希望可以帮到你哦!!
自定义ViewGroup实现左侧菜单的滑动效果
Android项目导航菜单横向左右滑动并和下方的控件实现联动.rar
android 左边抽屉式菜单,具有滑动效果,可以自己调整速度,感觉还可以,分享一下~
在主界面手指向右滑动,就可以将菜单展示出来,而主界面会被隐藏大部分,但是仍有左侧的一小部分同菜单一起展示。
简单实用,很多代码很杂乱,为实现这种小功能网上许多代码是掺杂了各种各样的其他代码,很难读懂,小编简化了侧滑菜单的功能,自己实现了这一单一功能,以便下载者设计更加丰富的样式。
android滑动菜单,实现了 左边滑动和右边滑动
人人客户端有一个特效还是挺吸引人的,在主界面手指向右滑动,就可以将菜单展示出来,而主...但其实这种效果并不难实现,因此我今天给大家带来的也是史上最简单的滑动菜单实现方案。 首先还是讲一下实现原理。在一个A
android类似人人网的左边菜单滑动效果,点击首界面的左边按钮,则显示左边菜单栏,而此时首界面只显示左边的一小部分。点击菜单,回到首界面。 现在很多应用都采用这种效果
摘要:Java源码,Android源码,滑动菜单 Android滑动菜单制作RenRenSlidingLayout源代码,侧滑布局对象,用于通过手指滑动将左侧的菜单布局进行显示或隐藏,menu按钮,点击按钮展示左侧布局,再点击一次隐藏左侧布局,...
android 仿网易新闻客户端 左侧滑动
摘要:Java源码,Android源码,滑动菜单,滚动视图 Android版SlidingMenu滑动菜单 - 实现手动、自动滚动视图,提供右侧显示视图,右侧视图的滑动区域,只能在左侧视图范围内滑动,每次滑动记录一次移动位置,用于计算...
左右滑动,切换页面,滑动最左边,出现侧面菜单。
BidirSlidingLayout.java为双向滑动菜单框架,在这里可以设置滚动显示和隐藏左侧布局时,手指滑动需要达到的速度、记录当前的滑动状态、是否正在滑动等。左侧和右侧菜单当前是显示还是隐藏。只有完全显示或隐藏时才...
左侧竖向选项卡TAB导航烂,支持viewpager,不依赖viewpager,支持自定义tab样式,自带切换动画