开始动手之前先来讲一下实现原理,在一个Activity的布局中需要有三部分,一个是左侧菜单的布局,一个是右侧菜单的布局,一个是内容布局。左侧菜单居屏幕左边缘对齐,右侧菜单居屏幕右边缘对齐,然后内容布局占满整个屏幕,并压在了左侧菜单和右侧菜单的上面。当用户手指向右滑动时,将右侧菜单隐藏,左侧菜单显示,然后通过偏移内容布局的位置,就可以让左侧菜单展现出来。同样的道理,当用户手指向左滑动时,将左侧菜单隐藏,右侧菜单显示,也是通过偏移内容布局的位置,就可以让右侧菜单展现出来。

1.新建Android项目,然后新建一个DoubleSlideMenu继承自RelativeLayout,核心类代码:
public class DoubleMenu extends RelativeLayout implements OnTouchListener {
    //滚动和隐藏菜单布局时手指所需要的速度
    private static final int SNAP_VELOCITY=200;
    //未进行任何滑动
    private static final int DO_NOTHING=0;
    //左侧滑动菜单的显示
    private static final int SHOW_LEFT_MENU=1;
    //右侧菜单显示
    private static final int SHOW_RIGHT_MENU=2;
    //左侧菜单隐藏
    private static final int HIDE_LEFT_MENU=3;
    //右侧菜单隐藏
    private static final int HIDE_RIGHT_MENU=4;
    
    //记录滑动的状态
    private int slideState;
    //滑动菜单最小的距离
    private int touchSlop;
    //屏幕宽
    private int screenWidth;
    //按下的横坐标
    private float xDown;
    //按下的纵坐标
    private float yDown;
    //移动的横坐标
    private float xMove;
    //移动的纵坐标
    private float yMove;
    //弹起的横坐标
    private float xUp;
    
    //标志左侧菜单是否显示
    private boolean isLeftMenuVisible;
    //标志右侧菜单是否显示
    private boolean isRightMenuVisible;
    //左侧菜单布局
    private View leftMenuLayout;
    //右侧菜单布局
    private View rightMenuLayout;
    //左侧菜单布局参数
    private MarginLayoutParams leftMenuLayoutParams;
    //右侧菜单布局参数
    private MarginLayoutParams rightMenuLayoutParams;
    //内容页面布局
    private View contentLayout;
    //内容页面布局参数
    private RelativeLayout.LayoutParams contentLayoutParams;
    //标志菜单是否正在滑动
    private boolean isSliding;
    //用于监听滑动事件的View
    private View mBindView;
    //手指的速度
    private VelocityTracker mVelocityTracker;
    
    public DoubleMenu(Context context, AttributeSet attrs) {
        super(context, attrs);
        WindowManager wm=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        screenWidth=wm.getDefaultDisplay().getWidth();
        touchSlop=ViewConfiguration.get(context).getScaledTouchSlop();  //触发滚动菜单事件的最小距离
    }
    
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if(changed){
            //获取左侧菜单
            leftMenuLayout=getChildAt(0);
            leftMenuLayoutParams=(MarginLayoutParams) leftMenuLayout.getLayoutParams();
            //获取右侧菜单
            rightMenuLayout=getChildAt(1);
            rightMenuLayoutParams=(MarginLayoutParams) rightMenuLayout.getLayoutParams();
            //获取内容页面
            contentLayout=getChildAt(2);
            contentLayoutParams=(RelativeLayout.LayoutParams) contentLayout.getLayoutParams();
            contentLayoutParams.width=screenWidth;
            contentLayout.setLayoutParams(contentLayoutParams);
        }
    }
    //绑定监听滑动的View
    public void setScrollEvent(View bindView){
        mBindView=bindView;
        mBindView.setOnTouchListener(this);
    }
    
    //判断左侧布局是否显示
    public boolean isLeftMenuVisible(){
        return isLeftMenuVisible;
    }
    //判断右侧布局是否显示
    public boolean isRightMenuVisible(){
        return isRightMenuVisible;
    }
    
    //显示左侧菜单时初始化
    public void initShowLeftState(){
        contentLayoutParams.rightMargin=0;
        contentLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, 0);
        contentLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
        contentLayout.setLayoutParams(contentLayoutParams);
        leftMenuLayout.setVisibility(View.VISIBLE);
        rightMenuLayout.setVisibility(View.GONE);
    }
    //显示右侧菜单时初始化
    public void initShowRightState(){
        contentLayoutParams.leftMargin=0;
        contentLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0);
        contentLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
        contentLayout.setLayoutParams(contentLayoutParams);
        rightMenuLayout.setVisibility(View.VISIBLE);
        leftMenuLayout.setVisibility(View.GONE);
    }
    
    
    //根据手指移动的方向,判断用户滑动意图
    private void checkSlideState(int moveDistanceX,int moveDistanceY){
        if(isLeftMenuVisible){  //如果左侧菜单已经正在显示,判断是否需要关闭
            if(!isSliding&&Math.abs(moveDistanceX)>touchSlop&&moveDistanceX<0){
                isSliding = true;
                slideState=HIDE_LEFT_MENU;
            }
        }
        else if(isRightMenuVisible){
            if(!isSliding&&Math.abs(moveDistanceX)>touchSlop&&moveDistanceX>0){
                isSliding = true;
                slideState=HIDE_RIGHT_MENU;
            }
        }
        else{
            if(!isSliding&&Math.abs(moveDistanceX)>touchSlop&&moveDistanceX>0&&Math.abs(moveDistanceY)<touchSlop){
                isSliding = true;
                slideState=SHOW_LEFT_MENU;
                initShowLeftState();
            }
            else if(!isSliding&&Math.abs(moveDistanceX)>touchSlop&&moveDistanceX<0&&Math.abs(moveDistanceY)<touchSlop){
                isSliding=true;
                slideState=SHOW_RIGHT_MENU;
                initShowRightState();
            }
        }
    }
    
    //在滑动中,检查左侧菜单的边界值
    private void checkLeftMenuBorder(){
        if(contentLayoutParams.rightMargin>0){     
            contentLayoutParams.rightMargin=0;  //隐藏左侧菜单的时刻
        }
        else if(contentLayoutParams.rightMargin<-leftMenuLayoutParams.width){
            contentLayoutParams.rightMargin=-leftMenuLayoutParams.width;  //显示左侧菜单的时刻
        }
    }
    //在滑动过程中检查右侧菜单的边界值
    private void checkRightMenuBorder(){
        if(contentLayoutParams.leftMargin>0){
            contentLayoutParams.leftMargin=0;
        }
        else if(contentLayoutParams.leftMargin<-rightMenuLayoutParams.width){
            contentLayoutParams.leftMargin=-rightMenuLayoutParams.width;
        }
    }
    
    /**
     * 创建VelocityTracker对象,并将触摸事件加入到VelocityTracker当中。
     * 
     * @param event
     *            右侧布局监听控件的滑动事件
     */
    private void createVelocityTracker(MotionEvent event) {
        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(event);
    }
    /**
     * 获取手指在绑定布局上的滑动速度。
     * 
     * @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 boolean shouldScrollToLeftMenu(){
        return xUp-xDown>leftMenuLayoutParams.width/2||getScrollVelocity()>SNAP_VELOCITY;
    }
    //判断是否应将右侧菜单显示
    private boolean shouldScrollToRightMenu(){
        return xDown-xUp>rightMenuLayoutParams.width/2||getScrollVelocity()>SNAP_VELOCITY;
    }
    //判断是否应从左侧转到内容页面
    private boolean shouldScrollToContentFromLeft(){
        return xDown-xUp>leftMenuLayoutParams.width/2||getScrollVelocity()>SNAP_VELOCITY;
    }
    //判断是否应从右侧转到内容页面
    private boolean shouldScrollToContentFromRight(){
        return xUp-xDown>rightMenuLayoutParams.width/2|getScrollVelocity()>SNAP_VELOCITY;
    }
    
    //让获得焦点的控件在滑动过程中失去焦点
    private void unFocusBindView(){
        if(mBindView!=null){
            mBindView.setPressed(false);
            mBindView.setFocusable(false);
            mBindView.setFocusableInTouchMode(false);
        }
    }
    
    class LeftMenuScrollTask extends AsyncTask<Integer, Integer, Integer>{
        @Override
        protected Integer doInBackground(Integer... speed) {
            int rightMargin=contentLayoutParams.rightMargin;
            while(true){
                rightMargin=rightMargin+speed[0];
                if(rightMargin>0){  //隐藏
                    rightMargin=0;
                    break;
                }
                if(rightMargin<-leftMenuLayoutParams.width){
                    rightMargin=-leftMenuLayoutParams.width;
                    break;
                }
                publishProgress(rightMargin);
                sleep(15);
            }
            if(speed[0]>0){
                isLeftMenuVisible=false;
            }
            else{
                isLeftMenuVisible=true;
            }
            isSliding=false;
            return rightMargin;
        }
        @Override
        protected void onProgressUpdate(Integer... values) {
            contentLayoutParams.rightMargin=values[0];
            contentLayout.setLayoutParams(contentLayoutParams);
            unFocusBindView();
        }
        @Override
        protected void onPostExecute(Integer result) {
            contentLayoutParams.rightMargin=result;
            contentLayout.setLayoutParams(contentLayoutParams);
        }
    }
    
    class RightMenuScrollTask extends AsyncTask<Integer, Integer, Integer>{
        @Override
        protected Integer doInBackground(Integer... speed) {
            int leftMargin=contentLayoutParams.leftMargin;
            while(true){
                leftMargin=leftMargin+speed[0];
                if(leftMargin>0){
                    leftMargin=0;
                    break;
                }
                if(leftMargin<-rightMenuLayoutParams.width){
                    leftMargin=-rightMenuLayoutParams.width;
                    break;
                }
                publishProgress(leftMargin);
                sleep(20);
            }
            if(speed[0]>0){
                isRightMenuVisible=false;
            }
            else{
                isRightMenuVisible=true;
            }
            isSliding=false;
            return leftMargin;
        }
        @Override
        protected void onProgressUpdate(Integer... values) {
            contentLayoutParams.leftMargin=values[0];
            contentLayout.setLayoutParams(contentLayoutParams);
            unFocusBindView();
        }
        @Override
        protected void onPostExecute(Integer result) {
            contentLayoutParams.leftMargin=result;
            contentLayout.setLayoutParams(contentLayoutParams);
        }
    }
    private void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    //将界面滚到左侧菜单
    public void scrollToLeftMenu(){
        new LeftMenuScrollTask().execute(-30);
    }
    //将界面滚动到右侧菜单
    public void scrollToRightMenu(){
        new RightMenuScrollTask().execute(-30);
    }
    //将界面从左侧滚到内容
    public void scrollToContentFromLeft(){
        new LeftMenuScrollTask().execute(30);
    }
    //将界面从右侧滚到内容
    public void scrollToContentFromRight(){
        new RightMenuScrollTask().execute(30);
    }
    
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        createVelocityTracker(event);
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            xDown=event.getRawX();
            yDown=event.getRawY();
            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_LEFT_MENU:
                contentLayoutParams.rightMargin=-moveDistanceX;
                checkLeftMenuBorder();
                contentLayout.setLayoutParams(contentLayoutParams);
                break;
            case HIDE_LEFT_MENU:
                contentLayoutParams.rightMargin=-leftMenuLayoutParams.width-moveDistanceX;
                checkLeftMenuBorder();
                contentLayout.setLayoutParams(contentLayoutParams);
                break;
            case SHOW_RIGHT_MENU:
                contentLayoutParams.leftMargin=moveDistanceX;
                checkRightMenuBorder();
                contentLayout.setLayoutParams(contentLayoutParams);
                break;
            case HIDE_RIGHT_MENU:
                contentLayoutParams.leftMargin=-rightMenuLayoutParams.width+moveDistanceX;
                checkRightMenuBorder();
                contentLayout.setLayoutParams(contentLayoutParams);
                break;
              }
            break;
            }
        case MotionEvent.ACTION_UP:
            xUp=event.getRawX();
            int upDistanceX=(int)(xUp-xDown);
            if(isSliding){
                switch (slideState) {
                case SHOW_LEFT_MENU:
                    if(shouldScrollToLeftMenu()){
                        scrollToLeftMenu();
                    }
                    else{
                        scrollToContentFromLeft();
                    }
                    break;
                case HIDE_LEFT_MENU:
                    if(shouldScrollToContentFromLeft()){
                        scrollToContentFromLeft();
                    }
                    else{
                        scrollToLeftMenu();
                    }
                    break;
                case SHOW_RIGHT_MENU:
                    if(shouldScrollToRightMenu()){
                        scrollToRightMenu();
                    }
                    else{
                        scrollToContentFromRight();
                    }
                    break;
                case HIDE_RIGHT_MENU:
                    if(shouldScrollToContentFromRight()){
                        scrollToContentFromRight();
                    }
                    else{
                        scrollToRightMenu();
                    }
                default:
                    break;
                }
            }
            else if(upDistanceX<touchSlop&&isLeftMenuVisible){
                scrollToContentFromLeft();
            }
            else if(upDistanceX<touchSlop&&isRightMenuVisible){
                scrollToContentFromRight();
            }
            recycleVelocityTracker();
            break;
        }
        
        if(v.isClickable()){   //这里要求控件必须是clickable的.
            if(isSliding){
                unFocusBindView();  //正在滑动时取消控件焦点
                return true;
            }
            if(isLeftMenuVisible||isRightMenuVisible){
                return true;//当左菜单或右菜单显示时,取消触摸事件
            }
            return false;
        }
        return true;
    }
}
首先在onLayout()方法中分别获取到左侧菜单、右侧菜单和内容布局的参数,并将内容布局的宽度重定义成屏幕的宽度,这样就可以保证内容布局既能覆盖住下面的菜单布局,还能偏移出屏幕。然后在onTouch()方法中监听触屏事件,以判断用户手势的意图。这里事先定义好了几种滑动状态,DO_NOTHING表示没有进行任何滑动,SHOW_LEFT_MENU表示用户想要滑出左侧菜单,SHOW_RIGHT_MENU表示用户想要滑出右侧菜单,HIDE_LEFT_MENU表示用户想要隐藏左侧菜单,HIDE_RIGHT_MENU表示用户想要隐藏右侧菜单,在checkSlideState()方法中判断出用户到底是想进行哪一种滑动操作,并给slideState变量赋值,然后根据slideState的值决定如何偏移内容布局。接着当用户手指离开屏幕时,会根据当前的滑动距离,决定后续的滚动方向,通过LeftMenuScrollTask和RightMenuScrollTask来完成完整的滑动过程。另外在滑动的过程,内容布局上的事件会被屏蔽掉,主要是通过一系列的return操作实现的.
2.打开activity_main.xml
<com.example.doubleslidemenu.DoubleMenu 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:id="@+id/double_slideMenu"
    tools:context=".MainActivity" >
    <RelativeLayout 
        android:layout_width="270dp"
        android:layout_height="fill_parent"
        android:id="@+id/left_menu"
        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 left menu"
            android:textColor="#000000"
            android:textSize="28sp" />
    </RelativeLayout>
    
        <RelativeLayout
        android:id="@+id/right_menu"
        android:layout_width="270dip"
        android:layout_height="fill_parent"
        android:layout_alignParentRight="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 right menu"
            android:textColor="#000000"
            android:textSize="28sp" />
    </RelativeLayout>
     <LinearLayout
        android:id="@+id/content"
        android:layout_width="320dip"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        android:background="#e9e9e9" >
        <RelativeLayout 
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            >
            <Button 
                android:id="@+id/show_left_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:text="show left"
                />
            <Button 
                android:id="@+id/show_right_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:text="show right"
                />
        </RelativeLayout>
        <ListView
            android:id="@+id/contentList"
            android:layout_width="fill_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:scrollbars="none"
            android:cacheColorHint="#00000000" >
        </ListView>
    </LinearLayout>
</com.example.doubleslidemenu.DoubleMenu>
3.打开MainActivity.java
public class MainActivity extends Activity {
    /**
     * 双向滑动菜单布局
     */
    private DoubleMenu bidirSldingLayout;
    /**
     * 在内容布局上显示的ListView
     */
    private ListView contentList;
    /**
     * 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_main);
        bidirSldingLayout = (DoubleMenu) findViewById(R.id.double_slideMenu);
        Button showLeftButton = (Button) findViewById(R.id.show_left_button);
        Button showRightButton = (Button) findViewById(R.id.show_right_button);
        contentList = (ListView) findViewById(R.id.contentList);
        contentListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,
                contentItems);
        contentList.setAdapter(contentListAdapter);
        bidirSldingLayout.setScrollEvent(contentList);
        showLeftButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (bidirSldingLayout.isLeftMenuVisible()) {
                    bidirSldingLayout.scrollToContentFromLeft();
                } else {
                    bidirSldingLayout.initShowLeftState();
                    bidirSldingLayout.scrollToLeftMenu();
                }
            }
        });
        showRightButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (bidirSldingLayout.isRightMenuVisible()) {
                    bidirSldingLayout.scrollToContentFromRight();
                } else {
                    bidirSldingLayout.initShowRightState();
                    bidirSldingLayout.scrollToRightMenu();
                }
            }
        });
    }
}
至此,可以双向滑动的SlideMenu就完成了.


android之SlideMenu双向滑动的更多相关文章

  1. Android双向滑动菜单完全解析,教你如何一分钟实现双向滑动特效

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9671609 记得在很早之前,我写了一篇关于Android滑动菜单的文章,其中有一个 ...

  2. Android 侧滑(双向滑动菜单)效果

    下面看看我们如何使用它,达到我们想要的效果 public class MainActivity extends Activity { /** * 双向滑动菜单布局 */ private SliderM ...

  3. 【转】Android双向滑动菜单完全解析,教你如何一分钟实现双向滑动特效

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9671609 记得在很早之前,我写了一篇关于Android滑动菜单的文章,其中有一个 ...

  4. 超酷的Android 侧滑(双向滑动菜单)效果

    下面看看我们如何使用它,达到我们想要的效果 public class MainActivity extends Activity { /** * 双向滑动菜单布局 */ private SliderM ...

  5. Android ScrollView监听滑动到顶部和底部的两种方式(你可能不知道的细节)

    Android ScrollView监听滑动到顶部和底部,虽然网上很多资料都有说,但是不全,而且有些细节没说清楚 使用场景: 1. 做一些复杂动画的时候,需要动态判断当前的ScrollView是否滚动 ...

  6. 仿优酷Android客户端图片左右滑动(自动滑动)

    最终效果: 页面布局main.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayou ...

  7. Android判断Touch为滑动事件还是操作控件

    Android判断Touch为滑动事件还是操作控件 因为在项目中要判断WebView是否处于滚动状态,但它不像ListView有onScrollStateChanged方法来监听,要实现就得手动监听它 ...

  8. android中无限循环滑动的gallery实例

    android中无限循环滑动的gallery实例 1.点击图片有变暗的效果,使用imageview.setAlpha(),并且添加ontouchListener public void init() ...

  9. Android开发之手势滑动(滑动手势监听)详解

    Android开发之手势滑动(滑动手势监听)详解 在Android应用中,经常需要手势滑动操作,比如上下滑动,或左右方向滑动,处理手势滑动通常有两种方法:一种是单独实现setOnTouchListen ...

随机推荐

  1. Getting aCC Error :name followed by "::" must be a class or namespace name"

    Getting aCC Error :name followed by "::" must be a class or namespace name" 原始是这样子的: ...

  2. 遗忘的html标签

    <span>x</span><sup>2</sup><span>+y=10</span> <br> <span ...

  3. 变量类型 ROWID 和 UROWID

    ROWID:    ROWID为该表行的唯一标识,是一个伪列,这个伪列可以用SELECT查看,但是不可以用INSERT, UPDATE来修改,不可以用DELETE来删除. UROWID: ROWID可 ...

  4. 理解 Gulp 和 Webpack(转)

    Gulp 和 webpack 之间的关系是十分暧昧的,却也经常被人误解,以为它俩是竞争关系,其实不然. Gulp 是一个任务管理工具,让简单的任务更清晰,让复杂的任务易于掌控:而 webpack 的理 ...

  5. SAP库存历史库存表更新逻辑 (转)

    根据库存类型的不同,库存信息保存在不同的表中,具体而言见下表 库存类型 当前库存 历史库存 库存金额 历史库存金额 工厂级别库存 MARC MARCH MBEW MBEWH MBEW 库存地点库存 M ...

  6. (转)神舟飞船上的计算机使用什么操作系统,为什么是自研发不是 Linux?

    中国航天用的SpaceOS主要内容是仿造美国风河系统公司的VxWorks653(653是产品名,并非版本号).先解释为什么用这个系统不用Linux:航天器的内存和CPU都非常弱,弱到什么程度呢:天宫一 ...

  7. 【PHP】nl2br转化输出input框的换行

    在input或者textarea框中输入的换行符保存到数据库是/n,如果直接输出到前端的话是不会有换行的,所以要用到nl2br转化 nl2br($test);

  8. 一行代码搞定checkbox全选和全不选

    <!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title> ...

  9. vim编辑器使用习惯问题

    Ubuntu中vi在编辑状态下方向键不能用,一按方向键盘就出ABCD,想插入个字母还非常麻烦,还有回格键不能删除等我们平时习惯的一些键都不能使用. 解决办法: 可以安装vim full版本,在full ...

  10. PHP递归操作

    对于php的递归操作解释说明,递归基本上是学习每种语言都要会的最基本的操作.来吧,下面是我闲的时候随便写的一个对数组进行遍历操作的一个递归函数. 原理很简单,递归就是在一个函数里面调用自身的一种机制. ...