메뉴 건너뛰기

조회 수 12535 추천 수 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
번호 제목 날짜 조회 수
237 HTML5로 나만의 비디오 플레이어 스킨 만들기 -2- JavaScript file 2014.09.04 6312
236 HTML5로 나만의 비디오 플레이어 스킨 만들기 -3- JavaScript file 2014.09.04 6288
235 HTML5 드래그 앤 드롭 하기 Drag and Drop file 2014.09.04 7744
234 HTML5 Web Storage -01- file 2014.09.04 5587
233 HTML5 Form 공부하기 -1- file 2014.09.04 5841
232 HTML5 Form 공부하기 -2- file 2014.09.04 6329
231 HTML5로 게임 만들기 워밍업 file 2014.09.04 6063
230 HTML5 Better semantic tags file 2014.09.04 5952
229 HTML5 Geolocation (구글 지도에 현위치 표시하기) file 2014.09.04 6810
228 jQuery ajax post 요청 text 응답 2014.10.16 6702
227 JSON(JavaScript Object Notation) - jQuery Ajax - jQuery.getJSON() 메서드 (비동기적으로 JSON파일 로드) file 2014.10.16 6568
226 jQuery Ajax - jQuery.load() 메서드 (동적으로 원격 페이지 로드) file 2014.10.16 6409
225 트리뷰(TreeView) 컨트롤 file 2014.10.16 6720
224 Effects - Stop() 메서드 (애니메이션 효과 멈추기) file 2014.10.16 6225
223 Effects - Animate() 메서드 (여러가지 효과 동시 처리) file 2014.10.16 30591
222 Effects - SlideToggle() 메서드 (슬라이드 업/다운) file 2014.10.16 6758
221 Effects - SlideUp() 메서드 (슬라이드업) file 2014.10.16 5999
220 Effects - FadeIn() / FadeOut() 메서드 (서서히 보이기 및 숨기기) file 2014.10.16 6068
219 Effects - Show() / Hide() 메서드 (보이기 및 숨기기) file 2014.10.16 5957
218 Events - Unbind() 메서드 (이벤트 처리기 해제) file 2014.10.16 5749
Board Pagination Prev 1 2 3 4 5 6 7 8 9 10 ... 13 Next
/ 13

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

© k2s0o1d4e0s2i1g5n. All Rights Reserved