Adroid应用中左右半屏功能的实现

在开发iNews的过程中用到了左右半屏的功能,这个功能也是目前非常多的APP中常见的功能。所以现在总结一套基于左右半屏的控件的开发模版,与各位同事交流一下。


在开发伊始选择控件的时候由于对Android不太熟悉,所以主要是参考网络上的一些资源,所以目前如果有其他的建议或者更好的控件,欢迎大家提出,谢谢!


对于左右半屏的应用,主要分为3部分,左屏视图(LeftView),中间主视图(MainView),右屏视图(RightView)。在最底层通过一个HorizontalVIew来组织,通过scroll方法实现半屏的滑动效果。


接下来主要介绍下具体代码和界面配置文件:

代码文件包括:MainActivity.java,ISizeCallBack.java,SizeCallBackForMenu.java,MenuHorizontalScrollView.java,SlidingLinearLayout.java

界面配置文件(放置在layout目录下):activity_main,xml,main_view.xml,left_view.xml,right_view.xml

MainActivity.java

public class MainActivity extends BaseAcitity implements View.OnClickListener {

    private MenuHorizontalScrollView scrollView = null;
	private View mainView = null;
    private LinearLayout slidLeftView = null;
    private LinearLayout slidRightView = null;

    private Button showLeftButton = null;
    private Button showRightButton = null;
    
    // 左侧按钮单击事件
    OnClickListener leftBtnListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            slidLeftView.setVisibility(View.VISIBLE);
            scrollView.clickLeftMenuBtn();
            slidRightView.setVisibility(View.INVISIBLE);
        }
    };

    // 右侧按钮单击事件
    OnClickListener rightBtnListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            siteListScrollView.clickRightMenuBtn();
        }
    };

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        inflater = LayoutInflater.from(this);
        try {
            
			

            // 半屏控件
            scrollView = (MenuHorizontalScrollView) findViewById(R.id.scrollView);
            slidLeftView = (LinearLayout) findViewById(R.id.slide_left);
            slidRightView = (LinearLayout) findViewById(R.id.slide_right);
            slidRightView.setVisibility(View.INVISIBLE);

            // MainView
            inflater = LayoutInflater.from(this);
            mainView = inflater.inflate(R.layout.main_view, null);
            showLeftButton = (Button) mainView
                    .findViewById(R.id.left_view_button);
            scrollView.setLeftMenuBtn(showLeftButton);
            showLeftButton.setOnClickListener(leftBtnListener);

            sysSettingButton = (Button) mainView
                    .findViewById(R.id.right_view_button);
            scrollView.setRightMenuBtn(showRightButton);
            showRightButton.setOnClickListener(rightBtnListener);

            // 初始化左右半屏控件
            View leftView = new View(this);
            leftView.setBackgroundColor(Color.TRANSPARENT);
            View rightView = new View(this);
            rightView.setBackgroundColor(Color.TRANSPARENT);
            View[] children = new View[] { leftView, newsPagerContainer,
                    rightView };
            scrollView.initViews(children, new SizeCallBackForMenu(
                    sitelistButton), slidLeftView, slidRightView);

            // 初始化主界面
            init();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    
    /********************* start left view ********************/

	//左半屏的相关操作放到这

    /********************* end left view ********************/

    /********************* start main view ********************/

	//主界面的相关操作放到这

    /**
     * 
     * 初始化主界面
     * 
     * */
    private void init() {

        //主界面初始化的操作
    }

    /********************* end main view ********************/

    /********************* start right view ********************/

    //右半屏的相关操作放到这

    /********************* end right view ********************/
}


ISizeCallBack.java

public interface ISizeCallBack {

	public void onGlobalLayout();

	public void getViewSize(int idx, int width, int height, int[] dims);
}

SizeCallBackForMenu.java

public class SizeCallBackForMenu implements ISizeCallBack {

	private Button menu;
	private int menuWidth;
	
	
	public SizeCallBackForMenu(Button menu){
		super();
		this.menu = menu;
	}
	@Override
	public void onGlobalLayout() {
		// TODO Auto-generated method stub
		this.menuWidth = this.menu.getMeasuredWidth() + 80;
	}

	@Override
	public void getViewSize(int idx, int width, int height, int[] dims) {
		// TODO Auto-generated method stub
		dims[0] = width;
		dims[1] = height;
		
		/*视图不是中间视图*/
		if(idx != 1){
			dims[0] = width - this.menuWidth;
		}
	}

}

MenuHorizontalScrollView.java

public class MenuHorizontalScrollView extends HorizontalScrollView {
	
	/*当前控件*/
	private MenuHorizontalScrollView me;
	
	/*菜单*/
	private View leftMenu;
	
	/*右边菜单*/
	private View rightMenu;
	
	/*左边菜单状态*/
	public static boolean leftMenuOut;
	
	/*右边菜单状态*/
	public static boolean rightMenuOut;
	
	/*扩展宽度*/
	private final int ENLARGE_WIDTH = 80;
	
	/*菜单的宽度*/
	private int leftMenuWidth;
	/*右边菜单的宽度*/
	private int rightMenuWidth;
	
	private int leftWidth;
	private int centerWidth;
	private int rightWidth;
	
	/*手势动作最开始时的x坐标*/
	private float lastMotionX = -1;
	
	/*按钮*/
	private Button leftMenuBtn;
	
	/*按钮*/
	private Button rightMenuBtn;
		
	/*当前滑动的位置*/
	private int current;
	
	private int scrollToViewPos;
	
	private boolean firstScroll = true;
	
	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);
		leftMenuOut = false;
		rightMenuOut = false;
	}
	
	public void initViews(View[] children, SizeCallBack sizeCallBack, View leftMenu,View rightMenu){
		this.leftMenu = leftMenu;
		this.rightMenu = rightMenu;
		
		
		ViewGroup	parent = (ViewGroup)getChildAt(0);
		
		for(int i = 0; i < children.length; i++){
			children[i].setVisibility(View.INVISIBLE);
			parent.addView(children[i]);
		}
		
		OnGlobalLayoutListener onGlLayoutistener = new  MenuOnGlobalLayoutListener(parent, 
				 children, sizeCallBack);
		getViewTreeObserver().addOnGlobalLayoutListener(onGlLayoutistener);
		 
	}
	
	 @Override
	 public boolean onInterceptTouchEvent(MotionEvent ev){
		 if(leftMenuOut||rightMenuOut){
				return true;
		}
	     return false;
	 }
	 
	 /**
	  * 设置按钮
	  * @param btn 
	  */
	 public void setLeftMenuBtn(Button btn){
		 this.leftMenuBtn = btn;
	 } 
	 
	 /**
	  * 设置按钮
	  * @param btn 
	  */
	 public void setRightMenuBtn(Button btn){
		 this.rightMenuBtn = btn;
	 } 
	 
	 
	 public void clickLeftMenuBtn(){

		 if(!leftMenuOut){
			 leftMenuOut = true;
		 }
		 else{
			 leftMenuOut = false;
		 }
		 leftMenuSlide();
	 }
	 
	 public void clickRightMenuBtn(){

		 if(!rightMenuOut){
			 rightMenuOut = true;
		 }
		 else{
			 rightMenuOut = false;
		 }
		 rightMenuSlide();
	 }
	 
	 /**
	  * 滑动出菜单
	  */
	 private void leftMenuSlide(){
		 
		 if(leftMenuOut){
			 me.smoothScrollTo(0, 0);
		 }
		 else{
			 me.smoothScrollTo(this.leftWidth, 0);
		 }
		
		 if(leftMenuOut == true)
			 this.leftMenuBtn.setBackgroundResource(R.drawable.sitelist_button_sel);
		 else
			 this.leftMenuBtn.setBackgroundResource(R.drawable.sitelist_button);
	 }
	 
	 /**
	  * 滑动出菜单
	  */
	 private void rightMenuSlide(){
		 
		 if(rightMenuOut){
			 me.scrollBy(this.leftWidth+this.rightWidth, 0);
		 }
		 else{
			 me.smoothScrollTo(this.leftWidth, 0);
		 }
		 if(rightMenuOut == true)
			 this.rightMenuBtn.setBackgroundResource(R.drawable.setting_button_sel);
		 else
			 this.rightMenuBtn.setBackgroundResource(R.drawable.setting_button);
	 }

	@Override
	protected void onScrollChanged(int l, int t, int oldl, int oldt) {
		// TODO Auto-generated method stub
		super.onScrollChanged(l, t, oldl, oldt);
		this.current = l;
	}
	


	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// TODO Auto-generated method stub
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		// TODO Auto-generated method stub
		super.onLayout(changed, l, t, r, b);
	}

	@Override
	public void fling(int velocityX) {
		// TODO Auto-generated method stub
		super.fling(velocityX);
	}

	@Override
	public void draw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.draw(canvas);
	}

	@Override
	public void scrollTo(int x, int y) {
	    if(!leftMenuOut){
	    	if(x<=0){
	    		x = this.leftWidth;
	    	}
	    }
	    if(!rightMenuOut){
	    	if(x>=(this.leftWidth+this.rightWidth)){
	    		x= this.leftWidth;
	    	}
	    }
	   
	    if (!leftMenuOut && !rightMenuOut && !firstScroll) {
            return;
        }
	   
		// TODO Auto-generated method stub
		super.scrollTo(x, y);
		if (x > 20) {
            firstScroll = false;
        }
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		int x = (int)ev.getRawX();
		
		if(ev.getAction() == MotionEvent.ACTION_DOWN){
			/*手指按下时的x坐标*/
			this.lastMotionX = (int)ev.getRawX();
		}
		if(leftMenuOut&& this.lastMotionX > this.leftWidth){
			clickLeftMenuBtn();
			return true;
		}
		if(rightMenuOut&&this.lastMotionX<(this.centerWidth - this.rightWidth)){
			clickRightMenuBtn();
			return true;
		}else{
			return false;
		}
	}


	/****************************************************/
	/*-												   -*/
	/*-			Class 			Area				   -*/
	/*-												   -*/
	/****************************************************/		
	
	public class MenuOnGlobalLayoutListener implements OnGlobalLayoutListener {
		
		private ViewGroup parent;
		private View[] children;
		//private int scrollToViewIndex = 0;
		private SizeCallBack sizeCallBack;
		
		public MenuOnGlobalLayoutListener(ViewGroup parent, View[] children, SizeCallBack sizeCallBack) {
			
			this.parent = parent;
			this.children = children;
			this.sizeCallBack = sizeCallBack;
		}

		@Override
		public void onGlobalLayout() {
			// TODO Auto-generated method stub
			me.getViewTreeObserver().removeGlobalOnLayoutListener(this);
	        this.sizeCallBack.onGlobalLayout();
	        this.parent.removeViewsInLayout(0, children.length);
	        int width = me.getMeasuredWidth();
	        int height = me.getMeasuredHeight();
	        leftWidth = (int)(width*0.42);
			rightWidth = (int)(width*0.8);
			centerWidth = me.getMeasuredWidth();
	        int[] dims = new int[2];
	        scrollToViewPos = 0;
	        
	        for(int i = 0; i < children.length; i++){
	        	children[i].setVisibility(View.VISIBLE);
	            if(i == 0){
	            	parent.addView(children[i], leftWidth, height);
	                scrollToViewPos += leftWidth;
	            }
	            if(i == 1){
	            	parent.addView(children[i], width, height);
	            }
	            if(i == 2){
	            	parent.addView(children[i], rightWidth, height);
	            	children[i].setVisibility(View.INVISIBLE);
	            }
	        }

            new Handler().post(new Runnable(){
                @Override
                public void run(){
                    
                    /*视图不是中间视图*/
                    me.setVisibility(View.VISIBLE);
                    leftMenu.setVisibility(View.VISIBLE);
                    rightMenu.setVisibility(View.INVISIBLE);
                }
            });
	    }
	}
}

SlidingLinearLayout.java
public class SlidingLinearLayout extends LinearLayout {

	/*手势动作最开始时的x坐标*/
	private float lastMotionX = -1;
	
	public SlidingLinearLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		//return super.onInterceptTouchEvent(ev);
		if(ev.getAction() == MotionEvent.ACTION_DOWN){
			this.lastMotionX = (int)ev.getRawX();
		}
		if(this.lastMotionX < 20)
			return true;
		else if(MenuHorizontalScrollView.leftMenuOut)
			return true;
		else 
			return super.onInterceptTouchEvent(ev);
	}

}
activity_main.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffffff"
     >
     
   	<!-- 右侧半屏布局 -->
    <LinearLayout
        android:id="@+id/slide_right"
	    android:layout_width="wrap_parent"
	    android:layout_height="match_parent">
	 
    	<!-- 具体的布局控件 -->
    
    </LinearLayout>
    
    <!-- 左侧半屏布局 -->
    <LinearLayout
        android:id="@+id/slide_left"
	    android:layout_width="match_parent"
	    android:layout_height="match_parent">
	 
    	<!-- 具体的布局控件 -->
    
    </LinearLayout>
    	
    <!-- ScrollView布局 -->
   	<com.bmdc.inews.MenuHorizontalScrollView
       	android:id="@+id/scroll_view"
        android:layout_width="match_parent" 
        android:layout_height="match_parent" 
        android:background="#00ffffff" 
        android:fadingEdge="none" 
        android:scrollbars="none"
        >
        <LinearLayout 
            android:id="@+id/top"
            android:layout_height="match_parent" 
            android:layout_width="match_parent"
            android:orientation="horizontal" 
            android:background="#00ffffff" 
           > 
        </LinearLayout> 
   	</com.bmdc.inews.MenuHorizontalScrollView>
   	
</FrameLayout>

main_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/acbuwa_page"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#ffffffff">
    <!-- 主界面Title的布局,通过其他配置文件生成,包含了控制左右半屏的Button和标题 -->
    <include 
        android:layout_width="match_parent" 
        android:layout_height="@dimen/base_action_bar_height" 
        layout="@layout/topbar" />
     
  	<com.bmdc.inews.SlidingLinearLayout
      	android:id="@+id/slidingLinearLayout"
      	android:layout_width="match_parent"
      	android:layout_height="match_parent"
      	android:background="#E8E8E8" >
	    <!-- 主界面的布局 -->
	</com.bmdc.inews.SlidingLinearLayout>  
</LinearLayout>

left_view.xml


right_view.xml


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值