메뉴 건너뛰기

조회 수 12596 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄 첨부
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄 첨부

페이스북 앱을 보면 좌측 메뉴 버튼을 눌렀을 때 좌측에서 슬라이드로 메뉴가 나오게 됩니다. 


원리는 메인화면을 구성하는 xml에 전체를 FrameLayout으로 감싸고 내부에 메뉴 레이아웃을 깔고 


그 위에 메인 화면의 레이아웃을 포개어 놓습니다. 그러고 메인화면의 메뉴 버튼을 눌렀을 때 메인화면 레이아웃을


애니메이션 처리하여 우측으로 밀어버려 아래에있던 메뉴 레이아웃이 노출되는 식입니다. 







<activity_main.xml>




구성요소는 다음과 같습니다.


1. MainActivity.java

2. OpenAnimation.java

3. CloseAnimation.java

4. activity_main.xml

5. leftslidemenu.xml



먼저 MainActivity 입니다. 



public class MainActivity extends Activity implements OnClickListener {

	// slide menu 
	private DisplayMetrics metrics;
	private LinearLayout ll_mainLayout;
	private LinearLayout ll_menuLayout;
	private FrameLayout.LayoutParams leftMenuLayoutPrams;
	private int leftMenuWidth;
	private static boolean isLeftExpanded;

	private Button bt_left, btn1, btn2, btn3, btn4;

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

		initSildeMenu();

	}

	private void initSildeMenu() {

		// init left menu width
		metrics = new DisplayMetrics();
		getWindowManager().getDefaultDisplay().getMetrics(metrics);
		leftMenuWidth = (int) ((metrics.widthPixels) * 0.75);

		// init main view
		ll_mainLayout = (LinearLayout) findViewById(R.id.ll_mainlayout);

		// init left menu
                ll_menuLayout = (LinearLayout) findViewById(R.id.ll_menuLayout);
		leftMenuLayoutPrams = (FrameLayout.LayoutParams) ll_menuLayout
				.getLayoutParams();
		leftMenuLayoutPrams.width = leftMenuWidth;
		ll_menuLayout.setLayoutParams(leftMenuLayoutPrams);

		// init ui
		bt_left = (Button) findViewById(R.id.bt_left);
		bt_left.setOnClickListener(this);

		btn1 = (Button) findViewById(R.id.btn1);
		btn2 = (Button) findViewById(R.id.btn2);
		btn3 = (Button) findViewById(R.id.btn3);
		btn4 = (Button) findViewById(R.id.btn4);
		btn1.setOnClickListener(this);
		btn2.setOnClickListener(this);
		btn3.setOnClickListener(this);
		btn4.setOnClickListener(this);
	}

	/**
	 * left menu toggle
	 */
	private void menuLeftSlideAnimationToggle() {

		if (!isLeftExpanded) {

			isLeftExpanded = true;

			// Expand
			new OpenAnimation(ll_mainLayout, leftMenuWidth,
					Animation.RELATIVE_TO_SELF, 0.0f,
					Animation.RELATIVE_TO_SELF, 0.75f, 0, 0.0f, 0, 0.0f);

			// enable all of menu view
			FrameLayout viewGroup = (FrameLayout) findViewById(R.id.ll_menuLayout)
					.getParent();
			enableDisableViewGroup(viewGroup, true);

			// enable empty view
			((LinearLayout) findViewById(R.id.ll_empty))
					.setVisibility(View.VISIBLE);

			findViewById(R.id.ll_empty).setEnabled(true);
			findViewById(R.id.ll_empty).setOnTouchListener(
					new OnTouchListener() {

						@Override
						public boolean onTouch(View arg0, MotionEvent arg1) {
							menuLeftSlideAnimationToggle();
							return true;
						}
					});

		} else {
			isLeftExpanded = false;

			// Collapse
			new CloseAnimation(ll_mainLayout, leftMenuWidth,
					TranslateAnimation.RELATIVE_TO_SELF, 0.75f,
					TranslateAnimation.RELATIVE_TO_SELF, 0.0f, 0, 0.0f, 0, 0.0f);

			
			// enable all of menu view
			FrameLayout viewGroup = (FrameLayout) findViewById(R.id.ll_menuLayout)
					.getParent();
			enableDisableViewGroup(viewGroup, false);

			// disable empty view
			((LinearLayout) findViewById(R.id.ll_empty))
					.setVisibility(View.GONE);
			findViewById(R.id.ll_empty).setEnabled(false);

		}
	}


    public static void enableDisableViewGroup(ViewGroup viewGroup,
			boolean enabled) {
		int childCount = viewGroup.getChildCount();
		for (int i = 0; i < childCount; i++) {


			View view = viewGroup.getChildAt(i);
			view.setEnabled(enabled);

			if (view instanceof ViewGroup) {
				enableDisableViewGroup((ViewGroup) view, enabled);
			}
		}
    }


	@Override
	public void onClick(View v) {

		switch (v.getId()) {
		case R.id.bt_left:
			menuLeftSlideAnimationToggle();
			break;
		case R.id.btn1:
			Toast.makeText(getApplicationContext(), "1", Toast.LENGTH_SHORT)
					.show();
			break;
		case R.id.btn2:
			Toast.makeText(getApplicationContext(), "2", Toast.LENGTH_SHORT)
					.show();
			break;
		case R.id.btn3:
			Toast.makeText(getApplicationContext(), "3", Toast.LENGTH_SHORT)
					.show();
			break;
		case R.id.btn4:
			Toast.makeText(getApplicationContext(), "4", Toast.LENGTH_SHORT)
					.show();
			break;

		}

	}
}


최초에 initSildeMenu()매소드에서 사용 할 메인 레이아웃과 메뉴 레이아웃을 초기화 합니다.


메뉴 레이아웃은 열렸을 때 화면 전체너비로 열리는 것이 아니라 우측에 메인 레이아웃이 살짝 걸치므로 


메뉴 레아이웃 너비가 될 leftMenuWidth 변수에 화면전체 너비에 0.75 정도 비율을 넣어 줍니다. 






이 후에 메인 레이아웃을 findViewById 하고 메뉴 레이아웃도 findViewById 한 후 


아까 만든 0.75의 너비를 width로 넣어줍니다. 나머지 버튼들도 리스너를 달아줍니다. 




이제 핵심이 되는 menuLeftSlideAnimationToggle() 매소드 입니다


토글이라는 말과 같이 메뉴가 열고 닫힐 때 모두 이 매소드를 사용하며


isLeftExpanded라는 boolean 값으로 열고 닫힐 때를 판단하게 됩니다.


우선 열릴 때 입니다.


메뉴버튼을 눌러 메뉴가 열리게 되면 우선 isLeftExpanded = true; 를 줘서 메뉴가 열렸다를 저장하고


OpenAnimation 이란 클래스를 통하여 메뉴가 열리게 됩니다.


처음 구조 설명 할 때 설명을 안했지만 메인 레이아웃 위에 empty 레이아웃을 하나 더 포개었는데


이 뷰를 VISIBLE 시키게 됩니다. 이 ll_empty 뷰는 투명한 뷰이며 


메뉴가 열려있을 때 우측에 살짝 보이는 메인 레이아웃을 덮고 있습니다. 


이 뷰를 터치하면 menuLeftSlideAnimationToggle(); 매소드를 호출하여 메뉴가 닫히게 됩니다. 


이는 꼭 메뉴버튼을 눌러야 메뉴가 닫히는것이 아닌 그냥 메인 뷰만 터치하면 닫히도록하는 편리함을 위함입니다.




public class OpenAnimation extends TranslateAnimation implements
		Animation.AnimationListener {

	private LinearLayout mainLayout
	int panelWidth;

	public OpenAnimation(LinearLayout layout, int width, int fromXType,
			float fromXValue, int toXType, float toXValue, int fromYType,
			float fromYValue, int toYType, float toYValue) {

		super(fromXType, fromXValue, toXType, toXValue, fromYType, fromYValue,
				toYType, toYValue);

		// init
		mainLayout = layout;
		panelWidth = width;
		setDuration(250);
		setFillAfter(false);
		setInterpolator(new AccelerateDecelerateInterpolator());
		setAnimationListener(this);
		mainLayout.startAnimation(this);
	}

	public void onAnimationEnd(Animation arg0) {

		LayoutParams params = (LayoutParams) mainLayout.getLayoutParams();
		params.leftMargin = panelWidth;
		params.gravity = Gravity.LEFT;
		mainLayout.clearAnimation();
		mainLayout.setLayoutParams(params);
		mainLayout.requestLayout();

	}

	public void onAnimationRepeat(Animation arg0) {

	}

	public void onAnimationStart(Animation arg0) {

	}

}


OpenAnimation 클래스입니다. 받아온 속성들로 초기화를 하며 setDuration(250);이 부분이 열릴 때의 속도입니다.



메뉴가 닫힐 때는 isLeftExpanded로 닫힐 때를 가려내고 isLeftExpanded = flase;를 줘 닫힘을 저장합니다.


OpenAnimarion 클래스와 같이 CloseAnimation을 호출하게되고 활성화 되어있던 empty뷰를 꺼서 


메인 레이아웃이 다시 노출되게 합니다.

public class CloseAnimation extends TranslateAnimation implements
		TranslateAnimation.AnimationListener {

	private LinearLayout mainLayout;
	int panelWidth;

	public CloseAnimation(LinearLayout layout, int width, int fromXType,
			float fromXValue, int toXType, float toXValue, int fromYType,
			float fromYValue, int toYType, float toYValue) {

		super(fromXType, fromXValue, toXType, toXValue, fromYType, fromYValue,
				toYType, toYValue);

		// Initialize
		mainLayout = layout;
		panelWidth = width;
		setDuration(250);
		setFillAfter(false);
		setInterpolator(new AccelerateDecelerateInterpolator());
		setAnimationListener(this);

		// Clear left and right margins
		LayoutParams params = (LayoutParams) mainLayout.getLayoutParams();
		params.rightMargin = 0;
		params.leftMargin = 0;
		mainLayout.setLayoutParams(params);
		mainLayout.requestLayout();
		mainLayout.startAnimation(this);

	}

	public void onAnimationEnd(Animation animation) {

	}

	public void onAnimationRepeat(Animation animation) {

	}

	public void onAnimationStart(Animation animation) {

	}

}


CloseAnimation입니다. 



아래엔 사용한 xml 파일입니다.


<-- activity_main.xml -->


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="fill_parent"

    android:layout_height="match_parent"

    android:orientation="vertical" >


    <FrameLayout

        android:layout_width="fill_parent"

        android:layout_height="match_parent"

        android:background="#ffffff"

        android:orientation="vertical" >


        <LinearLayout

            android:id="@+id/ll_menuLayout"

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:background="#ff393c46"

            android:gravity="left"

            android:orientation="vertical"

            android:textColor="#ff000000" >


            <!-- include -->


            <include

                android:id="@+id/ic_leftslidemenu"

                android:layout_width="match_parent"

                android:layout_height="match_parent"

                layout="@layout/leftslidemenu" />

        </LinearLayout>


        <!-- slide layout -->


        <LinearLayout

            android:id="@+id/ll_mainlayout"

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:background="#ffffffff"

            android:gravity="left"

            android:orientation="vertical" >


            <FrameLayout

                android:layout_width="match_parent"

                android:layout_height="match_parent" >


                <Button

                    android:id="@+id/bt_left"

                    android:layout_width="wrap_content"

                    android:layout_height="wrap_content"

                    android:layout_margin="10dp"

                    android:text="Left Slide" />


                <LinearLayout

                    android:id="@+id/ll_fragment"

                    android:layout_width="match_parent"

                    android:layout_height="wrap_content" >

                </LinearLayout>


                <LinearLayout

                    android:id="@+id/ll_empty"

                    android:layout_width="fill_parent"

                    android:layout_height="fill_parent"

                    android:background="@android:color/transparent" />

            </FrameLayout>

        </LinearLayout>

    </FrameLayout>


</LinearLayout>





<-- leftslidemenu.xml -->


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="fill_parent"

    android:layout_height="match_parent"

    android:background="#994444cc"

    android:orientation="vertical"

    android:padding="10dp" >


    <Button

        android:id="@+id/btn1"

        android:layout_width="fill_parent"

        android:layout_height="wrap_content"

        android:text="Button 1 " />


    <Button

        android:id="@+id/btn2"

        android:layout_width="fill_parent"

        android:layout_height="wrap_content"

        android:text="Button 2 " />


    <Button

        android:id="@+id/btn3"

        android:layout_width="fill_parent"

        android:layout_height="wrap_content"

        android:text="Button 3 " />


    <Button

        android:id="@+id/btn4"

        android:layout_width="fill_parent"

        android:layout_height="wrap_content"

        android:text="Button 4 " />


</LinearLayout>



위 처럼 메인 레이아웃에 메뉴 레이아웃이 include 되어있습니다. 




-- 2013 10 04 내용추가 


현재 버전에는 메인 화면에서는 메인 화면이 덮고있는 중에도 터치를 하면 뒤 LeftMenu의 버튼이 눌리게 됩니다. 


초보개발자 님 말씀대로 visible방법도 가능하고 


저는 뷰를 닫을 때 LeftMenu에 있는 모든 뷰를 다 setEnable로 꺼버리고 


열 때는 켜는 식을 사용 했습니다. 


열고 닫을 때 


FrameLayout viewGroup = (FrameLayout) findViewById(R.id.ll_menuLayout)

.getParent();


이런식으로 menu  레이아웃을 잡고 


enableDisableViewGroup(viewGroup, false);


setEnable을 true 할 건지 false 할 건지 정해 주시면 됩니다. 


그럼 


 public static void enableDisableViewGroup(ViewGroup viewGroup,
            boolean enabled) {
        int childCount = viewGroup.getChildCount();
        for (int i = 0; i < childCount; i++) {
 
 
            View view = viewGroup.getChildAt(i);
            view.setEnabled(enabled);
 
            if (view instanceof ViewGroup) {
                enableDisableViewGroup((ViewGroup) view, enabled);
            }
        }
  }
 

menu레이아웃에 있는 뷰들의 갯수 만큼 for문을 돌며 각각 setEnable을 할 수 있습니다.



응용하면 좌측 슬라이드 메뉴를 열었을 때 좌측 슬라이드에 있는 다른 버튼은 눌리지 않고

LeftSlide 버튼만 눌리게 하고싶을 땐

FrameLayout viewGroup = (FrameLayout) findViewById(R.id.ll_fragment)

.getParent();


이렇게 좌측 슬라이드 메뉴 레이아웃을 잡고 


enableDisableViewGroup 매소드 for문 안쪽에


View view = viewGroup.getChildAt(i);


if (view.getId() != R.id.ib_left) {

view.setEnabled(enabled);

if (view instanceof ViewGroup) {

enableDisableViewGroup((ViewGroup) view, enabled);

}

}


이런식으로 LeftSlide 버튼만 살려서 disable을 막는 방법이 있습니다.











LeftSlideMenuExample.zip









-- 2013 10 22 내용추가 


좌 우 측 슬라이드가 모두 되는 소스 첨부 합니다. 


우측 슬라이드도 좌측 슬라이드와 같은 방식으로 만들었습니다. 





SlideMenu.zip





List of Articles
번호 제목 날짜 조회 수
137 버튼 누르면 이미지 바꾸기 file 2015.07.26 6688
136 내가 입력한 글자 Toast로 나오게 하기 file 2015.07.26 6970
135 Android Navigation Drawer API 공개! 디자인 가이드 살펴보기 file 2015.07.29 8205
134 manifest 의 launchMode 속성 2015.08.11 7634
133 [안드로이드 강좌] 초보자들이 많이 하는 실수 file 2015.08.11 6894
132 안드로이드 기본어플 예제 어플소스 모음 2015.08.17 8933
131 [안드로이드] 콘텍스트 메뉴 사용예제 file 2015.09.03 7400
130 [안드로이드] 팝업메뉴 사용법 file 2015.09.03 9528
129 [안드로이드] 빠르게 사용할수 있는 컨텍스트 메뉴 만들기 file 2015.09.03 6874
128 [안드로이드] 리스트 뷰의 한 항목에 대한 컨텍스트 메뉴 만들기 file 2015.09.04 9153
127 안드로이드 로그인 화면 만들기 file 2015.09.05 8114
126 JAVA JDBC를 사용하여 MySQL과 연동 file 2015.11.21 8729
125 안드로이드 EditText 필터링 검색 구현(adapter.getFilter().filter(cs)) file 2015.12.14 8851
124 안드로이드 EditText 필터링 검색 file 2015.12.14 7761
123 Android Push GCM 서버 구성 하기(3) file 2015.12.14 6467
122 안드로이드 로그인유지 코드 2015.12.14 8861
121 Android] 안드로이드 홈 디렉토리 알아내기 2015.12.15 6986
120 Android] Fragment 내부의adapter에서 startActivity 하기 2015.12.15 6576
119 Android TIP] strings.xml 에서 특수문자 사용하기 2015.12.15 6713
» 안드로이드] 페이스북 같은 슬라이드 메뉴 만들기 file 2015.12.15 12596
Board Pagination Prev 1 2 3 4 5 6 7 8 9 10 11 ... 13 Next
/ 13

하단 정보를 입력할 수 있습니다

© k2s0o1d4e0s2i1g5n. All Rights Reserved