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하여 액티비티에 대한 ViewPagerPagerTabStrip두 클래스 위에서 바로 중지를 확장 할 수 있도록 토크, 시장 등과 같은 탭 당신은, 쉬운 방법으로 이러한 뷰를 사용하지 않도록 설정할 수없는 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.