메뉴 건너뛰기

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

단축키

Prev이전 문서

Next다음 문서

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

단축키

Prev이전 문서

Next다음 문서

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

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


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


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


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





2469FA4B52119F7E08FF5D



<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 정도 비율을 넣어 줍니다. 



2728283D5211845522494D




이 후에 메인 레이아웃을 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을 막는 방법이 있습니다.




출처: http://muzesong.tistory.com/83




List of Articles
번호 제목 날짜 조회 수
157 [안드로이드] 뷰(View)의 너비와 높이 지정하기 file 2015.07.17 7215
156 [안드로이드] 뷰(View)에 여백넣기 file 2015.07.17 7295
155 [안드로이드] 버튼 이벤트 처리하기 file 2015.07.17 7102
154 안드로이드 webview (웹뷰) 개발 #1 - 웹사이트를 어플로 만들어 보자! file 2015.07.17 8963
153 안드로이드 webview (웹뷰) 개발 #2 - 파일 첨부 및 플러그인 적용하기 file 2015.07.17 8346
152 안드로이드 webview (웹뷰) 개발 #3 - 초기 로딩화면 (splash) 띄우기 + 아이콘 적용하기 file 2015.07.17 8748
151 안드로이드 webview (웹뷰) 개발 #4 - 멀티터치 ( 확대 / 축소 ) 적용 file 2015.07.17 7603
150 안드로이드 ( Android ) APK 파일 생성하기 file 2015.07.17 7364
» [안드로이드] 페이스북 같은 슬라이드 메뉴 만들기 file 2015.07.21 8274
148 [안드로이드] 화면추가 버튼 리스너 file 2015.07.22 7753
147 안드로이드 스튜디오 gradle error 해결 2015.07.23 6743
146 안드로이드 팝업창 만들기(xml 내용 집어넣기) file 2015.07.23 9359
145 블루투스(Bluetooth) 통신에 대해 알아보자 file 2015.07.26 14117
144 블루투스 및 비콘 관련 정리 2015.07.26 10884
143 안드로이트 비콘 스캐닝시 고려 사항 2015.07.26 6723
142 폰갭 비콘 디텍팅 안될 때 (기본적인건 다 되있어야됨) 2015.07.26 6580
141 안드로이드 종료 취소 다이얼로그 코드 2015.07.26 6448
140 안드로이드 로딩화면 샘플 file 2015.07.26 7648
139 안드로이드 채팅 소스 샘플 file 2015.07.26 10148
138 화면 전환해도 데이터 유지 예제 2015.07.26 9269
Board Pagination Prev 1 2 3 4 5 6 7 8 9 10 ... 13 Next
/ 13

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

© k2s0o1d4e0s2i1g5n. All Rights Reserved