Я действительно хочу реализовать это (боковую навигацию) в моем собственном приложении, кто-нибудь знает, как Google это удалось?
Кажется, они отодвинули текущее окно в сторону и добавили собственную навигацию.
Я действительно хочу реализовать это (боковую навигацию) в моем собственном приложении, кто-нибудь знает, как Google это удалось?
Кажется, они отодвинули текущее окно в сторону и добавили собственную навигацию.
Ответы:
Фактически, способ сделать это. Даже без реализации собственного ActionBar
.
Просто взгляните на hierachyviewer
! (Находится в каталоге инструментов)
Там то DecorView
, и кот LinearLayout
в детстве. Он LinearLayout
содержит как тот, так ActionBar
и другой контент. Итак, вы можете просто применить FrameLayout.LayoutParams
к нему LinearLayout
немного места и таким образом освободить место с левой стороны. Затем вы можете заполнить это пространство своим меню-ListView и наложить другой контент с помощью FrameLayout, который при щелчке по нему сворачивает меню. Итак, вот код:
Во-первых, класс для сворачивания / разворачивания (SlideMenu.java):
package your.cool.app;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.animation.TranslateAnimation;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
public class SlideMenu {
//just a simple adapter
public static class SlideMenuAdapter extends ArrayAdapter<SlideMenu.SlideMenuAdapter.MenuDesc> {
Activity act;
SlideMenu.SlideMenuAdapter.MenuDesc[] items;
class MenuItem {
public TextView label;
public ImageView icon;
}
static class MenuDesc {
public int icon;
public String label;
}
public SlideMenuAdapter(Activity act, SlideMenu.SlideMenuAdapter.MenuDesc[] items) {
super(act, R.id.menu_label, items);
this.act = act;
this.items = items;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
if (rowView == null) {
LayoutInflater inflater = act.getLayoutInflater();
rowView = inflater.inflate(R.layout.menu_listitem, null);
MenuItem viewHolder = new MenuItem();
viewHolder.label = (TextView) rowView.findViewById(R.id.menu_label);
viewHolder.icon = (ImageView) rowView.findViewById(R.id.menu_icon);
rowView.setTag(viewHolder);
}
MenuItem holder = (MenuItem) rowView.getTag();
String s = items[position].label;
holder.label.setText(s);
holder.icon.setImageResource(items[position].icon);
return rowView;
}
}
private static boolean menuShown = false;
private static View menu;
private static LinearLayout content;
private static FrameLayout parent;
private static int menuSize;
private static int statusHeight = 0;
private Activity act;
SlideMenu(Activity act) {
this.act = act;
}
//call this in your onCreate() for screen rotation
public void checkEnabled() {
if(menuShown)
this.show(false);
}
public void show() {
//get the height of the status bar
if(statusHeight == 0) {
Rect rectgle = new Rect();
Window window = act.getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
statusHeight = rectgle.top;
}
this.show(true);
}
public void show(boolean animate) {
menuSize = Functions.dpToPx(250, act);
content = ((LinearLayout) act.findViewById(android.R.id.content).getParent());
FrameLayout.LayoutParams parm = (FrameLayout.LayoutParams) content.getLayoutParams();
parm.setMargins(menuSize, 0, -menuSize, 0);
content.setLayoutParams(parm);
//animation for smooth slide-out
TranslateAnimation ta = new TranslateAnimation(-menuSize, 0, 0, 0);
ta.setDuration(500);
if(animate)
content.startAnimation(ta);
parent = (FrameLayout) content.getParent();
LayoutInflater inflater = (LayoutInflater) act.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
menu = inflater.inflate(R.layout.menu, null);
FrameLayout.LayoutParams lays = new FrameLayout.LayoutParams(-1, -1, 3);
lays.setMargins(0,statusHeight, 0, 0);
menu.setLayoutParams(lays);
parent.addView(menu);
ListView list = (ListView) act.findViewById(R.id.menu_listview);
list.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//handle your menu-click
}
});
if(animate)
menu.startAnimation(ta);
menu.findViewById(R.id.overlay).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
SlideMenu.this.hide();
}
});
Functions.enableDisableViewGroup((LinearLayout) parent.findViewById(android.R.id.content).getParent(), false);
((ExtendedViewPager) act.findViewById(R.id.viewpager)).setPagingEnabled(false);
((ExtendedPagerTabStrip) act.findViewById(R.id.viewpager_tabs)).setNavEnabled(false);
menuShown = true;
this.fill();
}
public void fill() {
ListView list = (ListView) act.findViewById(R.id.menu_listview);
SlideMenuAdapter.MenuDesc[] items = new SlideMenuAdapter.MenuDesc[5];
//fill the menu-items here
SlideMenuAdapter adap = new SlideMenuAdapter(act, items);
list.setAdapter(adap);
}
public void hide() {
TranslateAnimation ta = new TranslateAnimation(0, -menuSize, 0, 0);
ta.setDuration(500);
menu.startAnimation(ta);
parent.removeView(menu);
TranslateAnimation tra = new TranslateAnimation(menuSize, 0, 0, 0);
tra.setDuration(500);
content.startAnimation(tra);
FrameLayout.LayoutParams parm = (FrameLayout.LayoutParams) content.getLayoutParams();
parm.setMargins(0, 0, 0, 0);
content.setLayoutParams(parm);
Functions.enableDisableViewGroup((LinearLayout) parent.findViewById(android.R.id.content).getParent(), true);
((ExtendedViewPager) act.findViewById(R.id.viewpager)).setPagingEnabled(true);
((ExtendedPagerTabStrip) act.findViewById(R.id.viewpager_tabs)).setNavEnabled(true);
menuShown = false;
}
}
Некоторые вспомогательные методы (для меня в static Functions.java):
public static int dpToPx(int dp, Context ctx) {
Resources r = ctx.getResources();
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics());
}
//originally: http://stackoverflow.com/questions/5418510/disable-the-touch-events-for-all-the-views
//modified for the needs here
public static void enableDisableViewGroup(ViewGroup viewGroup, boolean enabled) {
int childCount = viewGroup.getChildCount();
for (int i = 0; i < childCount; i++) {
View view = viewGroup.getChildAt(i);
if(view.isFocusable())
view.setEnabled(enabled);
if (view instanceof ViewGroup) {
enableDisableViewGroup((ViewGroup) view, enabled);
} else if (view instanceof ListView) {
if(view.isFocusable())
view.setEnabled(enabled);
ListView listView = (ListView) view;
int listChildCount = listView.getChildCount();
for (int j = 0; j < listChildCount; j++) {
if(view.isFocusable())
listView.getChildAt(j).setEnabled(false);
}
}
}
}
Затем макеты:
Макет меню (res / layout / menu.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:orientation="vertical"
android:layout_height="fill_parent"
android:layout_width="250dip"
android:background="@color/darkblack">
<ListView
android:id="@+id/menu_listview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:divider="@color/dividerblack"
android:dividerHeight="2dip" />
</LinearLayout>
<FrameLayout
android:id="@+id/overlay"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
</LinearLayout>
Расположение элементов списка (res / layout / menu_listitem.xml):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="fill_parent" >
<ImageView
android:id="@+id/menu_icon"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginRight="5dip"
android:layout_marginLeft="10dip"
android:layout_marginTop="10dip"
android:layout_marginBottom="10dip" />
<TextView
android:id="@+id/menu_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:textSize="24dp"
android:layout_marginTop="10dip"
android:layout_marginBottom="10dip" />
</LinearLayout>
Как это использовать:
В вашем onCreate()
:
private SlideMenu slidemenu;
@Override
public void onCreate(Bundle savedInstanceState) {
//your onCreate code
slidemenu = new SlideMenu(this);
slidemenu.checkEnabled();
}
В обработчике домашней кнопки ActionBar:
slidemenu.show();
Это оно!
А теперь небольшой снимок экрана в действии:
Насколько я знаю, работает. Если у вас возникнут проблемы или мои объяснения непонятны, свяжитесь со мной!
РЕДАКТИРОВАТЬ: ExtendedViewPager
& ExtendedPagerStrip
:
ExtendedViewPager:
package your.cool.app;
//source: http://blog.svpino.com/2011/08/disabling-pagingswiping-on-android.html
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
public class ExtendedViewPager extends ViewPager {
private boolean enabled;
public ExtendedViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.enabled = true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onTouchEvent(event);
}
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}
public void setPagingEnabled(boolean enabled) {
this.enabled = enabled;
}
}
ExtendedPagerTabStrip:
package your.cool.app;
//source: http://blog.svpino.com/2011/08/disabling-pagingswiping-on-android.html
import android.content.Context;
import android.support.v4.view.PagerTabStrip;
import android.util.AttributeSet;
import android.view.MotionEvent;
public class ExtendedPagerTabStrip extends PagerTabStrip {
private boolean enabled;
public ExtendedPagerTabStrip(Context context, AttributeSet attrs) {
super(context, attrs);
this.enabled = true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onTouchEvent(event);
}
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}
public void setNavEnabled(boolean enabled) {
this.enabled = enabled;
}
}
Я использую это SlideMenu
для деятельности с ViewPager
с PagerTabStrip
вкладками , как Talk, рынок и т.д. Вы не можете отключить эти взгляды в легком пути, так что эти два класса выше только продлить их , чтобы остановить onTouch
событие , когда отключены.
Есть несколько попыток сделать это, однако мне еще предстоит найти библиотеку или исходный код о том, как успешно реализовать это с помощью панели действий на всех уровнях api. Одна многообещающая библиотека здесь
https://github.com/jfeinstein10/SlidingMenu
вот видео примера приложения .
вот ссылка на приложение Google Play .
Это работает с ActionbarSherlock. Вам нужно будет собрать библиотеку SlidingMenu с ABS, чтобы она заработала. Работает и отлично смотрится!
Сделал обзор исходной реализации и добавил синтаксический анализ XML, а также autodetection
возможного присутствия actionbar
, поэтому он работает как с родной, так и с панелью действий поддержки, такой как ActionBarSherlock
.
Теперь все это представляет собой проект библиотеки вместе с примером приложения и описан в Sliding Menu для Android. Спасибо scirocco за первоначальную идею и код!
Если вы используете уровень API выше 11, вы можете использовать гораздо более простой подход, основанный на ответе @Scirocco.
// get content parent that is basically the whole
// app screen (viewed from hierarchy viewer)
final LinearLayout content =
(LinearLayout) findViewById(android.R.id.content).getParent();
// make new value animator with range from 0 to 1
final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
// set custom duration
animator.setDuration(500);
// on update is called for every value in the
// given range in time frame defined by the duration
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
// get the current value
float value = ((Float) (animation.getAnimatedValue())).floatValue();
// translate by that value, minus means translate left
content.setTranslationX(-250 * value);
}
});
// start the animator
animator.start();
// make or inflate custom view for test purposes
Button textView = new Button(this);
textView.setText("TestButton");
// add it to the frame layout that is the parent of the content on position 0
FrameLayout parent = (FrameLayout) content.getParent();
parent.addView(textView, 0);
Идея заключается в том, чтобы использовать ValueAnimator
это преобразование, а не просто анимацию основного макета с помощью панели действий, чтобы вы могли взаимодействовать с расширенным представлением, которое хотите использовать в качестве скользящей панели. Вы должны заменить жестко запрограммированные значения чем-то, что будет полезно для вашего приложения.
Надеюсь, это поможет :)
Ну, в настоящее время я работаю над проектом и наткнулся на скользящее меню, я погуглил, но очень разочаровался, увидев, что никто не дал какой-то фрагмент кода или намек, как начать создавать скользящее меню, но каждый дал ссылку на некоторые проекты / библиотеки github, я решил сделать это сам и, наконец, у меня есть собственное готовое скользящее меню ...
Я потратил на это два дня
1. о создании анимации скольжения
2. на то, чтобы он работал со всеми разрешениями экрана
Это действительно легко и просто, как только вы получите некоторое представление об анимации , я кое-где читал, не имеет смысла изобретать колесо (люди, которые ссылаются на исходный код github скользящего меню), но я считаю, что вы должны хотя бы один раз попробуйте сделать свой собственный, чтобы понять, как он на самом деле работает и функционирует: P
Итак, это картина того, как будет работать мое скользящее меню
1.Find.xml //later in the code it will be refer as findLayout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:id="@+id/find_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="60dp"
android:padding="2dp"
android:background="@drawable/main_header">
<Button
android:id="@+id/filter"
android:layout_width="40dp"
android:layout_height="30dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:background="@drawable/filter_button" />
<TextView
android:id="@+id/city"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/filter"
android:layout_marginLeft="20dp"
android:layout_marginTop="3dp"
android:text="Islamabad"
android:textSize="22sp"
android:textStyle="bold"
android:textColor="@android:color/primary_text_dark"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/city"
android:layout_alignLeft="@+id/city">
<TextView
android:id="@+id/interested_in"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="Men and Women"
android:textSize="12sp"
android:textColor="@android:color/primary_text_dark"/>
<ImageView
android:id="@+id/separator"
android:layout_width="2dp"
android:layout_height="18dp"
android:layout_toRightOf="@+id/interested_in"
android:layout_marginLeft="4dp"
android:src="@drawable/separator_1"
android:layout_centerVertical="true" />
<TextView
android:id="@+id/age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_toRightOf="@+id/separator"
android:layout_centerVertical="true"
android:text="18-24 years"
android:textSize="12sp"
android:textColor="@android:color/primary_text_dark"/>
<ImageView
android:id="@+id/separator_1"
android:layout_width="2dp"
android:layout_height="18dp"
android:layout_toRightOf="@+id/age"
android:layout_marginLeft="4dp"
android:src="@drawable/separator_1"
android:layout_centerVertical="true" />
<TextView
android:id="@+id/distance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_toRightOf="@+id/separator_1"
android:layout_centerVertical="true"
android:text=">30km"
android:textSize="12sp"
android:textColor="@android:color/primary_text_dark" />
</RelativeLayout>
</RelativeLayout>
<GridView
android:id="@+id/users_grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/header"
android:numColumns="4">
</GridView>
</RelativeLayout>
<include
layout="@layout/filter"/> //here i included the filter.xml, which is on top of find.xml layout and is initially invisible
</RelativeLayout>
2.Filter.xml //later in code refer as FilterLayout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/filter_layout"
android:visibility="invisible"
android:layout_width="260dp"
android:layout_height="match_parent"
android:background="@drawable/grey_bg" >
<ImageView
android:id="@+id/profile_pic"
android:layout_width="match_parent"
android:layout_height="220dp"
android:src="@drawable/pic"/>
<RelativeLayout
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="55dp"
android:paddingLeft="10dp"
android:paddingTop="5dp"
android:layout_below="@+id/profile_pic"
android:background="@drawable/light_blue_header">
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:text="Raja Babar"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/primary_text_dark"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/name"
android:layout_alignLeft="@+id/name">
<TextView
android:id="@+id/gender"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="Male"
android:textSize="12sp"
android:textColor="@android:color/primary_text_dark" />
<ImageView
android:id="@+id/seperator"
android:layout_width="2dp"
android:layout_height="20dp"
android:layout_toRightOf="@+id/gender"
android:layout_marginLeft="5dp"
android:src="@drawable/separator_1"
android:layout_centerVertical="true" />
<TextView
android:id="@+id/age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/seperator"
android:layout_marginLeft="5dp"
android:layout_centerVertical="true"
android:text="22 years"
android:textSize="12sp"
android:textColor="@android:color/primary_text_dark" />
</RelativeLayout>
</RelativeLayout>
<ScrollView
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_below="@+id/header"
android:layout_marginTop="15dp"
android:layout_centerHorizontal="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/filter_options"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/filter_options"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/primary_text_light"/>
<RelativeLayout
android:id="@+id/interested_in_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:paddingRight="40dp"
android:layout_below="@+id/filter_options"
android:background="@drawable/interested_in_field">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="@string/gender"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/primary_text_light"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="@string/women_men"
android:textSize="18sp"
android:textColor="#33b9cd" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/age_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:paddingRight="40dp"
android:layout_below="@+id/interested_in_layout"
android:background="@drawable/age_field_1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="@string/age"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/primary_text_light"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="18-24 years"
android:textSize="18sp"
android:textColor="#33b9cd"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:paddingRight="40dp"
android:layout_below="@+id/age_layout"
android:background="@drawable/distance_field">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="@string/distance"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/primary_text_light"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text=">30km"
android:textSize="18sp"
android:textColor="#33b9cd"/>
</RelativeLayout>
</RelativeLayout>
</ScrollView>
</RelativeLayout>
В find.xml я изначально включил filter.xml, который невидим
Теперь FilterAnimation.java
package matchat.helpers;
import com.s3.matchat.R;
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.RelativeLayout;
public class FilterAnimation implements AnimationListener
{
Context context;
RelativeLayout filterLayout, otherLayout;
private Animation filterSlideIn, filterSlideOut, otherSlideIn, otherSlideOut;
private static int otherLayoutWidth, otherLayoutHeight;
private boolean isOtherSlideOut = false;
private int deviceWidth;
private int margin;
public FilterAnimation(Context context)
{
this.context = context;
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
deviceWidth = displayMetrics.widthPixels; // as my animation is x-axis related so i gets the device width and will use that width,so that this sliding menu will work fine in all screen resolutions
}
public void initializeFilterAnimations(RelativeLayout filterLayout)
{
this.filterLayout = filterLayout;
filterSlideIn = AnimationUtils.loadAnimation(context, R.anim.filter_slide_in);
filterSlideOut = AnimationUtils.loadAnimation(context, R.anim.filter_slide_out);
}
public void initializeOtherAnimations(RelativeLayout otherLayout)
{
this.otherLayout = otherLayout;
otherLayoutWidth = otherLayout.getWidth();
otherLayoutHeight = otherLayout.getHeight();
otherSlideIn = AnimationUtils.loadAnimation(context, R.anim.other_slide_in);
otherSlideIn.setAnimationListener(this);
otherSlideOut = AnimationUtils.loadAnimation(context, R.anim.other_slide_out);
otherSlideOut.setAnimationListener(this);
}
public void toggleSliding()
{
if(isOtherSlideOut) //check if findLayout is already slided out so get so animate it back to initial position
{
filterLayout.startAnimation(filterSlideOut);
filterLayout.setVisibility(View.INVISIBLE);
otherLayout.startAnimation(otherSlideIn);
}
else //slide findLayout Out and filterLayout In
{
otherLayout.startAnimation(otherSlideOut);
filterLayout.setVisibility(View.VISIBLE);
filterLayout.startAnimation(filterSlideIn);
}
}
@Override
public void onAnimationEnd(Animation animation)
{
if(isOtherSlideOut) //Now here we will actually move our view to the new position,because animations just move the pixels not the view
{
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(otherLayoutWidth, otherLayoutHeight);
otherLayout.setLayoutParams(params);
isOtherSlideOut = false;
}
else
{
margin = (deviceWidth * 80) / 100; //here im coverting device percentage width into pixels, in my other_slide_in.xml or other_slide_out.xml you can see that i have set the android:toXDelta="80%",so it means the layout will move to 80% of the device screen,to work across all screens i have converted percentage width into pixels and then used it
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(otherLayoutWidth, otherLayoutHeight);
params.leftMargin = margin;
params.rightMargin = -margin; //same margin from right side (negavite) so that our layout won't get shrink
otherLayout.setLayoutParams(params);
isOtherSlideOut = true;
dimOtherLayout();
}
}
@Override
public void onAnimationRepeat(Animation animation)
{
}
@Override
public void onAnimationStart(Animation animation)
{
}
private void dimOtherLayout()
{
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.5f);
alphaAnimation.setFillAfter(true);
otherLayout.startAnimation(alphaAnimation);
}
}
Теперь Find.java
package main.matchat.activities;
import matchat.helpers.FilterAnimation;
import com.s3.matchat.R;
import android.app.Activity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.View.OnClickListener;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.Button;
import android.widget.RelativeLayout;
public class Find extends Activity implements OnClickListener
{
RelativeLayout filterLayout, findLayout;
Button btFilter;
FilterAnimation filterAnimation;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.find);
filterLayout = (RelativeLayout)findViewById(R.id.filter_layout);
findLayout = (RelativeLayout)findViewById(R.id.find_layout);
btFilter = (Button)findViewById(R.id.filter);
btFilter.setOnClickListener(this);
filterAnimation = new FilterAnimation(this);
initializeAnimations();
}
private void initializeAnimations()
{ //Setting GlobolLayoutListener,when layout is completely set this function will get called and we can have our layout onbject with correct width & height,else if you simply try to get width/height of your layout in onCreate it will return 0
final ViewTreeObserver filterObserver = filterLayout.getViewTreeObserver();
filterObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
@Override
public void onGlobalLayout()
{
filterLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
int deviceWidth = displayMetrics.widthPixels;
int filterLayoutWidth = (deviceWidth * 80) / 100; //here im coverting device percentage width into pixels, in my other_slide_in.xml or other_slide_out.xml you can see that i have set the android:toXDelta="80%",so it means the layout will move to 80% of the device screen,to work across all screens i have converted percentage width into pixels and then used it
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(filterLayoutWidth, RelativeLayout.LayoutParams.MATCH_PARENT);
filterLayout.setLayoutParams(params);//here im setting the layout params for my filter.xml because its has width 260 dp,so work it across all screen i first make layout adjustments so that it work across all screens resolution
filterAnimation.initializeFilterAnimations(filterLayout);
}
});
final ViewTreeObserver findObserver = findLayout.getViewTreeObserver();
findObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
@Override
public void onGlobalLayout()
{
findLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
filterAnimation.initializeOtherAnimations(findLayout);
}
});
}
@Override
public void onClick(View v)
{
int id = v.getId();
switch(id)
{
case R.id.filter:
filterAnimation.toggleSliding();
break;
}
}
}
Вот анимации res / anim
1.filter_slide_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator">
<translate
android:fromXDelta="-100%"
android:toXDelta="0%"
android:duration="1000"
android:fillEnabled="true" />
</set>
2.filter_slide_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator">
<translate
android:fromXDelta="0%"
android:toXDelta="-100%"
android:duration="1000"/>
</set>
3.other_slide_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator" >
<translate
android:fromXDelta="0%"
android:toXDelta="-80%"
android:duration="1000"
android:fillEnabled="true"/>
</set>
4.other_slide_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator">
<translate
android:fromXDelta="0%"
android:toXDelta="80%"
android:duration="1000"
android:fillEnabled="true"/>
</set>
Вот и полное рабочее и функциональное скользящее меню, и вы можете настроить его в соответствии со своими требованиями, если у кого-то все еще есть проблемы с настройкой, не стесняйтесь спрашивать, я с удовольствием помогу вам :)
Я создал свое собственное решение для сдвига представления и открытия меню внизу, так как многие другие решения не работали в более старых версиях Android или не имели надлежащих инструкций о том, как заставить его работать.
Мое решение имеет следующие особенности:
В решении используется настраиваемый макет, называемый SlidingMenuLayout, в который вы должны добавить 2 представления. Первое добавленное вами представление - это меню, второе - главное представление.
Самый простой способ добавить макет в существующий проект - переопределить setContentView()
метод Activity :
@Override
public void setContentView(View view) {
SlidingMenuLayout layout = new SlidingMenuLayout(this);
layout.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
0.0F));
layout.addView(new MenuView(this));
layout.addView(view);
super.setContentView(layout);
}
В этом примере MenuView
это представление, которое фактически отображает меню. Реализовать это представление зависит от вас.
Наконец, вы можете добавить кнопку (обычно в верхнем левом углу основного представления), которая вызывает openMenu()
или closeMenu()
в макете, в зависимости от ситуации.
Код для SlidingMenuLayout
находится на странице проекта GitHub .
Для тех из вас, кто использует библиотеку SlidingMenu ( https://github.com/jfeinstein10/SlidingMenu ), есть способ подключить ее, и, похоже, это работает! С помощью @Scirocco поместите это в свое onCreate
действие:
ViewGroup decorView = (ViewGroup) getWindow().getDecorView();
mSlidingMenu = new SlidingMenu(this);
ViewGroup mainContent = (ViewGroup) decorView.getChildAt(0);
decorView.removeView(mainContent);
mSlidingMenu.setContent(mainContent);
decorView.addView(mSlidingMenu);
mMenu = (LinearLayout) View.inflate(this, R.layout.menuview, null);
mSlidingMenu.setMenu(mMenu);
mSlidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
mSlidingMenu.setBehindOffsetRes(R.dimen.slidingmenu_offset);
в основном то, что он делает, заменяет вид linearlayout
in decor на slidingmenu
вместо этого.
Примечание: я проверил его только слегка, но, похоже, он работает.
public class ImprovedSlidingPaneLayout extends SlidingPaneLayout {
Context context;
FrameLayout left;
FrameLayout right;
Boolean canOpen = true;
public ImprovedSlidingPaneLayout(Context context) {
super(context);
this.context = context;
this.left = new FrameLayout(context);
this.right = new FrameLayout(context);
this.addView(left);
this.addView(right);
}
public ImprovedSlidingPaneLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (canOpen)
return super.onInterceptTouchEvent(ev);
else
return false;
}
public ImprovedSlidingPaneLayout canOpen(Boolean canOpen) {
this.canOpen = canOpen;
return this;
}
public ImprovedSlidingPaneLayout makeActionBarSlide(Window window){
ViewGroup decorView = (ViewGroup) window.getDecorView();
ViewGroup mainContent = (ViewGroup) decorView.getChildAt(0);
decorView.removeView(mainContent);
setContentView(mainContent);
decorView.addView(this);
return this;
}
public ImprovedSlidingPaneLayout setMenuView(View view){
if((left.getChildCount()== 1)){
left.removeView(left.getChildAt(0));
}
left.addView(view);
return this;
}
public ImprovedSlidingPaneLayout setContentView(View view){
if((right.getChildCount()== 1)){
right.removeView(right.getChildAt(0));
}
right.addView(view);
return this;
}
public ImprovedSlidingPaneLayout setMenuWidth(int width){
left.setLayoutParams(new SlidingPaneLayout.LayoutParams(width, ViewGroup.LayoutParams.MATCH_PARENT));
return this;
}
}
это мой класс расширяется SlidingPaneLayout
. Может скользить с помощью actio