Google은이를 어떻게 처리 했습니까? Android 애플리케이션의 Slide ActionBar


118

나는 정말로 내 앱에서 이것을 구현하고 싶습니다 (측면 탐색), Google이 어떻게 이것을 처리했는지 아는 사람이 있습니까?

그들은 현재 창을 옆으로 떼어 내고 자신의 플라이 인 내비게이션을 넣은 것 같습니다.


2 개의 레이아웃이 포함 된 레이아웃이 있다고 생각합니다. 하나는 메인 앱이고 다른 하나는 사이드 바입니다. 사이드 바가 활성화되면 메인 앱 레이아웃을 옆으로 밀어냅니다. 하지만 이것은 추측 일 뿐이므로 대답으로 넣지 않았습니다.
— Eric

1
누군가가 IO에서 "Android의 새로운 기능"강연 후 Q & A에서이 질문을 한 것 같습니다. 녹음 된 버전은 아직 사용할 수 없으며 유감스럽게도 대답이 무엇인지 기억이 나지 않습니다.
— Bryan Herbst

3
@ Tanis.7x 대답은 그들이 아직이 메뉴에 대한 프레임 워크 구성 요소를 계획하지 않았다는 것이 었습니다.하지만 여기 에서 좋은 블로그 게시물 시리즈를 찾을 수 있습니다 (내가 기억하는 한) .

1
그 블로그 게시물을 읽었습니다. 그들은 사용자 지정 작업 표시 줄을 구현했다고 말합니다. 이제 이것은 개발자에게는 합리적으로 들리지만 자체 API를 해킹하는 Google에서는 그렇지 않습니다!
— Matroska

2
이 질문에 대한 답은 이제 "정확한"구식입니다. Google은 이제 탐색 창을 도입했으며 접근 방식은 현재 나열된 것과 다릅니다.
— Chase Florell 2013

답변:


150

실제로이를 수행하는 방법이 있습니다. 자신의 ActionBar.

그냥 봐 hierachyviewer! (tools 디렉토리에 있음)

어린 시절 에는 DecorView, 및 a LinearLayout가 있습니다. 여기 LinearLayout에는 ActionBar및 기타 콘텐츠 가 모두 포함 됩니다. 그래서, 당신은 FrameLayout.LayoutParams이것에 약간 을 적용하고 LinearLayout이런 식으로 왼쪽에 약간의 공간을 얻을 수 있습니다. 그런 다음이 공간을 menu-ListView로 채우고 다른 콘텐츠를 FrameLayout으로 오버레이 할 수 있습니다.이 경우 클릭하면 메뉴가 축소됩니다. 그래서 다음은 몇 가지 코드입니다.

첫째, 축소 / 확장 클래스 (SlideMenu.java) :

package your.cool.app;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.animation.TranslateAnimation;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

public class SlideMenu {
//just a simple adapter
public static class SlideMenuAdapter extends ArrayAdapter<SlideMenu.SlideMenuAdapter.MenuDesc> {
    Activity act;
    SlideMenu.SlideMenuAdapter.MenuDesc[] items;
    class MenuItem {
        public TextView label;
        public ImageView icon;
    }
    static class MenuDesc {
        public int icon;
        public String label;
    }
    public SlideMenuAdapter(Activity act, SlideMenu.SlideMenuAdapter.MenuDesc[] items) {
        super(act, R.id.menu_label, items);
        this.act = act;
        this.items = items;
        }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View rowView = convertView;
        if (rowView == null) {
            LayoutInflater inflater = act.getLayoutInflater();
            rowView = inflater.inflate(R.layout.menu_listitem, null);
            MenuItem viewHolder = new MenuItem();
            viewHolder.label = (TextView) rowView.findViewById(R.id.menu_label);
            viewHolder.icon = (ImageView) rowView.findViewById(R.id.menu_icon);
            rowView.setTag(viewHolder);
        }

        MenuItem holder = (MenuItem) rowView.getTag();
        String s = items[position].label;
        holder.label.setText(s);
        holder.icon.setImageResource(items[position].icon);

        return rowView;
    }
}

private static boolean menuShown = false;
private static View menu;
private static LinearLayout content;
private static FrameLayout parent;
private static int menuSize;
private static int statusHeight = 0;
private Activity act;
SlideMenu(Activity act) {
    this.act = act;
}
//call this in your onCreate() for screen rotation
public void checkEnabled() {
    if(menuShown)
        this.show(false);
}
public void show() {
//get the height of the status bar
    if(statusHeight == 0) {
        Rect rectgle = new Rect();
        Window window = act.getWindow();
        window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
        statusHeight = rectgle.top;
        }
    this.show(true);
}
public void show(boolean animate) {
    menuSize = Functions.dpToPx(250, act);
    content = ((LinearLayout) act.findViewById(android.R.id.content).getParent());
    FrameLayout.LayoutParams parm = (FrameLayout.LayoutParams) content.getLayoutParams();
    parm.setMargins(menuSize, 0, -menuSize, 0);
    content.setLayoutParams(parm);
//animation for smooth slide-out
    TranslateAnimation ta = new TranslateAnimation(-menuSize, 0, 0, 0);
    ta.setDuration(500);
    if(animate)
        content.startAnimation(ta);
    parent = (FrameLayout) content.getParent();
    LayoutInflater inflater = (LayoutInflater) act.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    menu = inflater.inflate(R.layout.menu, null);
    FrameLayout.LayoutParams lays = new FrameLayout.LayoutParams(-1, -1, 3);
    lays.setMargins(0,statusHeight, 0, 0);
    menu.setLayoutParams(lays);
    parent.addView(menu);
    ListView list = (ListView) act.findViewById(R.id.menu_listview);
    list.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            //handle your menu-click
        }
    });
    if(animate)
        menu.startAnimation(ta);
    menu.findViewById(R.id.overlay).setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            SlideMenu.this.hide();
        }
    });
    Functions.enableDisableViewGroup((LinearLayout) parent.findViewById(android.R.id.content).getParent(), false);
    ((ExtendedViewPager) act.findViewById(R.id.viewpager)).setPagingEnabled(false);
    ((ExtendedPagerTabStrip) act.findViewById(R.id.viewpager_tabs)).setNavEnabled(false);
    menuShown = true;
    this.fill();
}
public void fill() {
    ListView list = (ListView) act.findViewById(R.id.menu_listview);
    SlideMenuAdapter.MenuDesc[] items = new SlideMenuAdapter.MenuDesc[5];
    //fill the menu-items here
    SlideMenuAdapter adap = new SlideMenuAdapter(act, items);
    list.setAdapter(adap);
}
public void hide() {
    TranslateAnimation ta = new TranslateAnimation(0, -menuSize, 0, 0);
    ta.setDuration(500);
    menu.startAnimation(ta);
    parent.removeView(menu);

    TranslateAnimation tra = new TranslateAnimation(menuSize, 0, 0, 0);
    tra.setDuration(500);
    content.startAnimation(tra);
    FrameLayout.LayoutParams parm = (FrameLayout.LayoutParams) content.getLayoutParams();
    parm.setMargins(0, 0, 0, 0);
    content.setLayoutParams(parm);
    Functions.enableDisableViewGroup((LinearLayout) parent.findViewById(android.R.id.content).getParent(), true);
    ((ExtendedViewPager) act.findViewById(R.id.viewpager)).setPagingEnabled(true);
    ((ExtendedPagerTabStrip) act.findViewById(R.id.viewpager_tabs)).setNavEnabled(true);
    menuShown = false;
}
}

몇 가지 도움이되는 방법 (나에게 정적 Functions.java) :

    public static int dpToPx(int dp, Context ctx) {
    Resources r = ctx.getResources();
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics());
}
//originally: http://stackoverflow.com/questions/5418510/disable-the-touch-events-for-all-the-views
//modified for the needs here
public static void enableDisableViewGroup(ViewGroup viewGroup, boolean enabled) {
    int childCount = viewGroup.getChildCount();
    for (int i = 0; i < childCount; i++) {
        View view = viewGroup.getChildAt(i);
        if(view.isFocusable())
            view.setEnabled(enabled);
        if (view instanceof ViewGroup) {
            enableDisableViewGroup((ViewGroup) view, enabled);
            } else if (view instanceof ListView) {
                if(view.isFocusable())
                    view.setEnabled(enabled);
                ListView listView = (ListView) view;
                int listChildCount = listView.getChildCount();
                for (int j = 0; j < listChildCount; j++) {
                    if(view.isFocusable())
                        listView.getChildAt(j).setEnabled(false);
                    }
                }
        }
    }

그런 다음 레이아웃 :

메뉴 레이아웃 (res / layout / menu.xml)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent" >
    <LinearLayout
        android:orientation="vertical"
        android:layout_height="fill_parent"
        android:layout_width="250dip"
        android:background="@color/darkblack">
        <ListView
            android:id="@+id/menu_listview"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:divider="@color/dividerblack"
            android:dividerHeight="2dip"  />
    </LinearLayout>
    <FrameLayout
        android:id="@+id/overlay"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </FrameLayout>
</LinearLayout>

목록 항목의 레이아웃 (res / layout / menu_listitem.xml) :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="fill_parent" >
    <ImageView
        android:id="@+id/menu_icon"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_marginRight="5dip"
        android:layout_marginLeft="10dip"
        android:layout_marginTop="10dip"
        android:layout_marginBottom="10dip" />

    <TextView
        android:id="@+id/menu_label"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="@color/white"
        android:textSize="24dp"
        android:layout_marginTop="10dip"
        android:layout_marginBottom="10dip" />
</LinearLayout>

사용 방법:

귀하의 onCreate():

private SlideMenu slidemenu;
@Override
public void onCreate(Bundle savedInstanceState) {
    //your onCreate code
    slidemenu = new SlideMenu(this);
    slidemenu.checkEnabled();
}

ActionBar 홈 버튼의 핸들러에서 :

slidemenu.show();

그게 다야!

그리고 이제 작동중인 작은 스크린 샷 :

SlideMenu

내가 아는 한 작동하고 있습니다. 문제가 있거나 설명이 명확하지 않은 경우 저에게 연락하십시오!

편집 : ExtendedViewPager& ExtendedPagerStrip:

ExtendedViewPager :

package your.cool.app;

//source: http://blog.svpino.com/2011/08/disabling-pagingswiping-on-android.html

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;

public class ExtendedViewPager extends ViewPager {

private boolean enabled;

public ExtendedViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.enabled = true;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (this.enabled) {
        return super.onTouchEvent(event);
    }

    return false;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    if (this.enabled) {
        return super.onInterceptTouchEvent(event);
    }

    return false;
}

public void setPagingEnabled(boolean enabled) {
    this.enabled = enabled;
}
}

ExtendedPagerTabStrip :

package your.cool.app;

//source: http://blog.svpino.com/2011/08/disabling-pagingswiping-on-android.html

import android.content.Context;
import android.support.v4.view.PagerTabStrip;
import android.util.AttributeSet;
import android.view.MotionEvent;

public class ExtendedPagerTabStrip extends PagerTabStrip {

private boolean enabled;

public ExtendedPagerTabStrip(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.enabled = true;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (this.enabled) {
        return super.onTouchEvent(event);
    }

    return false;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    if (this.enabled) {
        return super.onInterceptTouchEvent(event);
    }

    return false;
}

public void setNavEnabled(boolean enabled) {
    this.enabled = enabled;
}
}

내가 이것을 사용 SlideMenu하여 액티비티에 대한 ViewPager과 PagerTabStrip두 클래스 위에서 바로 중지를 확장 할 수 있도록 토크, 시장 등과 같은 탭 당신은, 쉬운 방법으로 이러한 뷰를 사용하지 않도록 설정할 수없는 onTouch경우 비활성화 이벤트.


1
멋져 보이지만 ExtendedViewPager 및 ExtendedPagerTabStrip은 어디에서 왔습니까?
— bk138

1
쿨, 추가 파일 덕분에 나는 그것을 lib로 변환하고 github에 게시하려고 노력할 것입니다.
— bk138

나는 당신의 활동을 위해 extendedViewPager와 extendedPagerTabStrip을 XML에 넣어야한다고 생각합니다. 위의 예는 R.id.viewpager를 찾습니다
— Patrick

2
안녕, 우리는 sciroccos의 원래 구현을 모아 보았고 XML 구문 분석과 가능한 액션 바의 자동 감지를 추가했습니다. 모든 것은 이제 예제 앱과 함께 라이브러리 프로젝트이며 coboltforge.com/2012/07/…에 설명되어 있습니다 . 초기 아이디어에 대해 @Scirocco에게 감사드립니다!
— bk138

1
나는 방법을 구현했고 그것은 안드로이드 4.1에서 작동하지만 안드로이드 2.3에서는 그렇지 않습니까? 더 높은 버전의 Android를 위해 빌드됩니까?
— Iulia Barbu 2012-08-28

21

이 작업을 수행 하려는 시도 가 여러 번 있지만 모든 API 수준에서 액션 바를 사용하여 성공적으로 구현하는 방법에 대한 lib 또는 소스 코드를 아직 찾지 못했습니다. 하나의 유망한 lib가 여기에 있습니다.

https://github.com/jfeinstein10/SlidingMenu

다음은 예제 앱 의 비디오입니다 .

다음은 Google Play 앱 링크입니다.

이것은 ActionbarSherlock에서 작동합니다. 작동하려면 ABS로 SlidingMenu 라이브러리를 빌드해야합니다. 작동하고 멋지게 보입니다!


2
위의 코드는 일반적으로 작동하지만이 라이브러리가이 문제에 대한 훌륭한 드롭 인 솔루션이라고 말할 수 있습니다. 측면 탐색을 구현하기위한 기성 솔루션으로 제게 성장하기 시작했습니다.
— hwrdprkns 2012 년

이 라이브러리가 우리에게 정말 도움이되었다고 동의합니다. 사용하기 매우 쉽고, 많은 구성 옵션을 제공하고, 다양한 API 레벨에서 작동하고, ActionBarSherlock과 잘 어울립니다!
— greg7gkb 2013

8

원래 구현을 정리 하고 XML 구문 분석을 추가 autodetection했으며 가능한 존재 actionbar를 추가 했으므로 .NET과 같은 기본 및 지원 작업 표시 줄과 함께 작동합니다 ActionBarSherlock.

모든 것은 이제 예제 앱과 함께 라이브러리 프로젝트 이며 Android 용 Sliding Menu에 설명 되어 있습니다. 초기 아이디어와 코드에 대해 scirocco 에게 감사드립니다 !

LibSlideMenu 스크린 샷


슬라이드 메뉴를 첫 번째 화면으로 설정해야합니다. 즉, 사용자가 앱에 들어가면 먼저 슬라이드 메뉴가 표시됩니다. 이에 대한 해결책이 있습니까?
— Sujiz

1
setAsShown ()로 추가 github.com/bk138/LibSlideMenu/commit/... 트릭을해야한다.
— bk138

좋은 작업! 하위 메뉴 항목을 추가하고 싶습니다 (예 : Facebook 앱 확인). 따라서 하위 항목이있는 메뉴 항목을 선택할 때 메뉴가 오른쪽으로 애니메이션되어야합니다. 이를 구현하기위한 팁이 있습니까?
— Luciano

@Luizje : SlideMenu와 같은 유사한보기를 사용해야 할 것 같지만 더 작고 그것에 애니메이션을 사용해야합니다. 나는 당신이 가지고 있을지도 모르는 어떤 패치든지 병합하게되어 기쁩니다 :-)
— bk138

7

11 이상의 API 레벨을 사용하는 경우 @Scirocco 의 답변에서 영감을 얻은 훨씬 더 간단한 접근 방식을 사용할 수 있습니다.

// get content parent that is basically the whole 
// app screen (viewed from hierarchy viewer)
final LinearLayout content = 
     (LinearLayout) findViewById(android.R.id.content).getParent();

// make new value animator with range from 0 to 1
final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
// set custom duration
animator.setDuration(500);
// on update is called for every value in the 
    // given range in time frame defined by the duration
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

    public void onAnimationUpdate(ValueAnimator animation) {
        // get the current value
        float value = ((Float) (animation.getAnimatedValue())).floatValue();
        // translate by that value, minus means translate left
        content.setTranslationX(-250 * value);
    }
});
// start the animator
animator.start();

// make or inflate custom view for test purposes 
Button textView = new Button(this);
textView.setText("TestButton");
// add it to the frame layout that is the parent of the content on position 0
FrameLayout parent = (FrameLayout) content.getParent();
parent.addView(textView, 0);

여기서 아이디어 ValueAnimator는 액션 바를 사용하여 메인 레이아웃에 애니메이션을 적용하는 것이 아니라 변형 을 사용 하는 것이므로 슬라이딩 패널로 사용하려는 팽창 된 뷰와 상호 작용할 수 있습니다. 하드 코딩 된 값을 앱에 사용되는 값으로 바꿔야합니다.

이게 도움이 되길 바란다 :)


6

현재 프로젝트에서 작업 중이며 Sliding 메뉴를 발견했습니다. 검색했지만 아무도 슬라이딩 메뉴를 만드는 방법에 대한 코드 또는 힌트를 제공하지 않았다는 사실에 매우 실망했지만 모든 사람이 일부 링크를 제공했습니다. github의 프로젝트 / 라이브러리를 사용하기로 결정했고, 마침내 나만의 슬라이딩 메뉴를 준비했습니다 ...

나는 그것에 이틀을 보냈다

1. 슬라이딩 애니메이션 제작

2. 모든 화면 해상도에서 작동하도록 만들기

애니메이션 에 대한 아이디어를 얻으면 정말 쉽고 간단 합니다. 휠 (슬라이딩 메뉴의 github 소스 코드를 참조하는 사람들) 을 다시 발명하는 것이 합리적이지 않은 곳을 읽었 지만 적어도 한 번은해야합니다. 자신의 것을 만들어서 실제로 어떻게 작동하고 작동하는지 아이디어를 얻으십시오.

이 사진은 내 슬라이딩 메뉴가 어떻게 작동하는지 보여줍니다.

1. Find.xml //later in the code it will be refer as findLayout

<?xml version="1.0" encoding="utf-8"?>


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <RelativeLayout
        android:id="@+id/find_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <RelativeLayout
        android:id="@+id/header" 
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:padding="2dp"
        android:background="@drawable/main_header">

        <Button 
            android:id="@+id/filter"
            android:layout_width="40dp"
            android:layout_height="30dp"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:background="@drawable/filter_button" />

        <TextView 
            android:id="@+id/city"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@+id/filter"
            android:layout_marginLeft="20dp"
            android:layout_marginTop="3dp"
            android:text="Islamabad"
            android:textSize="22sp"
            android:textStyle="bold"
            android:textColor="@android:color/primary_text_dark"/>

        <RelativeLayout 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/city"
            android:layout_alignLeft="@+id/city">

            <TextView 
                android:id="@+id/interested_in"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:text="Men and Women"
                android:textSize="12sp"
                android:textColor="@android:color/primary_text_dark"/>

            <ImageView 
                android:id="@+id/separator"
                android:layout_width="2dp"
                android:layout_height="18dp"
                android:layout_toRightOf="@+id/interested_in"
                android:layout_marginLeft="4dp"
                android:src="@drawable/separator_1"
                android:layout_centerVertical="true" />

            <TextView 
                android:id="@+id/age"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="4dp"
                android:layout_toRightOf="@+id/separator"
                android:layout_centerVertical="true"
                android:text="18-24 years"
                android:textSize="12sp"
                android:textColor="@android:color/primary_text_dark"/>

            <ImageView
                android:id="@+id/separator_1" 
                android:layout_width="2dp"
                android:layout_height="18dp"
                android:layout_toRightOf="@+id/age"
                android:layout_marginLeft="4dp"
                android:src="@drawable/separator_1"
                android:layout_centerVertical="true" />

            <TextView 
                android:id="@+id/distance"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="4dp"
                android:layout_toRightOf="@+id/separator_1"
                android:layout_centerVertical="true"
                android:text=">30km"
                android:textSize="12sp"
                android:textColor="@android:color/primary_text_dark" />


        </RelativeLayout>

    </RelativeLayout>

    <GridView 
        android:id="@+id/users_grid"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/header"
        android:numColumns="4">

    </GridView>

    </RelativeLayout>

    <include 
        layout="@layout/filter"/> //here i included the filter.xml, which is on top of find.xml layout and is initially invisible    
</RelativeLayout>

여기에 이미지 설명 입력

2. Filter.xml //later in code refer as FilterLayout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/filter_layout"
    android:visibility="invisible"
    android:layout_width="260dp"
    android:layout_height="match_parent"
    android:background="@drawable/grey_bg" >

    <ImageView 
        android:id="@+id/profile_pic"
        android:layout_width="match_parent"
        android:layout_height="220dp"
        android:src="@drawable/pic"/>

    <RelativeLayout
        android:id="@+id/header" 
        android:layout_width="match_parent"
        android:layout_height="55dp"
        android:paddingLeft="10dp"
        android:paddingTop="5dp"
        android:layout_below="@+id/profile_pic"
        android:background="@drawable/light_blue_header">

        <TextView
            android:id="@+id/name" 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="3dp"
            android:text="Raja Babar"
            android:textSize="18sp"
            android:textStyle="bold"
            android:textColor="@android:color/primary_text_dark"/>

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/name"
            android:layout_alignLeft="@+id/name">

            <TextView
                android:id="@+id/gender"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:text="Male"
                android:textSize="12sp"
                android:textColor="@android:color/primary_text_dark" />

            <ImageView 
                android:id="@+id/seperator"
                android:layout_width="2dp"
                android:layout_height="20dp"
                android:layout_toRightOf="@+id/gender"
                android:layout_marginLeft="5dp"
                android:src="@drawable/separator_1"
                android:layout_centerVertical="true" />

            <TextView
                android:id="@+id/age"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toRightOf="@+id/seperator"
                android:layout_marginLeft="5dp"
                android:layout_centerVertical="true"
                android:text="22 years"
                android:textSize="12sp"
                android:textColor="@android:color/primary_text_dark" />

        </RelativeLayout>


    </RelativeLayout>

    <ScrollView 
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:layout_below="@+id/header"
        android:layout_marginTop="15dp"
        android:layout_centerHorizontal="true">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    <TextView
            android:id="@+id/filter_options" 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/filter_options"
            android:textSize="18sp"
            android:textStyle="bold"
            android:textColor="@android:color/primary_text_light"/>

    <RelativeLayout
        android:id="@+id/interested_in_layout" 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="15dp"
        android:paddingRight="40dp"
        android:layout_below="@+id/filter_options"
        android:background="@drawable/interested_in_field">

        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:text="@string/gender"
            android:textSize="18sp"
            android:textStyle="bold"
            android:textColor="@android:color/primary_text_light"/>

        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:text="@string/women_men"
            android:textSize="18sp"
            android:textColor="#33b9cd" />


    </RelativeLayout>
    <RelativeLayout
        android:id="@+id/age_layout" 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="15dp"
        android:paddingRight="40dp"
        android:layout_below="@+id/interested_in_layout"
        android:background="@drawable/age_field_1">

        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:text="@string/age"
            android:textSize="18sp"
            android:textStyle="bold"
            android:textColor="@android:color/primary_text_light"/>

        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:text="18-24 years"
            android:textSize="18sp"
            android:textColor="#33b9cd"/>


    </RelativeLayout>
    <RelativeLayout 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="15dp"
        android:paddingRight="40dp"
        android:layout_below="@+id/age_layout"
        android:background="@drawable/distance_field">

        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:text="@string/distance"
            android:textSize="18sp"
            android:textStyle="bold"
            android:textColor="@android:color/primary_text_light"/>

        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:text=">30km"
            android:textSize="18sp"
            android:textColor="#33b9cd"/>


    </RelativeLayout>



    </RelativeLayout>

    </ScrollView>



</RelativeLayout>

여기에 이미지 설명 입력

에서 find.xml 내가 포함했다 filter.xml 보이지 않는 처음을

이제 FilterAnimation.java

package matchat.helpers;

import com.s3.matchat.R;

import android.content.Context;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.RelativeLayout;

public class FilterAnimation implements AnimationListener 
{
    Context context;

    RelativeLayout filterLayout, otherLayout;

    private Animation filterSlideIn, filterSlideOut, otherSlideIn, otherSlideOut;

    private static int otherLayoutWidth, otherLayoutHeight;

    private boolean isOtherSlideOut = false;

    private int deviceWidth;

    private int margin;

    public FilterAnimation(Context context) 
    {
        this.context = context;

        DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();

        deviceWidth = displayMetrics.widthPixels; // as my animation is x-axis related so i gets the device width and will use that width,so that this sliding menu will work fine in all screen resolutions
    }

    public void initializeFilterAnimations(RelativeLayout filterLayout)
    {
        this.filterLayout = filterLayout;

        filterSlideIn = AnimationUtils.loadAnimation(context, R.anim.filter_slide_in);

        filterSlideOut = AnimationUtils.loadAnimation(context, R.anim.filter_slide_out);    

    }

    public void initializeOtherAnimations(RelativeLayout otherLayout)
    {       
        this.otherLayout = otherLayout;

        otherLayoutWidth = otherLayout.getWidth();

        otherLayoutHeight = otherLayout.getHeight();


        otherSlideIn = AnimationUtils.loadAnimation(context, R.anim.other_slide_in);
        otherSlideIn.setAnimationListener(this);

        otherSlideOut = AnimationUtils.loadAnimation(context, R.anim.other_slide_out);
        otherSlideOut.setAnimationListener(this);
    }

    public void toggleSliding()
    {
        if(isOtherSlideOut) //check if findLayout is already slided out so get so animate it back to initial position
        {       
            filterLayout.startAnimation(filterSlideOut);

            filterLayout.setVisibility(View.INVISIBLE);

            otherLayout.startAnimation(otherSlideIn);
        }
        else //slide findLayout Out and filterLayout In
        {
            otherLayout.startAnimation(otherSlideOut);

            filterLayout.setVisibility(View.VISIBLE);

            filterLayout.startAnimation(filterSlideIn);
        }
    }

    @Override
    public void onAnimationEnd(Animation animation) 
    {
        if(isOtherSlideOut) //Now here we will actually move our view to the new position,because animations just move the pixels not the view
        {
            RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(otherLayoutWidth, otherLayoutHeight);

            otherLayout.setLayoutParams(params);

            isOtherSlideOut = false;
        }
        else
        {   
            margin = (deviceWidth * 80) / 100; //here im coverting device percentage width into pixels, in my other_slide_in.xml or other_slide_out.xml you can see that i have set the android:toXDelta="80%",so it means the layout will move to 80% of the device screen,to work across all screens i have converted percentage width into pixels and then used it



            RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(otherLayoutWidth, otherLayoutHeight);

            params.leftMargin = margin;

            params.rightMargin = -margin; //same margin from right side (negavite) so that our layout won't get shrink

            otherLayout.setLayoutParams(params);

            isOtherSlideOut = true;

            dimOtherLayout();
        }
    }

    @Override
    public void onAnimationRepeat(Animation animation) 
    {

    }

    @Override
    public void onAnimationStart(Animation animation) 
    {

    }

    private void dimOtherLayout()
    {
        AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.5f);

        alphaAnimation.setFillAfter(true);

        otherLayout.startAnimation(alphaAnimation);
    }

}

이제 Find.java

package main.matchat.activities;

import matchat.helpers.FilterAnimation;
import com.s3.matchat.R;
import android.app.Activity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.View.OnClickListener;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.Button;
import android.widget.RelativeLayout;

public class Find extends Activity implements OnClickListener
{
    RelativeLayout filterLayout, findLayout;

    Button btFilter;

    FilterAnimation filterAnimation;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {       
        super.onCreate(savedInstanceState);
        setContentView(R.layout.find);

        filterLayout = (RelativeLayout)findViewById(R.id.filter_layout);

        findLayout = (RelativeLayout)findViewById(R.id.find_layout);

        btFilter = (Button)findViewById(R.id.filter);
        btFilter.setOnClickListener(this);

        filterAnimation = new FilterAnimation(this);

        initializeAnimations(); 
    }

    private void initializeAnimations()
    {   //Setting GlobolLayoutListener,when layout is completely set this function will get called and we can have our layout onbject with correct width & height,else if you simply try to get width/height of your layout in onCreate it will return 0

        final ViewTreeObserver filterObserver = filterLayout.getViewTreeObserver();

        filterObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() 
        {

            @Override
            public void onGlobalLayout() 
            {
                filterLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);

                DisplayMetrics displayMetrics = getResources().getDisplayMetrics();

                int deviceWidth = displayMetrics.widthPixels;

                int filterLayoutWidth = (deviceWidth * 80) / 100; //here im coverting device percentage width into pixels, in my other_slide_in.xml or other_slide_out.xml you can see that i have set the android:toXDelta="80%",so it means the layout will move to 80% of the device screen,to work across all screens i have converted percentage width into pixels and then used it

                RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(filterLayoutWidth, RelativeLayout.LayoutParams.MATCH_PARENT);

                filterLayout.setLayoutParams(params);//here im setting the layout params for my filter.xml because its has width 260 dp,so work it across all screen i first make layout adjustments so that it work across all screens resolution 

                filterAnimation.initializeFilterAnimations(filterLayout);

            }
        });

        final ViewTreeObserver findObserver = findLayout.getViewTreeObserver();

        findObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() 
        {

            @Override
            public void onGlobalLayout() 
            {
                findLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);

                filterAnimation.initializeOtherAnimations(findLayout);
            }
        });

    }

    @Override
    public void onClick(View v) 
    {
        int id = v.getId();

        switch(id)
        {

        case R.id.filter:

            filterAnimation.toggleSliding();

            break;
        }
    } 

}

애니메이션 res / anim은 다음과 같습니다.

1.filter_slide_in.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:interpolator="@android:anim/decelerate_interpolator">

    <translate 
        android:fromXDelta="-100%"
        android:toXDelta="0%"
        android:duration="1000"
        android:fillEnabled="true" />

</set>

2.filter_slide_out.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:interpolator="@android:anim/decelerate_interpolator">

    <translate 
        android:fromXDelta="0%"
        android:toXDelta="-100%"
        android:duration="1000"/>

</set>

3.other_slide_in.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:interpolator="@android:anim/decelerate_interpolator" >

    <translate 
        android:fromXDelta="0%"
        android:toXDelta="-80%"
        android:duration="1000"
        android:fillEnabled="true"/>

</set>

4.other_slide_out.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:interpolator="@android:anim/decelerate_interpolator">

    <translate 
        android:fromXDelta="0%"
        android:toXDelta="80%"
        android:duration="1000"
        android:fillEnabled="true"/>

</set>

거기 당신은 완전한 작동과 기능 슬라이딩 메뉴를 이동하고 하나는 여전히 몇 가지 문제는, 내가 당신을 도와 즐거움을 느낄 물어 주시기 설정이 있다면 당신은, 당신의 요구 사항을 충족하도록 사용자 정의 할 수 있습니다 :


4
나는 바퀴 를 재발 명 하는 팬은 아니지만 여기에 제공 한 신중하고 완전한 답변에 감사드립니다.
— hwrdprkns

내가 말하고 무엇을 의미하는지 농담 @hwrdprkns은 ... 모든 사람이 : 학습 및 구현의 동작 채택해야한다는 것입니다
— 무하마드 바바

에 정말 좋은 게시물에 대한 @hwrdprkns 한 바퀴 개혁
— 무하마드 바바

5

다른 많은 솔루션이 이전 Android 버전에서 작동하지 않는 것처럼 보이거나 작동 방법에 대한 적절한 지침이 부족했기 때문에보기를 밀어 내고 아래에 메뉴를 표시하는 자체 솔루션을 만들었습니다.

내 솔루션에는 다음과 같은 기능이 있습니다.

  • 보기를 밀어내어 아래에있는 메뉴를 표시하는 기능을 제공합니다.
  • 위의 메뉴와보기는 모두 사용자 정의보기가 될 수 있습니다.
  • 이전 Android 버전에서 지원됨 (최소 Android 2.2에서 작동하도록 테스트 됨)
  • PhoneGap / Cordova 프로젝트에서 작동

이 솔루션은 2 개의 뷰를 추가 할 것으로 예상되는 SlidingMenuLayout이라는 사용자 지정 레이아웃을 사용합니다. 추가 한 첫 번째보기는 메뉴이고 두 번째보기는 기본보기입니다.

기존 프로젝트에 레이아웃을 추가하는 가장 간단한 방법은 활동의 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 프로젝트 페이지에 있습니다.


안녕하세요, 저는 귀하의 솔루션이 마음에 들었습니다. 저는 2.2 휴대폰에서 작업하고 있습니다. "메인"레이아웃을 슬라이드하지만 "메뉴"를 닫을 때에도 "메뉴"레이아웃이 표시됩니다. 이유는 무엇입니까?
— Veer

나는 같은 문제가 있었다. 단지 "메인"레이아웃에 배경색이 있는지 확인하고 잘 작동 할 것이다.
— iTech

3

SlidingMenu 라이브러리 ( https://github.com/jfeinstein10/SlidingMenu ) 를 사용하는 분들을 위해 잭 인 방법이 있으며 작동하는 것 같습니다! @Scirocco의 도움으로 활동을 위해 이것을 넣으십시오 onCreate.

ViewGroup decorView = (ViewGroup) getWindow().getDecorView();
mSlidingMenu = new SlidingMenu(this);
ViewGroup mainContent = (ViewGroup) decorView.getChildAt(0);
decorView.removeView(mainContent);
mSlidingMenu.setContent(mainContent);
decorView.addView(mSlidingMenu);
mMenu = (LinearLayout) View.inflate(this, R.layout.menuview, null);
mSlidingMenu.setMenu(mMenu);
mSlidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
mSlidingMenu.setBehindOffsetRes(R.dimen.slidingmenu_offset);

기본적으로 linearlayout장식보기를 slidingmenu대신으로 대체합니다 .

주의 : 나는 가볍게 테스트했지만 작동하는 것 같습니다.


0
    public class ImprovedSlidingPaneLayout extends SlidingPaneLayout {
    Context context;
    FrameLayout left;
    FrameLayout right;
    Boolean canOpen = true;
    public ImprovedSlidingPaneLayout(Context context) {
        super(context);
        this.context = context;
        this.left = new FrameLayout(context);
        this.right = new FrameLayout(context);
        this.addView(left);
        this.addView(right);
    }
    public ImprovedSlidingPaneLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (canOpen)
            return super.onInterceptTouchEvent(ev);
        else
            return false;
    }

    public ImprovedSlidingPaneLayout canOpen(Boolean canOpen) {
        this.canOpen = canOpen;
        return this;
    }

    public ImprovedSlidingPaneLayout makeActionBarSlide(Window window){
        ViewGroup decorView = (ViewGroup) window.getDecorView();
        ViewGroup mainContent = (ViewGroup) decorView.getChildAt(0);
        decorView.removeView(mainContent);
        setContentView(mainContent);
        decorView.addView(this);
        return this;
    }

    public ImprovedSlidingPaneLayout setMenuView(View view){
        if((left.getChildCount()== 1)){
            left.removeView(left.getChildAt(0));
        }
        left.addView(view);
        return this;
    }

    public ImprovedSlidingPaneLayout setContentView(View view){
        if((right.getChildCount()== 1)){
            right.removeView(right.getChildAt(0));
        }
        right.addView(view);
        return this;
    }

    public ImprovedSlidingPaneLayout setMenuWidth(int width){
        left.setLayoutParams(new SlidingPaneLayout.LayoutParams(width, ViewGroup.LayoutParams.MATCH_PARENT));
        return this;
    }

}

이것은 내 클래스 확장 SlidingPaneLayout입니다. actio로 슬라이드 가능


레이아웃 xml의 <android.support.v4.widget.SlidingPaneLayout> 태그를 클래스로 바꾸려고 시도했지만 아무것도 변경되지 않았습니다. 액션 바없이 계속 슬라이딩합니다. 다른 일을 한 적이 있고 여기서 언급하지 않았습니까? 감사!
— Amir Uval 2014
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.