android 가로 스크롤 슬라이딩 메뉴(Sliding Menu)
HorizontalScrollView를 상속받아 구현
<스크롤뷰 초기 이동>
- 스크롤뷰 초기 설정이 동작하지 않는다. ex) scrollView.scrollTo(x,y)
- 그때는 이렇게 하면 된다.
scrollView.post(new Runnable(){ public void run() { scrollView.scrollTo(x, y); } });
- 만약 0.1초 정도의 딜레이를 주고 스크롤 뷰를 움직이고 싶다면..
scrollView.postDelayed(new Runnable(){ public void run() { scrollView.scrollTo(x, y); } }, 100);
< scrollTo, scrollBy, smoothScrollTo >
scrollBy(x,y) 해당뷰의 현재좌표에서 가로 x만큼, 세로 y만큼 이동
scrollTo(x,y) 해당뷰의 절대좌표 x,y 로 이동함
smoothScrollTo(x,y) 해당뷰의 절대좌표 x,y 로 부드럽게 이동
아래 소스는 화면 캡춰하는 소스도 포함되었으니 알아서 보세요..
< MiniMyTestActivity.java 소스 >
package dingdong.util.minimytest; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.os.Bundle; import android.os.Environment; import android.view.Display; import android.view.View; import android.view.WindowManager; import android.widget.Button; import android.widget.LinearLayout; public class MiniMyTestActivity extends Activity{ View capView; // 캡춰 private MenuSlideView mSlideView; private Context mContext; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mContext = this; setContentView(R.layout.main); Button bt_capture = (Button)findViewById(R.id.bt_capture); Button bt_scrollTo = (Button)findViewById(R.id.bt_scrollTo); LinearLayout ly_main = (LinearLayout)findViewById(R.id.ly_main); bt_capture.setOnClickListener(mClickListener); bt_scrollTo.setOnClickListener(mClickListener); capView = ly_main; // 리니어 레이아웃 캡춰 // capView = getWindow().getDecorView(); // 전체 화면 캡춰 mSlideView = (MenuSlideView)findViewById(R.id.menu_slide); // 이게 왜 안되지? --> 아래처럼 하면 동작함 // mSlideView.post(new Runnable(){ // public void run() { // //get screen size, move default scroll position // Display display = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); // int mScreenWidth = display.getWidth(); // mSlideView.scrollTo(mScreenWidth/3, 0); // } // }); mSlideView.moveDefault(0,3); } protected void onResume() { super.onResume(); mContext = this; }; View.OnClickListener mClickListener = new View.OnClickListener() { @Override public void onClick(View v) { switch (v.getId()) { case R.id.bt_capture: try { screenshot(capView); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } break; case R.id.bt_scrollTo: try { //get screen size, move default scroll position Display display = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); int mScreenWidth = display.getWidth(); mSlideView.smoothScrollTo(mScreenWidth/3, 0); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } break; default: break; } } }; public void screenshot (View view) throws Exception{ view.setDrawingCacheEnabled(true); Bitmap scrreenshot = view.getDrawingCache(); String filename = "screenshot.png"; try{ File f = new File(Environment.getExternalStorageDirectory(),filename); f.createNewFile(); OutputStream outStream = new FileOutputStream(f); scrreenshot.compress(Bitmap.CompressFormat.PNG, 100, outStream); outStream.close(); }catch( IOException e){ e.printStackTrace(); } view.setDrawingCacheEnabled(false); } }
< MenuSlideView.java 소스 >
package dingdong.util.minimytest; import android.content.Context; import android.os.SystemClock; import android.util.AttributeSet; import android.util.Log; import android.view.Display; import android.view.GestureDetector; import android.view.GestureDetector.OnGestureListener; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.Button; import android.widget.HorizontalScrollView; import android.widget.ImageView; import android.widget.Toast; /** * @author damianjj * */ public class MenuSlideView extends HorizontalScrollView{ private Context mContext; private int mScreenWidth; private static final String TAG = "MiniApp"; private static final int SWIPE_MIN_DISTANCE = 120; private static final int SWIPE_MAX_OFF_PATH = 250; private static final int SWIPE_THRESHOLD_VELOCITY = 200; private int mCurPosX = 0; ImageView iv_left; private int mMoveDefault = -1; //Gesture private GestureDetector mGesture; private GestureDetector.OnGestureListener mGesturesListener = new OnGestureListener(){ @Override public boolean onDown(MotionEvent e){ Log.d(TAG, "start onDown"); return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { Log.d(TAG, "start onFling"); // TODO int nScrollX = getScrollX(); int nScrollY = getScrollY(); // 지정된 위치로 이동, 부드럽게 이동(smoothScrollTo) moveThisPos(nScrollX, nScrollY); // try { // if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) // return false; // // // right to left swipe <----------------- // if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE // && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { // Toast.makeText(mContext, "<------------ ("+velocityX+","+velocityY+")", Toast.LENGTH_SHORT).show(); // } // // left to right swipe ------------> // else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE // && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { // Toast.makeText(mContext, "------------> ("+velocityX+","+velocityY+")", Toast.LENGTH_SHORT).show(); // } // // down to up swipe // else if (e1.getY() - e2.getY() > SWIPE_MIN_DISTANCE // && Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) { // Toast.makeText(mContext, "Swipe up", Toast.LENGTH_SHORT).show(); // } // // up to down swipe // else if (e2.getY() - e1.getY() > SWIPE_MIN_DISTANCE // && Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) { // Toast.makeText(mContext, "Swipe down", Toast.LENGTH_SHORT).show(); // } // } catch (Exception e) { // // } return false; } @Override public void onLongPress(MotionEvent e) { Log.d(TAG, "start onLongPress"); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // Log.d(TAG, "start onScroll"); smoothScrollBy((int)distanceX,0); // 스크롤할때 따라오기 int nScrollX = getScrollX(); // 스크롤 현위치 int nScrollY = getScrollY(); // Toast.makeText(mContext, "onScroll, nScrollX="+nScrollX+", nScrollY="+nScrollY+",("+distanceX+","+distanceY+")", Toast.LENGTH_SHORT).show(); // Log.d(TAG, "onScroll, nScrollX="+nScrollX+", nScrollY="+nScrollY+",("+distanceX+","+distanceY+")"); return false; } @Override public void onShowPress(MotionEvent e) { Log.d(TAG, "start onShowPress"); } @Override public boolean onSingleTapUp(MotionEvent e) { Log.d(TAG, "start onSingleTapUp"); return false; } }; public MenuSlideView(Context context) { super(context); mContext = context; createSubView(); } public MenuSlideView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mContext = context; createSubView(); } public MenuSlideView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; createSubView(); } private void createSubView() { mGesture = new GestureDetector(mContext, mGesturesListener); //scroll view setting setHorizontalScrollBarEnabled(false); //get screen size Display display = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); mScreenWidth = display.getWidth(); Toast.makeText(mContext, "mSW="+mScreenWidth, Toast.LENGTH_SHORT).show(); //set sub layout LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View v = inflater.inflate(R.layout.menu_layout, null); iv_left = (ImageView)v.findViewById(R.id.iv_left); // iv_left.setVisibility(View.GONE); // 자리 안차지 iv_left.setVisibility(View.INVISIBLE); // 자리 차지 ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, 100); // 높이 100 addView(v,params); } public void moveDefault(int x, int count){ if(count != 0){ mMoveDefault = mScreenWidth/count; }else{ mMoveDefault = x; } // 스크롤바 초기 이동 post(new Runnable(){ public void run() { //get screen size, move default scroll position scrollTo(mMoveDefault, 0); } }); mCurPosX = mMoveDefault; } @Override public boolean onTouchEvent(MotionEvent ev) { int nScrollX = getScrollX(); int nScrollY = getScrollY(); float nMoveX = ev.getX(); float nMoveY = ev.getY(); mGesture.onTouchEvent(ev); int action = ev.getAction(); switch(action){ case MotionEvent.ACTION_MOVE: Log.d(TAG, "ACTION_MOVE: getScrollX()="+getScrollX()); break; case MotionEvent.ACTION_UP: // TODO // 지정된 위치로 이동, 부드럽게 이동(smoothScrollTo) moveThisPos(nScrollX, nScrollY); // // Toast.makeText(mContext, "ACTION_UP: Scroll("+nScrollX+","+nScrollY+")"+" POS("+nMoveX+","+nMoveY+")", Toast.LENGTH_SHORT).show(); // Log.d(TAG, "ACTION_UP: Scroll("+nScrollX+","+nScrollY+")"+" POS("+nMoveX+","+nMoveY+")"); break; } return true; } // 지정된 위치로 이동 public void moveThisPos(int nScrollX, int nScrollY){ if(nScrollX < mScreenWidth/6){ smoothScrollTo(0,0); }else if(nScrollX >= mScreenWidth/6 && nScrollX < mScreenWidth/3){ smoothScrollTo(mScreenWidth/3,0); }else if(nScrollX >= mScreenWidth/3 && nScrollX < mScreenWidth/2){ smoothScrollTo(mScreenWidth/3,0); }else if(nScrollX >= (mScreenWidth/2) && nScrollX < (mScreenWidth/3*2)){ smoothScrollTo(mScreenWidth/3*2,0); }else if(nScrollX >= (mScreenWidth/3+mScreenWidth/3) && nScrollX < (mScreenWidth/6*5)){ smoothScrollTo(mScreenWidth/3*2,0); }else if(nScrollX >= (mScreenWidth/6*5) && nScrollX < (mScreenWidth)){ smoothScrollTo(mScreenWidth,0); } } }
< Menu_layout.xml 소스 >
< main.xml 소스 >
<참고 자료>
@@ Sliding Menu @@
https://github.com/gitgrimbo/android-sliding-menu-demo
---> 좋은 소스임.. 참고하세요..
@ Sliding Toggle 버튼 만들기(SlidingDrawer 상속) @
http://www.androidpub.com/878847
@@ 슬라이드바 @@
android animation slidedown slideup
Android Sliding Drawer
http://ememomo.tistory.com/tag/Slide
@@ 좌우 슬라이딩 @@
--> 주로 이소스를 수정하여서 만들었음.
@Android: Making a TextView Scrollable
http://www.gubatron.com/blog/2010/04/19/android-making-a-textview-scrollable/
@@@ API Demos - ImageSwitcher @@@
최근까지 여기저기 삽질을 해본결과
안드로이드에 기본제공되는 API Demos의 Views - ImageSwitcher 소스를 참고해서
가로 이미지 스크롤 메뉴나, 가로 텍스트 스크롤메뉴를 만드는것이 가장 좋아보임.
즉 Gallery 를 이용하는것이 젤 좋아보임.. 이 방식이 스크롤 동작이 가장 부드럽고, 터치시에 가운데로 움직이는 기능도 있어서 좋다.
10점만점에 10점..
이것을 이용해서 만든 앱(SK Btv 방송 편성표)..
Btv 편성표 다운로드 (안드로이드 마켓 이동)
여기는 참고자료..
< 가로 스크롤뷰를 상속하여 만든 메뉴 소스 다운로드 >
(추신 : 소스 다운로드시에 감사의 댓글을~~~)
(SyntaxHighlighter를 처음 적용해봐서.. 레이아웃이 좀 깨지네요.. ㅠ.ㅠ 그래도 소스 보기는 좋은듯..)
'안드로이드 개발 팁' 카테고리의 다른 글
android에서 assets에 있는 기존 sqlite DB 사용하기 (2) | 2012.05.07 |
---|---|
안드로이드 디자인 (0) | 2012.05.03 |
안드로이드에서 강제로 터치 이벤트 발생시키기 (0) | 2012.04.16 |
안드로이드 화면 캡춰 소스 (0) | 2012.04.12 |
안드로이드용 이클립스 세팅 절차 (0) | 2012.02.06 |