左右滑动自定义控件

本文介绍了一种基于Android的滑动按钮控件实现方法,通过自定义布局和交互逻辑,实现了滑动显示隐藏侧边栏的功能。文章提供了完整的代码示例,包括MainActivity、自定义控件AbsLeftBottomView、MenuHorizontalScrollView等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近做了一个外包项目,用了滑动的按钮显示的界面,原本代码应该是从网上找的,源出处不详,后来我接手后顺手改了一下,把它做成了一个控件的形式。

随手放出来给大家一测吧。


这是MainActivity的代码:

public class MainActivity extends Activity {

	private AbsLeftBottomView mLeftView = null;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		initUI();
	}

	private void initUI() {
		View subView = LayoutInflater.from(this).inflate(R.layout.test_b, null);
		subView.findViewById(R.id.slide_menu_btn).setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				mLeftView.showLeftMenu();
			}
		});
		
		mLeftView = new AbsLeftBottomView(this, null) {
			
			@Override
			protected View returnYouView(Context context, ICallBackShow callBackShow) {
				// TODO Auto-generated method stub
				View subView = LayoutInflater.from(context).inflate(R.layout.test_a, null);
				
				return subView;
			}
		};
		mLeftView.addUpperView(subView);
		
		setContentView(mLeftView.getView());
	}
}

两个用到的布局文件:

test_a.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="@dimen/activity_horizontal_margin"
    android:background="#FFFFFF"
     >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" 
        android:textColor="#000000"
        />

</RelativeLayout>

text_b.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="@dimen/activity_horizontal_margin"
    android:background="#00FF00" >

    <Button
        android:id="@+id/slide_menu_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="左边栏按钮" />

    
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="测试" />
    
</RelativeLayout>

看看效果:

      


=====================================================================

以下为控件关键代码:

AbsLeftBottomView.java代码:

public abstract class AbsLeftBottomView {
	private static final String TAG = AbsLeftBottomView.class.getSimpleName();
	
	private Context mContext = null;
	private View mMainView = null; 
	
	private MenuHorizontalScrollView mScrollView = null;
	private LinearLayout mAddLayout = null;
	
	private View mSubView = null;
	
	private ICallBackShow mICallBackShow = null;
	public AbsLeftBottomView(Context context, ICallBackShow callBackShow) {
		mContext = context; 
		mICallBackShow = callBackShow;
		initUI();
	}
	
	/**
	 * 初始化,mainView为主界面,switchView为切换View
	 */
	public void addUpperView(View upperView) {
		View transparentView = new View(mContext);
		transparentView.setBackgroundColor(Color.TRANSPARENT);
		final View[] children = new View[] { transparentView, upperView };
		mScrollView.initViews(children, new IBottomViewListener() {
			
			@Override
			public int onGetWidth() {
				// TODO Auto-generated method stub
				int width = mSubView.getWidth();
				return width;
			}
			
			@Override
			public int onGetMeasuredWidth() {
				// TODO Auto-generated method stub
				int measuredWidth = mSubView.getMeasuredWidth();
				return measuredWidth;
			}
		});
	}
	
	public void showLeftMenu() {
		mScrollView.clickMenuBtn();
	}
	
	public View getView() {
		// TODO Auto-generated method stub
		return mMainView;
	}
	
	private void initUI() {
		mMainView = LayoutInflater.from(mContext).inflate(R.layout.just_use_for_widget_absleftbottomview, null);
		mScrollView = (MenuHorizontalScrollView) mMainView.findViewById(R.id.just_use_for_widget_absleftbottomview_ScrollView);
		mAddLayout = (LinearLayout) mMainView.findViewById(R.id.just_use_for_widget_absleftbottomview_Add_layout);
		mSubView = returnYouView(mContext, mICallBackShow);
		mAddLayout.addView(mSubView);
	}
	
	abstract protected View returnYouView(Context context, ICallBackShow callBackShow);
}


这是 MenuHorizontalScrollView.java 代码,彻彻底底改的别人的代码:

public class MenuHorizontalScrollView extends HorizontalScrollView {
	private static final String TAG = MenuHorizontalScrollView.class.getSimpleName();
	
	public interface IBottomViewListener {
		int onGetMeasuredWidth();
		
		int onGetWidth();
	}
	
	/* 当前控件 */
	private MenuHorizontalScrollView me;

	/* 菜单状态 */
	private boolean menuOut;

	/* 扩展宽度 */
	private final int ENLARGE_WIDTH = 80 + 35;

	/* 菜单的宽度 */
	private int menuWidth;

	/* 当前滑动的位置 */
	private int current;

	private int scrollToViewPos;

	private IBottomViewListener mIBottomViewListener = null;
	
	
	public MenuHorizontalScrollView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		init();
	}

	public MenuHorizontalScrollView(Context context, AttributeSet attrs) { 
		super(context, attrs);
		// TODO Auto-generated constructor stub
		init();
	}

	public MenuHorizontalScrollView(Context context, AttributeSet attrs,
			int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
		init();
	}

	private void init() {
		this.setHorizontalFadingEdgeEnabled(false);
		this.setVerticalFadingEdgeEnabled(false);
		this.me = this;
		this.me.setVisibility(View.INVISIBLE);
		this.menuOut = false;
	}

	public void initViews(View[] children, IBottomViewListener listener) {
		mIBottomViewListener = listener;
		Print.d(TAG, "initViews() width = " + listener.onGetWidth() + " # MeasuredWidth() = " +listener.onGetMeasuredWidth());
		ViewGroup parent = (ViewGroup) getChildAt(0);

		for (int i = 0; i < children.length; i++) {
			children[i].setVisibility(View.INVISIBLE);
			Print.d(TAG, "parent = " + parent + " # children = " + children);
			parent.addView(children[i]);
		}
		OnGlobalLayoutListener onGlLayoutistener = new MenuOnGlobalLayoutListener(parent, children/*, sizeCallBack*/);
		getViewTreeObserver().addOnGlobalLayoutListener(onGlLayoutistener);
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		return false;
	}

	public void clickMenuBtn() {
		if (!this.menuOut) {
			this.menuWidth = 0;
		} else {
			this.menuWidth = mIBottomViewListener.onGetMeasuredWidth() - this.ENLARGE_WIDTH;
		}
		menuSlide();
	}

	/**
	 * 滑动出菜单
	 */
	private void menuSlide() {
		if (this.menuWidth == 0) {
			this.menuOut = true;
		} else {
			this.menuOut = false;
		}
		me.scrollTo(this.menuWidth, 0);
		
//		if (this.menuOut == true)
//			this.menuBtn.setBackgroundResource(R.drawable.user_title);
//		else
//			this.menuBtn.setBackgroundResource(R.drawable.user_title);
	}

	@Override
	protected void onScrollChanged(int l, int t, int oldl, int oldt) {
		// TODO Auto-generated method stub
		super.onScrollChanged(l, t, oldl, oldt);
		if (l < (mIBottomViewListener.onGetMeasuredWidth() - this.ENLARGE_WIDTH) / 2) {
			this.menuWidth = 0;
		} else {
			this.menuWidth = mIBottomViewListener.onGetWidth() - this.ENLARGE_WIDTH;
		}
		this.current = l;
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		int x = (int) ev.getRawX();
		if ((this.current == 0 && x < this.scrollToViewPos)
				|| (this.current == this.scrollToViewPos * 2 && x > this.ENLARGE_WIDTH)) {
			return false;
		} else {
			if (ev.getAction() == MotionEvent.ACTION_UP) {
				menuSlide();
				return false;
			}
		}
		return super.onTouchEvent(ev);
	}

	/****************************************************/
	/*-												   -*/
	/*-			Class 			Area				   -*/
	/*-												   -*/
	/****************************************************/

	public class MenuOnGlobalLayoutListener implements OnGlobalLayoutListener {

		private ViewGroup parent;
		private View[] children;

		public MenuOnGlobalLayoutListener(ViewGroup parent, View[] children ) {

			this.parent = parent;
			this.children = children;
		}

		@Override
		public void onGlobalLayout() {
			// TODO Auto-generated method stub
			me.getViewTreeObserver().removeGlobalOnLayoutListener(this);
			this.parent.removeViewsInLayout(0, children.length);
			int width = me.getMeasuredWidth();
			int height = me.getMeasuredHeight();

			scrollToViewPos = 0;

			for (int i = 0; i < children.length; i++) {
				int[] dims = getViewDimens(i, width, height); 
				children[i].setVisibility(View.VISIBLE);
				parent.addView(children[i], dims[0], dims[1]);
				if (i == 0) {
					scrollToViewPos += dims[0];
				}
			}

			new Handler().post(new Runnable() {
				@Override
				public void run() {
					me.scrollBy(scrollToViewPos, 0);

					/* 视图不是中间视图 */
					me.setVisibility(View.VISIBLE);
//					menu.setVisibility(View.VISIBLE);
				}
			});
		}
		
		private int[] getViewDimens(int index, int width, int height) {
			int[] dimens = new int[2];
			dimens[0] = width;
			dimens[1] = height;
			
			/* 视图不是中间视图 */
			if (index != 1) {
				dimens[0] = width - ENLARGE_WIDTH;
			}
			return dimens;
		}
	}

}


这是ICallBackShow.java代码:

public interface ICallBackShow {
	void onShowSubView(int pos);
}


有一个布局如下:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <LinearLayout  
        android:id="@+id/just_use_for_widget_absleftbottomview_Add_layout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

</LinearLayout>

    <com.zt.slide_widget.widget.MenuHorizontalScrollView
        android:id="@+id/just_use_for_widget_absleftbottomview_ScrollView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="#00ffffff"
        android:fadingEdge="none"
        android:scrollbars="none" >

        <LinearLayout
            android:id="@+id/just_use_for_widget_absleftbottomview_Top"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:background="#00ffffff"
            android:orientation="horizontal" >
        </LinearLayout>
    </com.zt.slide_widget.widget.MenuHorizontalScrollView>

</FrameLayout>


==========================================================================

结束,有需要的自己拿去。不想copy的自己到这里下载: http://download.youkuaiyun.com/detail/sasoritattoo/7261919






评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值