Google จัดการกับสิ่งนี้ได้อย่างไร Slide ActionBar ในแอปพลิเคชัน Android


118

ฉันต้องการใช้สิ่งนี้ (การนำทางด้านข้าง) ในแอปของฉันเองมีใครรู้บ้างว่า Google จัดการกับสิ่งนี้ได้อย่างไร

ดูเหมือนว่าพวกเขาจะดึงหน้าต่างปัจจุบันออกด้านข้างและนำทางบินเข้ามาเอง


ฉันเดาว่าพวกเขามีเลย์เอาต์ที่มี 2 เลย์เอาต์: 1 เป็นแอพหลักและอีกอันคือแถบด้านข้าง เมื่อเปิดใช้งานแถบด้านข้างมันจะดันเค้าโครงแอพหลักออกไปด้านข้าง นี่เป็นเพียงการคาดเดาดังนั้นฉันจึงไม่ได้ใส่เป็นคำตอบ
Eric

1
ฉันเชื่อว่ามีคนถามเรื่องนี้ในคำถาม & คำตอบหลังจากพูดคุยเรื่อง "มีอะไรใหม่ใน Android" ที่ IO เวอร์ชันที่บันทึกไว้ยังไม่พร้อมใช้งานและฉันจำไม่ได้ว่าคำตอบคืออะไร
Bryan Herbst

3
@ Tanis.7x คำตอบก็คือสวยมากว่าพวกเขาไม่ได้วางแผนที่เป็นส่วนประกอบกรอบสำหรับเมนูนี้ แต่ที่คุณสามารถหาชุดที่ดีของบล็อกโพสต์มากกว่าที่นี่ (เท่าที่ผมจำได้)

1
ฉันอ่านบล็อกโพสต์นั้น พวกเขากล่าวว่าพวกเขาใช้แถบการทำงานที่กำหนดเอง ตอนนี้ผู้พัฒนาฟังดูสมเหตุสมผล แต่ไม่ใช่ของ Google ที่แฮ็ก API ของตัวเอง!
Matroska

2
คำตอบสำหรับคำถามนี้ตอนนี้ "quazi" ล้าสมัยแล้ว ตอนนี้ Google ได้แนะนำ Navigation Drawer แล้วและวิธีการนี้จะแตกต่างจากที่ระบุไว้ในปัจจุบัน
Chase Florell

คำตอบ:


150

อันที่จริงมีวิธีการทำเช่นนี้ ActionBarแม้จะไม่มีการดำเนินการของคุณเอง

เพียงแค่ดูhierachyviewer! (อยู่ในไดเรกทอรีเครื่องมือ)

มีDecorViewและตอนLinearLayoutเป็นเด็ก ซึ่งLinearLayoutมีทั้งActionBarเนื้อหาอื่น ๆ ดังนั้นคุณสามารถใช้บางส่วนFrameLayout.LayoutParamsกับสิ่งนี้LinearLayoutและเพิ่มพื้นที่ทางด้านซ้ายด้วยวิธีนี้ จากนั้นคุณสามารถเติมช่องว่างนี้ด้วย menu-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;
}
}

วิธีการช่วยเหลือบางอย่าง (สำหรับฉันใน 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();

แค่นั้นแหละ!

และตอนนี้ภาพหน้าจอเล็ก ๆ น้อย ๆ ในการดำเนินการ:

SlideMenu

เท่าที่ฉันรู้คือใช้งานได้ หากคุณประสบปัญหาใด ๆ หรือคำอธิบายของฉันไม่ชัดเจนโปรดติดต่อฉัน!

แก้ไข: 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สำหรับกิจกรรมกับแท็บViewPagerwith PagerTabStripfor เช่น Talk, Market เป็นต้นคุณไม่สามารถปิดการใช้งาน Views เหล่านี้ได้ด้วยวิธีง่ายๆดังนั้นทั้งสองคลาสด้านบนจึงขยายเพื่อหยุดonTouchกิจกรรมเมื่อปิดใช้งาน


1
ดูดี แต่ ExtendedViewPager และ ExtendedPagerTabStrip มาจากไหน?
bk138

1
เจ๋งมากขอบคุณสำหรับไฟล์พิเศษฉันจะพยายามแปลงเป็น lib และโพสต์บน github
bk138

ฉันเดาว่าคุณต้องใส่ ExtendedViewPager และ ExtendedPagerTabStrip ใน XML สำหรับกิจกรรมของคุณใช่ไหม ตัวอย่างข้างต้นมองหา R.id.viewpager
Patrick

2
สวัสดีเราได้สรุปการใช้งานดั้งเดิมของ sciroccos และเพิ่มการแยกวิเคราะห์ XML รวมถึงการตรวจจับอัตโนมัติของแถบการทำงานที่อาจมีอยู่ สิ่งที่ทั้งอยู่ในขณะนี้ togther โครงการห้องสมุดที่มีตัวอย่างของแอปและมีการอธิบายมากกว่าที่coboltforge.com/2012/07/... ขอบคุณ @Scirocco สำหรับแนวคิดเริ่มต้น!
bk138

1
ฉันใช้วิธีนี้และใช้ได้กับ Android 4.1 แต่ใน Android 2.3 ไม่ได้? มันสร้างขึ้นสำหรับ Android เวอร์ชันที่สูงกว่าหรือไม่
Iulia Barbu

21

มีความพยายามหลายครั้งในการดำเนินการนี้ แต่ฉันยังไม่พบ lib หรือซอร์สโค้ดเกี่ยวกับวิธีใช้งานให้สำเร็จด้วยแถบการดำเนินการในทุกระดับ API Lib ที่มีแนวโน้มอยู่ที่นี่

https://github.com/jfeinstein10/SlidingMenu

นี่เป็นวิดีโอที่แอปพลิเคตัวอย่างเช่น

นี่คือลิงค์แอปGoogle Play

สิ่งนี้ใช้ได้กับ ActionbarSherlock คุณจะต้องสร้างไลบรารี SlidingMenu ด้วย ABS เพื่อให้ใช้งานได้ ใช้งานได้และดูดี!


2
แม้ว่าโดยทั่วไปโค้ดข้างต้นจะใช้งานได้ แต่ฉันสามารถพูดได้อย่างไม่ต้องสงสัยเลยว่าไลบรารีนี้เป็นโซลูชันแบบดรอปอินที่ยอดเยี่ยมสำหรับปัญหานี้ มันเริ่มเติบโตขึ้นสำหรับฉันในฐานะโซลูชันสำเร็จรูปสำหรับการใช้ side-nav
hwrdprkns

ยอมรับว่าไลบรารีนี้มีประโยชน์สำหรับเรามาก - ใช้งานง่ายสุด ๆ มีตัวเลือกการกำหนดค่ามากมายใช้งานได้กับ API หลายระดับและเล่นกับ ActionBarSherlock ได้ดี!
greg7gkb

8

ทำการสรุปการใช้งานดั้งเดิมและเพิ่มการแยกวิเคราะห์ XML รวมถึงautodetectionปัจจุบันที่เป็นไปได้actionbarดังนั้นจึงใช้งานได้กับเนทีฟและแถบการดำเนินการสนับสนุนเช่นActionBarSherlock.

ตอนนี้ทั้งหมดเป็นโครงการห้องสมุดพร้อมกับแอปตัวอย่างและมีการอธิบายไว้ที่เมนูเลื่อนสำหรับ Androidขอบคุณsciroccoสำหรับแนวคิดและรหัสเริ่มต้น!

ภาพหน้าจอ LibSlideMenu


ฉันต้องตั้งค่าเมนูสไลด์เป็นหน้าจอแรกนั่นคือเมื่อผู้ใช้เข้าสู่แอพเขาจะเห็นเมนูสไลด์ก่อนเป็นวิธีใดสำหรับสิ่งนั้น?
Sujiz

1
setAsShown () เพิ่มด้วยgithub.com/bk138/LibSlideMenu/commit/…ควรทำเคล็ดลับ
bk138

งานที่ดี! ฉันต้องการเพิ่มรายการเมนูย่อย (เช่นตรวจสอบแอพ facebook) ดังนั้นเมื่อเลือกรายการเมนูที่มีรายการย่อยเมนูจะต้องเคลื่อนไหวไปทางขวา มีเคล็ดลับในการดำเนินการนี้หรือไม่?
Luciano

@Luizje: ฉันเดาว่าคุณจะต้องใช้มุมมองที่คล้ายกันเช่น SlideMenu แต่เล็กกว่าและใช้ภาพเคลื่อนไหวในเรื่องนั้น ฉันยินดีที่จะรวมเข้ากับแพตช์ใด ๆ ที่คุณอาจมี :-)
bk138

7

หากคุณใช้ระดับ 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ที่แปลงและไม่เพียง แต่ทำให้เค้าโครงหลักเคลื่อนไหวด้วยแถบการดำเนินการดังนั้นคุณสามารถโต้ตอบกับมุมมองที่สูงเกินจริงที่คุณต้องการใช้เป็นแผงเลื่อนได้ คุณควรแทนที่ค่าฮาร์ดโค้ดด้วยค่าที่ใช้กับแอปของคุณ

ฉันหวังว่านี่จะช่วยได้ :)


6

ตอนนี้ฉันกำลังทำงานในโปรเจ็กต์และเจอเมนู Sliding ฉัน googled แต่รู้สึกผิดหวังมากที่เห็นว่าไม่มีใครให้รหัสบางส่วนหรือคำแนะนำบางอย่างเกี่ยวกับวิธีเริ่มสร้างเมนูแบบเลื่อน แต่ทุกคนมีลิงค์ไปยังบางส่วน โครงการ / ไลบรารีของ github ที่จะใช้ฉันตัดสินใจทำเองและในที่สุดฉันก็มีเมนูเลื่อนของตัวเองพร้อม ...

ฉันใช้เวลาสองวันกับมัน

1. ในการสร้างภาพเคลื่อนไหวของการเลื่อน

2. ในการทำให้มันทำงานได้กับความละเอียดหน้าจอทั้งหมด

มันง่ายมากและง่ายมากเมื่อคุณได้รับความคิดเกี่ยวกับแอนิเมชั่นฉันได้อ่านบางส่วนแล้วมันไม่สมเหตุสมผลที่จะประดิษฐ์Wheel ขึ้นมาใหม่ (ผู้ที่อ้างถึงซอร์สโค้ดของ 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>

คุณไปที่เมนูเลื่อนที่ใช้งานได้และใช้งานได้อย่างสมบูรณ์และคุณสามารถปรับแต่งให้ตรงตามความต้องการของคุณได้หากมีปัญหาในการตั้งค่าโปรดอย่าลังเลที่จะถามฉันยินดีที่จะช่วยเหลือคุณ:)


4
ในขณะที่ฉันไม่ได้เป็นแฟนตัวยงของการคิดค้นล้อใหม่ แต่ฉันก็รู้สึกขอบคุณสำหรับคำตอบที่คุณได้ให้ไว้ที่นี่
hwrdprkns

@hwrdprkns นั่นเป็นเรื่องตลก ... สิ่งที่ฉันตั้งใจจะพูดคือทุกคนควรนำพฤติกรรมของการเรียนรู้และนำไปใช้ :)
มูฮัมหมัดบาบาร์

@hwrdprkns +1 สำหรับโพสต์ที่ดีในการสร้างวงล้อใหม่
Muhammad Babar

5

ฉันได้สร้างโซลูชันของตัวเองสำหรับการเลื่อนมุมมองออกไปและเปิดเผยเมนูที่อยู่ด้านล่างเนื่องจากโซลูชันอื่น ๆ ดูเหมือนว่าจะไม่ทำงานบน Android เวอร์ชันเก่าหรือไม่มีคำแนะนำที่เหมาะสมในการใช้งาน

โซลูชันของฉันมีคุณสมบัติดังต่อไปนี้:

  • ให้การสนับสนุนสำหรับการเลื่อนมุมมองออกไปเพื่อแสดงเมนูที่อยู่ด้านล่าง
  • ทั้งเมนูและมุมมองด้านบนสามารถเป็นมุมมองที่กำหนดเองได้
  • รองรับ Android เวอร์ชันเก่า (ทดสอบแล้วว่าทำงานอย่างน้อยบน Android 2.2)
  • ทำงานร่วมกับโปรเจ็กต์ PhoneGap / Cordova

โซลูชันนี้ใช้เค้าโครงแบบกำหนดเองที่เรียกว่า SlidingMenuLayout ซึ่งคุณคาดว่าจะเพิ่ม 2 มุมมอง มุมมองแรกที่คุณเพิ่มคือเมนูส่วนที่สองคือมุมมองหลัก

วิธีที่ง่ายที่สุดในการเพิ่มเลย์เอาต์ไปยังโปรเจ็กต์ที่คุณมีอยู่คือการลบล้างsetContentView()วิธีการของกิจกรรมของคุณ:

@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 หน้าโครงการ


สวัสดีฉันชอบวิธีแก้ปัญหาของคุณฉันกำลังทำงานบนโทรศัพท์ 2.2 มันเลื่อนเค้าโครง "หลัก" แต่จะแสดงเค้าโครง "เมนู" ด้วยแม้ว่าฉันจะปิด "เมนู" ก็ตาม ทำไม?
Veer

ฉันมีปัญหาเดียวกันตรวจสอบให้แน่ใจว่าเค้าโครง "หลัก" มีสีพื้นหลังและจะทำงานได้ดี
iTech

3

สำหรับผู้ที่ใช้ไลบรารี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มุมมองการตกแต่งด้วยslidingmenuแทน

หมายเหตุ: ฉันได้ทดสอบเพียงเบา ๆ แต่ดูเหมือนว่าจะได้ผล


0
    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นี้เป็นชั้นเรียนของฉันขยาย สามารถเลื่อนด้วยแอคทิโอ


ฉันได้ลองแทนที่แท็ก <android.support.v4.widget.SlidingPaneLayout> ในรูปแบบ xml ด้วยคลาสของคุณแล้ว แต่ไม่มีอะไรเปลี่ยนแปลง ยังคงเลื่อนโดยไม่มีแถบการทำงาน คุณทำอย่างอื่นหรือไม่และไม่ได้กล่าวถึงที่นี่? ขอบคุณ!
Amir Uval
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.