安卓侧边栏如何实现类似Facebook或Firefox的效果

17

有了新的Facebook应用程序,它带有一个隐藏的侧边栏,我希望在我的应用程序中使用类似的东西。 它看起来有点像Firefox移动版拥有的侧边栏...

除了重新实现ViewPager外,您有任何实现它的想法吗? 我尝试过使用HorizontalScrollView,但这也会导致其重新实现...

除了这两种方法,我没有看到其他办法... 有什么建议吗?

提前感谢


扩展版Facebook:灰色布局从这里向左扩展:Facebook主视图在Firefox上,我们有这个:Firefox - 左侧是“侧边栏”。 - baen
@alextsc 不错!我找了两天也没找到这个结果!谢谢 =) - baen
4个回答

23
我想出了一个解决方案...我不知道它是否完美,但它运行良好。
所以我做的是一个单一的FrameLayout,将两个布局叠在一起,然后我只是动画地将顶部布局滑动到屏幕的右侧(只需要调用slideTo或scrollBy)。基本上就是这样!非常简单而有效!(尽管代码不太漂亮:P)
编辑:
一些代码示例。
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#FFF" >

        <include
        android:id="@+id/menu_layout"
            layout="@layout/menu_list"
            android:visibility="invisible"/>

        <include
            android:id="@+id/news_list_parent"
            layout="@layout/main_news_list" 
            />

</FrameLayout>

这是布局xml,非常简单。包含的.xml文件是简单的LinearLayouts,具有标题和listview。
"魔力"发生在动画中:
protected void applyTransformation(float interpolatedTime, Transformation t) {
    int newOffset;
    if(expanded) {
        newOffset = 0;
        newOffset = (int)(endOffset*(1-interpolatedTime));
    } else {
        newOffset = (int)(endOffset*(interpolatedTime));
    }
    view.scrollTo(-newOffset, 0);
}

endOffset是目标移动位置。在开始动画之前,我会将其设置好,并且要动画的View(在这种情况下是id为news_list_parent的View)已经在构造函数中设置好了。

但为了更好地理解它的工作原理,请创建一个按钮并添加监听器,然后执行以下操作:

if(viewBeneath.getVisibility() == View.INVISIBLE) {
    viewBeneath.setVisibility(View.Visible);
    viewToSlide.slideTo(-(width-50), 0);
}

最后,覆盖返回按钮以执行与按钮相反的操作。
if(viewBeneath.getVisibility() == View.VISIBLE) {
    viewToSlide.slideTo(0, 0);
    viewBeneath.setVisibility(View.Visible);
}

请将以下伪代码阅读一遍 =) 这是我最初的做法,但那段代码已经丢失了 :P


我已经编辑过了,包括在内了。如果有任何问题,请随时问! - baen
1
@baen,我知道你在做什么。为什么不将其封装成一个库并在Github上分享呢? - Amokrane Chentir
1
@AmokraneChentir 我有计划去做那个,但现在我想尽快结束这个项目,然后我想制作一个自定义的ViewGroup来实现这个...现在我能做到的最好的就是给你一个例子。希望你能理解 ;) - baen
1
@baen,我设法让它工作了,除了相反的操作(按下后退按钮时)。 它确实返回到初始状态(x = 0),但没有动画。 我使用了你的代码。 有什么想法是什么原因引起的吗? - Tofira
有没有办法在scrollBy操作中添加动画?我已经让它工作了,但我希望滚动操作能够平稳地运行,而不是快速滚动。谢谢。 - Thiago
显示剩余7条评论

6

谢谢。正是我所寻找的。 - codezoner

4
我做了以下类似的事情: enter image description here enter image description here 以下是我的代码,类似于Facebook侧边栏:
  1. 我在FrameLayout中重叠了2个视图。底部视图是菜单,顶部视图是内容主体。
  2. 我将内容主体放入一个水平滚动视图中。我还将一个视图放在内容主体的左侧,并将该视图的背景设置为透明。
  3. 然后滚动到内容主体开始。这样侧边栏就被内容主体遮盖了。
  4. 当点击按钮显示菜单时,我滚动水平滚动视图以显示透明占位符。现在菜单会出现,因为它在透明占位符下面。
我没有使用XML来创建界面,而是在以下代码中创建了所有内容。我认为这应该很容易阅读并放入您的Eclipse中。
package com.chaoshen.androidstudy.facebooklikesidemenubar;


import android.os.Bundle;
import android.app.Activity;
import android.graphics.Color;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MainActivity extends Activity{

    private boolean Menu_Displayed=false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Display display = getWindowManager().getDefaultDisplay();
        final int width = display.getWidth();

        // menu:
        LinearLayout li_menu = new LinearLayout(this);
        li_menu.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));  
        li_menu.setOrientation(1);//1 is vertical
        li_menu.setBackgroundColor(Color.GREEN);

        Button btn1 = new Button(this);
        btn1.setText("button 1");
        btn1.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));  

        li_menu.addView(btn1);

        //body:
        final HorizontalScrollView hsv = new HorizontalScrollView(this){
            @Override
            // do not let hsv consume the click itself. Then the view under the hsv will also consume the click
            //so that the menu will be clicked
            //when menu is not showed up, let hsv be the only view to consume the click.
            //so that the menu will not be clicked
            public boolean onTouchEvent(MotionEvent ev) {
                if(Menu_Displayed){
                    return false;
                }
                else{
                    return true;
                }
            }
        };
        hsv.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));  
        hsv.setBackgroundColor(Color.TRANSPARENT);
        hsv.setHorizontalFadingEdgeEnabled(false);
        hsv.setVerticalFadingEdgeEnabled(false);

        final LinearLayout li_body = new LinearLayout(this);
        li_body.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT));  
        li_body.setOrientation(0);//0 is horizantal
        li_body.setBackgroundColor(Color.TRANSPARENT);

        hsv.addView(li_body);

        //body: place holder transparent
        TextView placeholder = new TextView(this);
        placeholder.setTextColor(Color.TRANSPARENT); 
        placeholder.setLayoutParams(new LayoutParams(width-100, LayoutParams.FILL_PARENT));  
        placeholder.setVisibility(View.INVISIBLE);
        li_body.addView(placeholder);

        //body: real content
        LinearLayout li_content = new LinearLayout(this);
        li_content.setLayoutParams(new LayoutParams(width, LayoutParams.FILL_PARENT));  
        li_content.setOrientation(1);//1 is vertical
        li_content.setBackgroundColor(Color.CYAN);

        TextView tv1 = new TextView(this);  
        tv1.setText("txt 1");  
        tv1.setTextSize(40);  
        tv1.setTextColor(Color.BLACK);  

        TextView tv2 = new TextView(this);  
        tv2.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));  
        tv2.setTextSize(50);  
        tv2.setText("txt 2");  
        tv2.setTextColor(Color.WHITE);  

        //use this button to scroll
        Button btn_showMenu = new Button(this);
        btn_showMenu.setText("Menu");
        btn_showMenu.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
        btn_showMenu.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                hsv.post(new Runnable() {

                    @Override
                    public void run() {
                        if(Menu_Displayed){
                            hsv.smoothScrollTo(width-100, 0);
                        }
                        else{
                            hsv.smoothScrollTo(0, 0);
                        }
                        Menu_Displayed = !Menu_Displayed;
                    }
                });
            }
        });

        li_content.addView(tv1);
        li_content.addView(tv2);
        li_content.addView(btn_showMenu);

        li_body.addView(li_content);

        //add menu and body in to frame
        FrameLayout mainFrame = new FrameLayout(this);  
        mainFrame.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));  
        mainFrame.addView(li_menu);  
        mainFrame.addView(hsv);  

        //scroll to the body real content to block the menu
        hsv.post(new Runnable() {

            @Override
            public void run() {
                hsv.scrollBy(width-100, 0);             
            }
        });

        setContentView(mainFrame);         
    }
}

3
我也创建了自己的解决方案,因为许多现成的解决方案似乎在旧版本的Android上无法正常工作,或者缺乏如何使其正常工作的适当说明。
我的解决方案具有以下特点:
- 提供支持,以滑动视图来显示位于其下面的菜单 - 菜单可以是任何自定义视图 - 上面的视图也可以是任何自定义视图 - 支持旧版Android(已测试可在Android 2.2上运行)
该解决方案使用一个称为“SlidingMenuLayout”的自定义布局,您需要向其中添加两个视图。您添加的第一个视图是菜单,第二个是主视图。
将布局添加到现有项目中的最简单方法是重写Activity的“setContentView()”方法:
@Override
public void setContentView(View view) {

    SlidingMenuLayout layout = new SlidingMenuLayout(this);
    layout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
        ViewGroup.LayoutParams.MATCH_PARENT, 0.0F));

    layout.addView(new MenuView(this));

    layout.addView(view);

    super.setContentView(layout);
}

在这个例子中,MenuView是实际显示菜单的视图。您需要自己实现此视图。
最后,您可以添加一个按钮(通常位于主视图的左上角),调用相应的openMenu()closeMenu()对布局进行操作。 SlidingMenuLayout的代码可以在GitHub项目页面上找到:

我尝试过几种飞入式导航,但你们的导航似乎是迄今为止最好的 - 而且它非常容易应用于现有项目中。我很感激! - Bins Ich
感谢您的实现,但您能否也发布一下您如何实现MenuView类的示例?提前致谢。 - Tobias Moe Thorstensen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接