Android 는 슬라이딩 메뉴 프레임 워 크 를 이용 하여 슬라이딩 메뉴 효 과 를 구현 합 니 다.
19824 단어 android슬라이딩 메뉴메뉴 프레임 워 크
이전 글 에서 도 마지막 으로 언급 했 듯 이 애플 리 케 이 션 에 많은 Activity 가 미끄럼 메뉴 기능 을 추가 해 야 한다 면 모든 Activity 는 백 줄 의 코드 를 써 야 효 과 를 낼 수 있 고 아무리 간단 한 미끄럼 메뉴 구현 방안 도 소 용이 없다.따라서 우 리 는 오늘 미끄럼 메뉴 의 프레임 워 크 를 실현 하고 모든 Activity 에서 1 분 동안 미끄럼 메뉴 기능 을 도입 할 수 있 습 니 다.
우선 실현 원 리 를 말 해 보 자.슬라이딩 메뉴 의 프레임 워 크 라 고 하 더 라 도 솔직히 말하자면 간단 합 니 다.바로 우리 가 레이아웃 을 사용자 정의 하 는 것 입 니 다.이 사용자 정의 레이아웃 에서 슬라이딩 메뉴 의 기능 을 잘 실현 한 다음 에 Activity 의 레이아웃 파일 에 사용자 정의 레이아웃 을 도입 하면 이 Activity 는 슬라이딩 메뉴 의 기능 을 가지 게 됩 니 다.원 리 를 다 말 했 으 니 매우 간단 하지 않 습 니까?다음은 우리 가 손 을 써 서 실현 합 시다.
Eclipse 에 안 드 로 이 드 프로젝트 를 새로 만 들 었 습 니 다.프로젝트 이름 은 RenRenSliding Layout 입 니 다.
SlidingLayout 라 는 클래스 를 새로 만 들 었 습 니 다.이 클래스 는 LinearLayout 에서 계승 되 었 고 OnTouchListener 인 터 페 이 스 를 실 현 했 습 니 다.구체 적 인 코드 는 다음 과 같 습 니 다.
public class SlidingLayout extends LinearLayout implements OnTouchListener {
/**
* , 。
*/
public static final int SNAP_VELOCITY = 200;
/**
* 。
*/
private int screenWidth;
/**
* 。 ,marginLeft , 。
*/
private int leftEdge;
/**
* 。 0, marginLeft 0 , 。
*/
private int rightEdge = 0;
/**
* , 。
*/
private int leftLayoutPadding = 80;
/**
* 。
*/
private float xDown;
/**
* 。
*/
private float xMove;
/**
* 。
*/
private float xUp;
/**
* 。 , 。
*/
private boolean isLeftLayoutVisible;
/**
* 。
*/
private View leftLayout;
/**
* 。
*/
private View rightLayout;
/**
* View。
*/
private View mBindView;
/**
* , , leftMargin 。
*/
private MarginLayoutParams leftLayoutParams;
/**
* , 。
*/
private MarginLayoutParams rightLayoutParams;
/**
* 。
*/
private VelocityTracker mVelocityTracker;
/**
* SlidingLayout , 。
*
* @param context
* @param attrs
*/
public SlidingLayout(Context context, AttributeSet attrs) {
super(context, attrs);
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
screenWidth = wm.getDefaultDisplay().getWidth();
}
/**
* View, View 。
*
* @param bindView
* View 。
*/
public void setScrollEvent(View bindView) {
mBindView = bindView;
mBindView.setOnTouchListener(this);
}
/**
* , 30.
*/
public void scrollToLeftLayout() {
new ScrollTask().execute(30);
}
/**
* , -30.
*/
public void scrollToRightLayout() {
new ScrollTask().execute(-30);
}
/**
* , , 。
*
* @return true, false。
*/
public boolean isLeftLayoutVisible() {
return isLeftLayoutVisible;
}
/**
* onLayout 。
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (changed) {
//
leftLayout = getChildAt(0);
leftLayoutParams = (MarginLayoutParams) leftLayout.getLayoutParams();
// leftLayoutPadding
leftLayoutParams.width = screenWidth - leftLayoutPadding;
//
leftEdge = -leftLayoutParams.width;
leftLayoutParams.leftMargin = leftEdge;
leftLayout.setLayoutParams(leftLayoutParams);
//
rightLayout = getChildAt(1);
rightLayoutParams = (MarginLayoutParams) rightLayout.getLayoutParams();
rightLayoutParams.width = screenWidth;
rightLayout.setLayoutParams(rightLayoutParams);
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
createVelocityTracker(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// ,
xDown = event.getRawX();
break;
case MotionEvent.ACTION_MOVE:
// , , , leftMargin ,
xMove = event.getRawX();
int distanceX = (int) (xMove - xDown);
if (isLeftLayoutVisible) {
leftLayoutParams.leftMargin = distanceX;
} else {
leftLayoutParams.leftMargin = leftEdge + distanceX;
}
if (leftLayoutParams.leftMargin < leftEdge) {
leftLayoutParams.leftMargin = leftEdge;
} else if (leftLayoutParams.leftMargin > rightEdge) {
leftLayoutParams.leftMargin = rightEdge;
}
leftLayout.setLayoutParams(leftLayoutParams);
break;
case MotionEvent.ACTION_UP:
// , , ,
xUp = event.getRawX();
if (wantToShowLeftLayout()) {
if (shouldScrollToLeftLayout()) {
scrollToLeftLayout();
} else {
scrollToRightLayout();
}
} else if (wantToShowRightLayout()) {
if (shouldScrollToContent()) {
scrollToRightLayout();
} else {
scrollToLeftLayout();
}
}
recycleVelocityTracker();
break;
}
return isBindBasicLayout();
}
/**
* 。 , , 。
*
* @return true, false。
*/
private boolean wantToShowRightLayout() {
return xUp - xDown < 0 && isLeftLayoutVisible;
}
/**
* 。 , , 。
*
* @return true, false。
*/
private boolean wantToShowLeftLayout() {
return xUp - xDown > 0 && !isLeftLayoutVisible;
}
/**
* 。 1/2, SNAP_VELOCITY,
* 。
*
* @return true, false。
*/
private boolean shouldScrollToLeftLayout() {
return xUp - xDown > screenWidth / 2 || getScrollVelocity() > SNAP_VELOCITY;
}
/**
* 。 leftLayoutPadding 1/2,
* SNAP_VELOCITY, 。
*
* @return true, false。
*/
private boolean shouldScrollToContent() {
return xDown - xUp + leftLayoutPadding > screenWidth / 2
|| getScrollVelocity() > SNAP_VELOCITY;
}
/**
* View layout, layout, layout,
* AbsoluteLayout 。
*
* @return View LinearLayout,RelativeLayout,FrameLayout,
* TableLayout true, false。
*/
private boolean isBindBasicLayout() {
if (mBindView == null) {
return false;
}
String viewName = mBindView.getClass().getName();
return viewName.equals(LinearLayout.class.getName())
|| viewName.equals(RelativeLayout.class.getName())
|| viewName.equals(FrameLayout.class.getName())
|| viewName.equals(TableLayout.class.getName());
}
/**
* VelocityTracker , VelocityTracker 。
*
* @param event
*
*/
private void createVelocityTracker(MotionEvent event) {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
}
/**
* View 。
*
* @return , 。
*/
private int getScrollVelocity() {
mVelocityTracker.computeCurrentVelocity(1000);
int velocity = (int) mVelocityTracker.getXVelocity();
return Math.abs(velocity);
}
/**
* VelocityTracker 。
*/
private void recycleVelocityTracker() {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
class ScrollTask extends AsyncTask<Integer, Integer, Integer> {
@Override
protected Integer doInBackground(Integer... speed) {
int leftMargin = leftLayoutParams.leftMargin;
// , , 。
while (true) {
leftMargin = leftMargin + speed[0];
if (leftMargin > rightEdge) {
leftMargin = rightEdge;
break;
}
if (leftMargin < leftEdge) {
leftMargin = leftEdge;
break;
}
publishProgress(leftMargin);
// , 20 , 。
sleep(20);
}
if (speed[0] > 0) {
isLeftLayoutVisible = true;
} else {
isLeftLayoutVisible = false;
}
return leftMargin;
}
@Override
protected void onProgressUpdate(Integer... leftMargin) {
leftLayoutParams.leftMargin = leftMargin[0];
leftLayout.setLayoutParams(leftLayoutParams);
}
@Override
protected void onPostExecute(Integer leftMargin) {
leftLayoutParams.leftMargin = leftMargin;
leftLayout.setLayoutParams(leftLayoutParams);
}
}
/**
* 。
*
* @param millis
* ,
*/
private void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
이곳 을 보면,나 는 모두 가 반드시 이 코드 들 이 매우 익숙 하 다 고 느 낄 것 이 라 고 믿는다.맞 아,기본적으로 이 코드 들 은 이전 글 의 코드 와 크게 다 르 지 않 아.예전 에는 이 코드 들 이 Activity 에 쓰 여 있 었 지만 지금 은 사용자 정의 View 로 이동 했다.이어서 제 가 이전 과 다른 부분 을 설명 하 겠 습 니 다.여기 서 onLayout 방법 을 다시 썼 습 니 다.getChildAt(0)에서 얻 은 레이아웃 을 왼쪽 레이아웃 으로 하고 getChildAt(1)에서 얻 은 레이아웃 을 오른쪽 레이아웃 으로 사용 합 니 다.또한 왼쪽 레이아웃 의 폭 을 화면 너비 에서 left LayoutPadding 을 줄 이 고 오른쪽 레이아웃 의 폭 을 화면 너비 로 다시 정의 합 니 다.그리고 왼쪽 레이아웃 을 화면 밖으로 옮 기 면 오른쪽 레이아웃 만 볼 수 있 습 니 다.따라서 여기 서 우 리 는 Sliding Layout 라 는 레이아웃 을 사용 하 는 전제 조건 을 알 수 있 습 니 다.이 레이아웃 에 두 개의 키 요 소 를 제공 해 야 합 니 다.첫 번 째 요 소 는 왼쪽 레이아웃 으로 화면 에서 이동 하고 두 번 째 요 소 는 오른쪽 레이아웃 으로 화면 에 표 시 됩 니 다.
그리고 set ScrollEvent 방법 을 살 펴 보 겠 습 니 다.이 방법 은 View 를 매개 변수 로 받 은 다음 에 이 View 에 touch 이 벤트 를 연결 합 니 다.이게 무슨 뜻 이 죠?오른쪽 레이아웃 이 LinearLayout 라면 LinearLayout 의 touch 사건 을 감청 하여 왼쪽 레이아웃 의 표시 와 숨 김 을 제어 할 수 있 습 니 다.그러나 오른쪽 레이아웃 의 LinearLayout 에 ListView 가 추가 되 어 있 고 이 ListView 는 LinearLayout 전 체 를 가득 채 우 고 있 습 니 다.이 럴 때 LinearLayout 는 더 이상 터치 되 지 않 을 것 입 니 다.이 럴 때 저 희 는 touch 사건 을 ListView 에 등록 해 야 합 니 다.setScrollEvent 방법 은 등록 인 터 페 이 스 를 제공 하 는 것 입 니 다.touch 이 벤트 는 들 어 오 는 View 에 등 록 됩 니 다.
마지막 으로 낯 선 방법 이 하나 더 있 습 니 다.isBind Basic Layout.이 방법 은 등록 터치 이벤트 의 View 가 네 가지 기본 레이아웃 중 하나 인지 판단 하 는 것 입 니 다.만약 에 true 로 돌아 가지 않 으 면 false 로 돌아 갑 니 다.이 방법 은 전체 SlidingLayout 에서 매우 중요 한 역할 을 합 니 다.주로 onTouch 사건 이 true 로 돌아 가 는 지 false 로 돌아 가 는 지 제어 하 는 데 사 용 됩 니 다.이것 은 레이아웃 에 있 는 View 의 기능 이 사용 가능 한 지 에 영향 을 줄 것 입 니 다.안 드 로 이 드 의 이벤트 퍼 가기 체제 와 관련 되 어 있 기 때문에 내용 이 비교적 많 기 때문에 여기 서 상세 하 게 설명 하지 않 겠 습 니 다.저 는 앞으로 안 드 로 이 드 의 사건 체 제 를 전문 적 으로 글 을 써 서 소개 하 는 것 을 고려 하 겠 습 니 다.기본 레이아웃 이 라면 트 루 로 돌아 가 고,그렇지 않 으 면 false 로 돌아 가 는 것 을 간단하게 기억 하 세 요.
자,우리 의 Sliding Layout 를 다 썼 습 니 다.다음은 기적 을 보 는 순간 입 니 다.Activity 에서 어떻게 1 분 동안 미끄럼 메뉴 기능 을 도입 하 는 지 살 펴 보 겠 습 니 다.
layot 디 렉 터 리 에 있 는 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="fill_parent"
android:orientation="horizontal"
tools:context=".MainActivity" >
<!-- ,orientation -->
<com.example.slide.SlidingLayout
android:id="@+id/slidingLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<!--
, , ,
LinearLayout, RelativeLayout, FrameLayout TableLayout。
, 。 ,
Activity , 。
-->
<RelativeLayout
android:id="@+id/menu"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#00ccff" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="This is menu"
android:textColor="#000000"
android:textSize="28sp" />
</RelativeLayout>
<LinearLayout
android:id="@+id/content"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="@+id/menuButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Menu" />
<ListView
android:id="@+id/contentList"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</ListView>
</LinearLayout>
</com.example.slide.SlidingLayout>
</LinearLayout>
루트 레이아웃 아래 에 사용자 정의 레이아웃 com.example.slide.sliding Layout 를 도입 한 다음 에 그 안에 두 개의 하위 요소,하 나 는 RelativeLayout 와 하 나 는 LinearLayout 를 추가 한 것 을 볼 수 있 습 니 다.Relative Layout 에 간단 해서 TextView 를 추 가 했 습 니 다.LinearLayout 에 우 리 는 버튼 과 ListView 를 추가 했다.그리고 MainActivity 를 프로그램의 주 Activity 로 만 들 거나 열 고 코드 를 추가 합 니 다.
public class MainActivity extends Activity {
/**
* , 。
*/
private SlidingLayout slidingLayout;
/**
* menu , , 。
*/
private Button menuButton;
/**
* content ListView。
*/
private ListView contentListView;
/**
* contentListView 。
*/
private ArrayAdapter<String> contentListAdapter;
/**
* contentListAdapter 。
*/
private String[] contentItems = { "Content Item 1", "Content Item 2", "Content Item 3",
"Content Item 4", "Content Item 5", "Content Item 6", "Content Item 7",
"Content Item 8", "Content Item 9", "Content Item 10", "Content Item 11",
"Content Item 12", "Content Item 13", "Content Item 14", "Content Item 15",
"Content Item 16" };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
slidingLayout = (SlidingLayout) findViewById(R.id.slidingLayout);
menuButton = (Button) findViewById(R.id.menuButton);
contentListView = (ListView) findViewById(R.id.contentList);
contentListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,
contentItems);
contentListView.setAdapter(contentListAdapter);
// contentListView
slidingLayout.setScrollEvent(contentListView);
menuButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// menu ,
if (slidingLayout.isLeftLayoutVisible()) {
slidingLayout.scrollToRightLayout();
} else {
slidingLayout.scrollToLeftLayout();
}
}
});
}
}
상기 코드 의 중점 은 SlidingLayout 의 set ScrollEvent 방법 을 호출 하여 ListView 에 touch 이 벤트 를 등록 하 는 것 입 니 다.동시에 버튼 에 클릭 이 벤트 를 추가 하여 클릭 하여 왼쪽 레이아웃 을 표시 하고 왼쪽 레이아웃 을 숨 기 는 기능 을 실현 합 니 다.마지막 으로 오래된 규칙 입 니 다.AndroidManifest.xml 코드 를 드 립 니 다.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.slide"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="8" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar" >
<activity
android:name="com.example.slide.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
자,이제 운행 합 시다.우선 프로그램 이 열 렸 을 때 오른쪽 레이아웃 이 표 시 됩 니 다.손가락 으로 인터페이스 에서 오른쪽으로 미 끄 러 지면 왼쪽 레이아웃 이 나타 나 는 것 을 볼 수 있다.왼쪽 레이아웃 이 완전히 표 시 될 때 효과 도 는 다음 과 같 습 니 다.
그 밖 에 Menu 단 추 를 누 르 면 왼쪽 레이아웃 의 표시 와 숨 김 을 제어 할 수 있 으 니 직접 시도 해 보 세 요.
사용자 정의 레이아웃 을 사용 하면 임의의 Activity 에 슬라이딩 메뉴 기능 을 간단하게 추가 할 수 있 습 니 다.아무리 많은 Activity 가 있어 도 두려워 하지 않 아 도 됩 니 다.1 분 동안 슬라이딩 메뉴 를 도입 하 는 것 이 좋 습 니 다.
다시 한 번 정리 해 보 세 요.Activity 에 미끄럼 메뉴 기능 을 추가 하려 면 두 단계 만 필요 합 니 다.
1.Acitivty 의 layot 에 사용자 정의 레이아웃 을 도입 하고 이 레이아웃 에 두 개의 직접 하위 요 소 를 추가 합 니 다.
2.Activity 에서 set ScrollEvent 방법 을 통 해 View 에 touch 이 벤트 를 등록 합 니 다.
자,오늘 설명 은 여기 서 마 치 겠 습 니 다.궁금 한 분 은 아래 에 메 시 지 를 남 겨 주세요.
원본 다운로드,여 기 를 클릭 하 세 요.
보충:
이 글 은 비교적 일찍 썼 기 때문에 그때 쓴 미끄럼 메뉴 에 아직도 많은 문제 가 존재 했다.나 는 그 후에 위의 코드 를 많이 바 꾸 었 고 수정판 의 미끄럼 메뉴 를 만 들 었 다.이 버 전 은 주로 다음 과 같은 내용 을 수정 했다.
1.미끄럼 방식 을 커버 형 으로 바 꾸 었 습 니 다.
2.ListView 를 위아래 로 굴 릴 때 메뉴 가 쉽게 미 끄 러 지지 않 습 니 다.
3.미 끄 러 지고 있 을 때 내용 레이아웃 에 있 는 이 벤트 를 차단 합 니 다.
4.메뉴 레이아웃 이 표 시 될 때 오른쪽 에 있 는 내용 레이아웃 을 클릭 하면 메뉴 를 숨 길 수 있 습 니 다.
5.프로그램 을 처음 열 었 을 때 메뉴 가 잠시 표시 되 고 순식간에 사라 질 수 있 는 bug 를 복원 합 니 다.
수정판 원본 다운로드,여 기 를 클릭 하 세 요.
또한 양 방향 슬라이딩 메뉴 에 관심 이 있 으 신 분 은 돌려 보 세 요. Android 에서 양 방향 슬라이딩 효 과 를 실현 하 는 인 스 턴 스 코드
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.