Боковая панель Android, такая как facebook или firefox

В новом приложении Facebook есть скрытая боковая панель, которую я хотел бы использовать в своих приложениях. Это похоже на боковые панели, которые есть в Firefox Mobile...

У вас есть идеи, как это реализовать, кроме повторной реализации ViewPager? Я пробовал с HorizontalScrollView, но это также привело бы к его повторной реализации...

Я не вижу другого пути, кроме этих двух... есть предложения?

заранее спасибо


person baen    schedule 10.12.2011    source источник
comment
Расширенный facebook серый макет расширяется слева от этого: Основной вид на facebook В Firefox у нас есть это: firefox - левая сторона является боковой панелью   -  person baen    schedule 10.12.2011
comment
@alextsc хорошо! Мои 2-х дневные поиски не дали такого результата! спасибо =)   -  person baen    schedule 10.12.2011


Ответы (4)


Я придумал решение... Не знаю, идеально ли оно, но работает хорошо.

Итак, что я сделал, это один 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 с заголовком и списком.

«Магия» происходит в анимации:

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 — это целевое движение. Я устанавливаю его перед запуском анимации, и представление, которое я хочу анимировать (в данном случае это представление с id=news_list_parent), устанавливается в конструкторе.

Но просто чтобы понять, как это работает, создайте кнопку, и ее слушатель сделает что-то вроде этого:

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

person baen    schedule 11.12.2011
comment
Баен, не могли бы вы поделиться с нами своим кодом? Я пытаюсь сделать это сам и пока безуспешно... Спасибо! - person Tofira; 11.12.2011
comment
Я отредактировал его, чтобы включить. Все, что угодно, просто спросите! - person baen; 11.12.2011
comment
@baen Я вижу, что ты делаешь. Почему бы вам не обернуть это в библиотеку и не поделиться на Github? - person Amokrane Chentir; 12.12.2011
comment
@AmokraneChentir У меня есть планы сделать это, но сейчас я хочу завершить этот проект как можно быстрее, затем я хочу создать пользовательскую группу просмотра, которая реализует это ... Прямо сейчас лучшее, что я мог сделать, это дать вам пример. Надеюсь, вы понимаете ;) - person baen; 12.12.2011
comment
Конечно, это достаточно явно ;) - person Amokrane Chentir; 12.12.2011
comment
@baen, мне удалось заставить его работать, за исключением обратного действия (при нажатии кнопки «Назад»). Он возвращается в исходное состояние (x = 0), но без анимации. Я использовал ваш код. Любая идея, что может вызвать это? - person Tofira; 25.12.2011
comment
Есть ли способ добавить анимацию в действие scrollBy? У меня это работает, но я хотел бы, чтобы действие прокрутки выполнялось плавно, а не быстро. Спасибо - person Thiago; 30.12.2011
comment
@tofira ты сбрасываешь анимацию каждый раз, когда что-то с ней делаешь? Это только мое предположение - person baen; 13.01.2012
comment
@HarshaMV, к сожалению, нет... извините. - person baen; 13.01.2012
comment
@ Тиаго, как так? Я не совсем понял ваш вопрос... Можете ли вы повторить его в других терминах? - person baen; 13.01.2012
comment
@bean: Единственным недостатком такой реализации является то, что мне нужно иметь часть FrameLayout и часть макета меню в каждом файле макета. Я прав или я что-то упускаю? - person Anand Sainath; 28.01.2012
comment
@AnandS да ... это большой недостаток, у меня еще не было времени реализовать это в одном представлении (что возможно) ... Если кто-то разработает такое представление, поделитесь: D - person baen; 21.02.2012

Вы можете попробовать это. Хороший пример. Проверьте класс слайдера.

https://github.com/gitgrimbo/android-sliding-menu-demo

person user1701593    schedule 04.10.2012
comment
Спасибо. Именно то, что я ищу - person bynu022; 10.05.2014

Я сделал что-то вроде следующего: введите здесь описание изображения

введите здесь описание изображения

Ниже приведен мой код для чего-то вроде боковой панели меню facebook.

  1. Я помещаю 2 представления, перекрывающиеся в макете кадра. Вид снизу — это меню, вид сверху — это тело контента.
  2. И я поместил тело контента в горизонтальную прокрутку. Я также поместил представление слева от тела содержимого в режиме горизонтальной прокрутки. И установите фон представления прозрачным.
  3. Затем прокрутите до содержимого в начале. Таким образом, боковая панель меню заблокирована телом контента.
  4. Когда я нажимаю кнопку, чтобы отобразить меню, я прокручиваю горизонтальную прокрутку, чтобы показать прозрачный заполнитель. Затем появится меню, так как оно теперь находится под прозрачным заполнителем.

Я не использовал XML для интерфейса. Я создаю все в приведенном ниже коде. Я думаю, что это должно быть легко читать и помещать в ваше затмение.

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);         
    }
}
person Chao    schedule 24.08.2012

Я также создал свое собственное решение для этого, так как многие стандартные решения не работали на более старых версиях Android или не имели надлежащих инструкций о том, как заставить их работать.

Мое решение имеет следующие особенности:

  • Обеспечивает поддержку скольжения представления, чтобы открыть меню, которое находится под ним.
  • Меню может быть любым пользовательским View
  • Представление выше также может быть любым пользовательским представлением.
  • Поддерживается в старых версиях Android (проверено на работу как минимум на Android 2.2)

В решении используется настраиваемый макет с именем SlidingMenuLayout, в который вы должны добавить 2 представления. Первый вид, который вы добавляете, — это меню, второй — основной вид.

Самый простой способ добавить макет в существующий проект — переопределить метод setContentView() вашей Activity:

@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:

person arendjr    schedule 27.09.2012
comment
я пробовал несколько летать в навигации. но ваша навигация кажется лучшей на данный момент - и ее действительно легко внедрить в существующие проекты. Я ценю это! - person Bins Ich; 03.11.2012
comment
Спасибо за реализацию, но не могли бы вы опубликовать пример того, как вы реализовали класс MenuView? Заранее спасибо. - person Tobias Moe Thorstensen; 03.12.2012