您的位置:首页 > 编程语言

一个侧屏滑动操作的实例(仿遇见)之三:代码分析

2012-08-13 10:54 489 查看


一个侧屏滑动操作的实例(仿遇见)之三:代码分析

分类: android UI android
view2012-08-12 22:43 134人阅读 评论(0) 收藏 举报

首先看一下主activity:

[java] view
plaincopy

package grimbo.android.demo.slidingmenu;

import android.app.Activity;

import android.graphics.Color;

import android.os.Bundle;

import android.view.LayoutInflater;

import android.view.View;

import android.widget.Button;

public class MainActivity extends Activity {

private MyHorizontalScrollView scrollView;

private View leftMenu;

private View rightMenu;

private View tab01;

private Button leftButton;

private Button rightButton;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

LayoutInflater inflater = LayoutInflater.from(this);

setContentView(inflater.inflate(R.layout.main, null));

scrollView = (MyHorizontalScrollView) findViewById(R.id.myScrollView);

leftMenu = findViewById(R.id.leftmenu);

rightMenu = findViewById(R.id.rightmenu);

tab01 = inflater.inflate(R.layout.tab01, null);

leftButton = (Button) tab01.findViewById(R.id.leftButton);

rightButton = (Button)tab01.findViewById(R.id.rightButton);

leftButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

scrollView.clickLeftButton(leftButton.getMeasuredWidth());

}

});

rightButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

scrollView.clickRightButton(rightButton.getMeasuredWidth());

}

});

View leftView = new View(this);//左边透明视图

View rightView = new View(this);//右边透明视图

leftView.setBackgroundColor(Color.TRANSPARENT);

rightView.setBackgroundColor(Color.TRANSPARENT);

final View[] children = new View[] {leftView, tab01,rightView };

//初始化滚动布局

scrollView.initViews(children, new SizeCallbackForMenu(leftButton),leftMenu,rightMenu);

}

}

其中tab01是一个由布局文件tab01.xml定义的view,放置“左边”和“右边”两个按钮

View leftView = new View(this);//左边透明视图

View rightView = new View(this);//右边透明视图

leftView.setBackgroundColor(Color.TRANSPARENT);

rightView.setBackgroundColor(Color.TRANSPARENT);

四句定义两个透明视图,透明视图就是只占用空间,不遮挡放置在其下面的视图

scrollView.initViews把两个透明视图和一个中间的tab视图放入HorizontalScrollView 的LinearLayout里,LinearLayout是横向布局,这样tab移到屏幕可视范围的时候就遮住了底下的leftmenu和rightmenu,当两侧透明视图移入屏幕可视范围的时候,底下的leftmenu或rightmenu就显现出来了,以此实现侧滑效果

然后看一下自定义的滑动类MyHorizontalScrollView

[java] view
plaincopy

package grimbo.android.demo.slidingmenu;

import android.content.Context;

import android.os.Handler;

import android.util.AttributeSet;

import android.util.Log;

import android.view.GestureDetector;

import android.view.GestureDetector.SimpleOnGestureListener;

import android.view.MotionEvent;

import android.view.VelocityTracker;

import android.view.View;

import android.view.ViewGroup;

import android.view.GestureDetector.OnGestureListener;

import android.view.ViewTreeObserver.OnGlobalLayoutListener;

import android.widget.HorizontalScrollView;

import android.widget.Scroller;

public class MyHorizontalScrollView extends HorizontalScrollView {

private final String tag = "MyHorizontalScrollView";

private MyHorizontalScrollView me;//当前控件

private View leftMenu;//左边菜单

private View rightMenu;//右边菜单

private boolean leftMenuOut = false;//左边菜单状态

private boolean rightMenuOut = false;//左边菜单状态

private final int ENLARGE_WIDTH = 20;//扩展宽度

public MyHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

init(context);

}

public MyHorizontalScrollView(Context context, AttributeSet attrs) {

super(context, attrs);

init(context);

}

public MyHorizontalScrollView(Context context) {

super(context);

init(context);

}

void init(Context context) {

// remove the fading as the HSV looks better without it

//setHorizontalFadingEdgeEnabled(true);

//setVerticalFadingEdgeEnabled(true);

me = this;

me.setVisibility(View.INVISIBLE);

}

public void initViews(View[] children, SizeCallback sizeCallback,View leftMenu,View rightMenu) {

this.leftMenu = leftMenu;

this.rightMenu = rightMenu;

ViewGroup parent = (ViewGroup) getChildAt(0);

// Add all the children, but add them invisible so that the layouts are calculated, but you can't see the Views

for (int i = 0; i < children.length; i++) {

children[i].setVisibility(View.INVISIBLE);

parent.addView(children[i]);

}

// Add a layout listener to this HSV

// This listener is responsible for arranging the child views.

OnGlobalLayoutListener listener = new MyOnGlobalLayoutListener(parent, children, sizeCallback);

getViewTreeObserver().addOnGlobalLayoutListener(listener);

}

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

// Do not allow touch events.

return false;

}

class MyOnGlobalLayoutListener implements OnGlobalLayoutListener {

ViewGroup parent;

View[] children;

int scrollToViewPos = 0;

SizeCallback sizeCallback;

public MyOnGlobalLayoutListener(ViewGroup parent, View[] children, SizeCallback sizeCallback) {

this.parent = parent;

this.children = children;

this.sizeCallback = sizeCallback;

}

@Override

public void onGlobalLayout() {

me.getViewTreeObserver().removeGlobalOnLayoutListener(this);

sizeCallback.onGlobalLayout();

parent.removeViewsInLayout(0, children.length);

final int w = me.getMeasuredWidth();

final int h = me.getMeasuredHeight();

int[] dims = new int[2];

scrollToViewPos = 0;

for (int i = 0; i < children.length; i++) {

sizeCallback.getViewSize(i, w, h, dims);

children[i].setVisibility(View.VISIBLE);

parent.addView(children[i], dims[0], dims[1]);

if (i == 0) {

scrollToViewPos += dims[0];

}

Log.d(tag, children[i]+": w=" + dims[0] + ", h=" + dims[1]);

Log.d(tag, "scrollToViewIdx:"+0+",scrollToViewPos:"+scrollToViewPos);

}

new Handler().post(new Runnable() {

@Override

public void run() {

me.scrollBy(scrollToViewPos,0);

//因为这些控件默认都为隐藏,控件加载完成后,设置成显示

me.setVisibility(View.VISIBLE);

leftMenu.setVisibility(View.VISIBLE);

rightMenu.setVisibility(View.VISIBLE);

}

});

}

}

public void clickLeftButton(int leftButtonWidth){

rightMenu.setVisibility(View.GONE);

leftMenu.setVisibility(View.VISIBLE);

int menuWidth = leftMenu.getMeasuredWidth()-(leftButtonWidth+ENLARGE_WIDTH);

System.out.println("leftmenuWidth:"+menuWidth);

if (!leftMenuOut) {

int left = 0;

me.smoothScrollTo(left, 0);

} else {

int left = menuWidth;

me.smoothScrollTo(left, 0);

}

leftMenuOut = !leftMenuOut;

}

public void clickRightButton(int rightButtonWidth){

<span style="white-space:pre"> </span>leftMenu.setVisibility(View.GONE);

rightMenu.setVisibility(View.VISIBLE);

int menuWidth = rightMenu.getMeasuredWidth() - (rightButtonWidth+ENLARGE_WIDTH);

if (!rightMenuOut) {

int right = menuWidth + me.getMeasuredWidth();

System.out.println("rightmenuWidth:"+right);

me.smoothScrollTo(right, 0);

} else {

int right = menuWidth;

System.out.println("rightmenuWidth:"+right);

me.smoothScrollTo(right, 0);

}

rightMenuOut = !rightMenuOut;

}

@Override

<span style="white-space:pre"> </span>public boolean onTouchEvent(MotionEvent ev) {

return false;

}

public interface SizeCallback {

public void onGlobalLayout();

public void getViewSize(int idx, int w, int h, int[] dims);

}

}

initViews:把传入的view加入第0个viewgroup,也就是xml中配置的LinearLayout中,并把一个MyOnGlobalLayoutListener对象设置为layout变化的观察者,initViews中放入的view只是占了个位置,后面的onGlobalLayout中会重新给这些view分配高和宽并加到LinearLayout中,但是在这之前需要预先放上去以得到某些控件的size(sizeCallback.onGlobalLayout()中),所以需要在这先加一次

onGlobalLayout:作为观察者,会在view的layout发生发生改变时自动调用此方法,由于只需要调用一次,所以方法里第一句就是调用removeGlobalOnLayoutListener,这个方法的主要功能就是把需要加入layout的views按照计算的宽度并加上去,然后调用me.scrollBy(scrollToViewPos,0);使加上去的view偏移,让tab01这个view偏移到屏幕可视范围中

clickLeftButton,clickRightButton:点击左边和右边的按钮时,控制MyHorizontalScrollView自身移动,显示出侧面相应的功能菜单,注意在移动之前,最左侧和最右侧是屏幕外的leftview和rightview,所以:

int left = 0;

me.smoothScrollTo(left, 0);

是把leftview移进来,中间的tab01向右移

完整源码下载地址:

http://download.csdn.net/detail/lamp_zy/4494989
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: