tôi đã có yêu cầu tương tự mà làm cho hình ảnh động bố trí như ứng dụng Facebook. Để làm điều đó, tôi đã tạo một ViewGroup tùy chỉnh (được gọi là AnimationLayout). Hy vọng các mã giúp.
AnimationLayout cần hai con: Thanh bên và Nội dung. (bằng cách chỉ định @ + id/animation_sidebar và @ + id/animation_content cho tương ứng)
Đây là bố cục xml, SideBar có nút và chế độ xem danh sách. Nội dung có một textview và một nút (nó liên kết với một chức năng gọi lại).
<?xml version="1.0" encoding="utf-8"?>
<org.zeroxlab.widget.AnimationLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/animation_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:id="@+id/animation_sidebar"
android:layout_width="200dip"
android:layout_height="match_parent"
android:background="#550000"
android:orientation="vertical"
>
<Button
android:id="@+id/button_test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sidebar Button"
/>
<ListView
android:id="@+id/sidebar_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
<LinearLayout
android:id="@+id/animation_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#003300"
android:clickable="true"
>
<Button android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Content Button"
android:onClick="onClickButton"
/>
<TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="The Answer to Life, the Universe, and Everything -- is 42"
/>
</LinearLayout>
</org.zeroxlab.widget.AnimationLayout>
Đây là hoạt động thử nghiệm. Nó khởi tạo một ListView và gán chính nó như là một Listener để AnimationLayout.
package test.julian.hello;
import org.zeroxlab.widget.AnimationLayout;
import android.app.Activity;
import android.app.ActivityManager;
import android.os.Bundle;
import android.widget.*;
import android.util.Log;
import android.view.View;
public class HelloAndroid extends Activity implements AnimationLayout.Listener {
ListView mList;
AnimationLayout mLayout;
String[] mStrings = {"a", "b", "c", "d", "e", "f", "g"};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.app_layout);
mLayout = (AnimationLayout) findViewById(R.id.animation_layout);
mLayout.setListener(this);
mList = (ListView) findViewById(R.id.sidebar_list);
mList.setAdapter(
new ArrayAdapter<String>(
this, android.R.layout.simple_list_item_multiple_choice
, mStrings));
mList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
}
public void onClickButton(View v) {
mLayout.toggleSidebar();
}
@Override
public void onSidebarOpened() {
Log.d("Foo", "opened");
}
@Override
public void onSidebarClosed() {
Log.d("Foo", "opened");
}
@Override
public boolean onContentTouchedWhenOpening() {
Log.d("Foo", "going to close sidebar");
mLayout.closeSidebar();
return true;
}
}
Đây là AnimationLayout.
/*
* Copyright (C) 2012 0xlab - http://0xlab.org/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Authored by Julian Chu <walkingice AT 0xlab.org>
*/
package org.zeroxlab.widget;
import test.julian.hello.R;
import android.content.Context;
import android.util.AttributeSet;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
public class AnimationLayout extends ViewGroup {
public final static int DURATION = 500;
protected boolean mOpened;
protected View mSidebar;
protected View mContent;
protected int mSidebarWidth = 150; // by default
protected Animation mAnimation;
protected OpenListener mOpenListener;
protected CloseListener mCloseListener;
protected Listener mListener;
protected boolean mPressed = false;
public AnimationLayout(Context context) {
this(context, null);
}
public AnimationLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void onFinishInflate() {
super.onFinishInflate();
mSidebar = findViewById(R.id.animation_sidebar);
mContent = findViewById(R.id.animation_content);
if (mSidebar == null) {
throw new NullPointerException("no view id = animation_sidebar");
}
if (mContent == null) {
throw new NullPointerException("no view id = animation_content");
}
mOpenListener = new OpenListener(mSidebar, mContent);
mCloseListener = new CloseListener(mSidebar, mContent);
}
@Override
public void onLayout(boolean changed, int l, int t, int r, int b) {
/* the title bar assign top padding, drop it */
mSidebar.layout(l, 0, l + mSidebarWidth, 0 + mSidebar.getMeasuredHeight());
if (mOpened) {
mContent.layout(l + mSidebarWidth, 0, r + mSidebarWidth, b);
} else {
mContent.layout(l, 0, r, b);
}
}
@Override
public void onMeasure(int w, int h) {
super.onMeasure(w, h);
super.measureChildren(w, h);
mSidebarWidth = mSidebar.getMeasuredWidth();
}
@Override
protected void measureChild(View child, int parentWSpec, int parentHSpec) {
/* the max width of Sidebar is 90% of Parent */
if (child == mSidebar) {
int mode = MeasureSpec.getMode(parentWSpec);
int width = (int)(getMeasuredWidth() * 0.9);
super.measureChild(child, MeasureSpec.makeMeasureSpec(width, mode), parentHSpec);
} else {
super.measureChild(child, parentWSpec, parentHSpec);
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (!isOpening()) {
return false;
}
int action = ev.getAction();
if (action != MotionEvent.ACTION_UP
&& action != MotionEvent.ACTION_DOWN) {
return false;
}
/* if user press and release both on Content while
* sidebar is opening, call listener. otherwise, pass
* the event to child. */
int x = (int)ev.getX();
int y = (int)ev.getY();
if (mContent.getLeft() < x
&& mContent.getRight() > x
&& mContent.getTop() < y
&& mContent.getBottom() > y) {
if (action == MotionEvent.ACTION_DOWN) {
mPressed = true;
}
if (mPressed
&& action == MotionEvent.ACTION_UP
&& mListener != null) {
mPressed = false;
return mListener.onContentTouchedWhenOpening();
}
} else {
mPressed = false;
}
return false;
}
public void setListener(Listener l) {
mListener = l;
}
/* to see if the Sidebar is visible */
public boolean isOpening() {
return mOpened;
}
public void toggleSidebar() {
if (mContent.getAnimation() != null) {
return;
}
if (mOpened) {
/* opened, make close animation*/
mAnimation = new TranslateAnimation(0, -mSidebarWidth, 0, 0);
mAnimation.setAnimationListener(mCloseListener);
} else {
/* not opened, make open animation */
mAnimation = new TranslateAnimation(0, mSidebarWidth, 0, 0);
mAnimation.setAnimationListener(mOpenListener);
}
mAnimation.setDuration(DURATION);
mAnimation.setFillAfter(true);
mAnimation.setFillEnabled(true);
mContent.startAnimation(mAnimation);
}
public void openSidebar() {
if (!mOpened) {
toggleSidebar();
}
}
public void closeSidebar() {
if (mOpened) {
toggleSidebar();
}
}
class OpenListener implements Animation.AnimationListener {
View iSidebar;
View iContent;
OpenListener(View sidebar, View content) {
iSidebar = sidebar;
iContent = content;
}
public void onAnimationRepeat(Animation animation) {
}
public void onAnimationStart(Animation animation) {
iSidebar.setVisibility(View.VISIBLE);
}
public void onAnimationEnd(Animation animation) {
iContent.clearAnimation();
mOpened = !mOpened;
requestLayout();
if (mListener != null) {
mListener.onSidebarOpened();
}
}
}
class CloseListener implements Animation.AnimationListener {
View iSidebar;
View iContent;
CloseListener(View sidebar, View content) {
iSidebar = sidebar;
iContent = content;
}
public void onAnimationRepeat(Animation animation) {
}
public void onAnimationStart(Animation animation) {
}
public void onAnimationEnd(Animation animation) {
iContent.clearAnimation();
iSidebar.setVisibility(View.INVISIBLE);
mOpened = !mOpened;
requestLayout();
if (mListener != null) {
mListener.onSidebarClosed();
}
}
}
public interface Listener {
public void onSidebarOpened();
public void onSidebarClosed();
public boolean onContentTouchedWhenOpening();
}
}
Khi SideBar đóng, có vẻ như thế này.

Khi SideBar mở ra, nó trông như thế này.

làm việc tốt ... nhưng cách chọn menu bên trái có thể cho tôi biết .. tôi cũng có thể mở mục cụ thể. –
Bạn có ý nghĩa cách chọn một mục trong listView không? như trong trường hợp của tôi là Android, Blackberry, iPhone? –
có mà item..select bất kỳ mục cụ thể hiển thị nó trên màn hình menu .. –