在Android中的滑动抽屉中滑动手势不支持手指在listview上

时间:2014-09-25 11:19:51

标签: android android-listview slidingdrawer swipe-gesture

现在我正在使用带有列表视图的滑动抽屉控件。 我的问题是,我无法用手指在列表视图上滑动,但菜单(切换)按钮工作正常。 有没有人遇到过这样的情况,如果有的话,请帮我解决这个问题。 建议请。

我希望下面的图片可以让您清楚地了解我的问题 enter image description here

以下是我的工作资料

activity_main.xml中

<com.entropy.slidingmenu2.layout.MainLayout     xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

 <!-- This holds our menu -->
 <LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <ListView
        android:id="@+id/activity_main_menu_listvie"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#B4D609"
        android:cacheColorHint="#00000000" >
    </ListView>
</LinearLayout>

<!-- This holds our content-->
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <!-- This acts as Actionbar -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#96D6E3"
        android:orientation="horizontal" >

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="toggleMenu"
            android:text="Menu"
            android:id="@+id/activity_main_content_button_menu" />

        <TextView
             android:layout_width="0dp"
             android:layout_height="wrap_content"
             android:text="@string/app_name"
             android:gravity="center"
             android:id="@+id/activity_main_content_title"
             android:layout_weight="1" />

    </LinearLayout>       

    <!-- This is where fragment will show up -->
    <FrameLayout
        android:id="@+id/activity_main_content_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        </FrameLayout>
     </LinearLayout>
</com.entropy.slidingmenu2.layout.MainLayout>

fragment_listview.xml

<?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"
android:background="@android:color/white" >

<ListView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/fragment_listview_listview" />
</RelativeLayout>

MainActiviy.java

public class MainActivity extends FragmentActivity {

MainLayout mainLayout;
private ListView lvMenu;
private String[] lvMenuItems;
Button btMenu;
TextView tvTitle;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mainLayout = (MainLayout)this.getLayoutInflater().inflate(R.layout.activity_main, null);
    setContentView(mainLayout);

    lvMenuItems = getResources().getStringArray(R.array.menu_items);
    lvMenu = (ListView) findViewById(R.id.activity_main_menu_listvie);
    lvMenu.setAdapter(new ArrayAdapter<String>(this,
            android.R.layout.simple_list_item_1, lvMenuItems));
    lvMenu.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            onMenuItemClick(parent, view, position, id);
        }
    });
    btMenu = (Button) findViewById(R.id.activity_main_content_button_menu);
    btMenu.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            // Show/hide the menu
            toggleMenu(v);
        }
    });
    tvTitle = (TextView) findViewById(R.id.activity_main_content_title);
    // Add FragmentMain as the initial fragment       
    FragmentManager fm = MainActivity.this.getSupportFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();

    FragmentMain fragment = new FragmentMain();
    ft.add(R.id.activity_main_content_fragment, fragment);
    ft.commit();   
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

public void toggleMenu(View v){
    mainLayout.toggleMenu();
}

private void onMenuItemClick(AdapterView<?> parent, View view, int position, long id) {
    String selectedItem = lvMenuItems[position];
    String currentItem = tvTitle.getText().toString();

    // Do nothing if selectedItem is currentItem
    if(selectedItem.compareTo(currentItem) == 0) {
        mainLayout.toggleMenu();
        return;
    }
    FragmentManager fm = MainActivity.this.getSupportFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    Fragment fragment = null;


    if(selectedItem.compareTo("ListView") == 0) {
        fragment = new FragmentListView();
    }

    if(fragment != null) {
        // Replace current fragment by this new one
        ft.replace(R.id.activity_main_content_fragment, fragment);
        ft.commit();

        // Set title accordingly
        tvTitle.setText(selectedItem);
    }
    mainLayout.toggleMenu();
}

@Override
public void onBackPressed() {
    if (mainLayout.isMenuShown()) {
        mainLayout.toggleMenu();
    }
    else {
        super.onBackPressed();
    }
}}

FragmentListView.java

public class FragmentListView extends Fragment {
ListView listView;

public FragmentListView() {
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_listview, null);

    String[] listViewItems = new String[] {"Sachin Tendulkar", "Sourav Ganguly", "Rahul Dravid", "Virendar Shewag", 
            "Yuvraj Singh","Mahendra Singh Dhoni","Irfan Pathan","Bhuvaneshawar kumar","Harbhajan Singh",
            "Zaheer Khan","Ashish Nehra","Virat Kohli"};
    listView = (ListView) view.findViewById(R.id.fragment_listview_listview);
    listView.setAdapter(new ArrayAdapter<String>(getActivity(),
            android.R.layout.simple_list_item_1, listViewItems));

    return view;
}}

MainLayout.java

public class MainLayout extends LinearLayout {

// Duration of sliding animation, in miliseconds
private static final int SLIDING_DURATION = 500;

// Query Scroller every 16 miliseconds
private static final int QUERY_INTERVAL = 16;

// MainLayout width
int mainLayoutWidth;

// Sliding menu
private View menu;

// Main content
private View content;

// menu does not occupy some right space
// This should be updated correctly later in onMeasure
private static int menuRightMargin = 150;

// The state of menu
private enum MenuState {
    HIDING,
    HIDDEN,
    SHOWING,
    SHOWN,
};

// content will be layouted based on this X offset
// Normally, contentXOffset = menu.getLayoutParams().width = this.getWidth - menuRightMargin
private int contentXOffset;

// menu is hidden initially
private MenuState currentMenuState = MenuState.HIDDEN;

// Scroller is used to facilitate animation
private Scroller menuScroller = new Scroller(this.getContext(),
        new EaseInInterpolator());

// Used to query Scroller about scrolling position
// Note: The 3rd paramter to startScroll is the distance
private Runnable menuRunnable = new MenuRunnable();
private Handler menuHandler = new Handler();

// Previous touch position
int prevX = 0;

// Is user dragging the content
boolean isDragging = false;

// Used to facilitate ACTION_UP 
int lastDiffX = 0;

// Constructor

// 3 parameters constructor seems to be unavailable in 2.3
/*
public MainLayout(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}
*/

public MainLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public MainLayout(Context context) {
    super(context);
}

// Overriding LinearLayout core methods

// Ask all children to measure themselves and compute the measurement of this
// layout based on the children
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    mainLayoutWidth = MeasureSpec.getSize(widthMeasureSpec);
    menuRightMargin = mainLayoutWidth * 10 / 100;
    // Nothing to do, since we only care about how to layout
}

// This is called when MainLayout is attached to window
// At this point it has a Surface and will start drawing. 
// Note that this function is guaranteed to be called before onDraw
@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();

    // Get our 2 child View
    menu = this.getChildAt(0);
    content = this.getChildAt(1);   

    // Attach View.OnTouchListener
    content.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return MainLayout.this.onContentTouch(v, event);
        }
    });

    // Initially hide the menu
    menu.setVisibility(View.GONE);
}

// Called from layout when this view should assign a size and position to each of its children
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    //Log.d("MainLayout.java onLayout()", "left " + left + " top " + top + " right " + right + " bottom " + bottom);
    //Log.d("MainLayout.java onLayout()", "getHeight " + this.getHeight() + " getWidth " + this.getWidth());

    // True if MainLayout 's size and position has changed
    // If true, calculate child views size
    if(changed) {
        // Note: LayoutParams are used by views to tell their parents how they want to be laid out

        //Log.d("MainLayout.java onLayout()", "changed " + changed);

        // content View occupies the full height and width
        LayoutParams contentLayoutParams = (LayoutParams)content.getLayoutParams();
        contentLayoutParams.height = this.getHeight();
        contentLayoutParams.width = this.getWidth();

        // menu View occupies the full height, but certain width
        LayoutParams menuLayoutParams = (LayoutParams)menu.getLayoutParams();
        menuLayoutParams.height = this.getHeight();
        menuLayoutParams.width = this.getWidth() - menuRightMargin;          
    }

    // Layout the child views    
    menu.layout(left, top, right - menuRightMargin, bottom);
    content.layout(left + contentXOffset, top, right + contentXOffset, bottom);

}

// Custom methods for MainLayout

// Used to show/hide menu accordingly
public void toggleMenu() {
    // Do nothing if sliding is in progress
    if(currentMenuState == MenuState.HIDING || currentMenuState == MenuState.SHOWING)
        return;

    switch(currentMenuState) {
    case HIDDEN:
        currentMenuState = MenuState.SHOWING;
        menu.setVisibility(View.VISIBLE);
        menuScroller.startScroll(0, 0, menu.getLayoutParams().width,
                0, SLIDING_DURATION);
        break;
    case SHOWN:
        currentMenuState = MenuState.HIDING;
        menuScroller.startScroll(contentXOffset, 0, -contentXOffset, 
                0, SLIDING_DURATION);
        break;
    default:
        break;
    }

    // Begin querying
    menuHandler.postDelayed(menuRunnable, QUERY_INTERVAL);

    // Invalite this whole MainLayout, causing onLayout() to be called
    this.invalidate();
}

// Query Scroller
protected class MenuRunnable implements Runnable {
    @Override
    public void run() {
        boolean isScrolling = menuScroller.computeScrollOffset();
        adjustContentPosition(isScrolling);
    }
}

// Adjust content View position to match sliding animation
private void adjustContentPosition(boolean isScrolling) {
    int scrollerXOffset = menuScroller.getCurrX();

    //Log.d("MainLayout.java adjustContentPosition()", "scrollerOffset " + scrollerOffset);

    // Translate content View accordingly
    content.offsetLeftAndRight(scrollerXOffset - contentXOffset);

    contentXOffset = scrollerXOffset;

    // Invalite this whole MainLayout, causing onLayout() to be called
    this.invalidate();

    // Check if animation is in progress
    if (isScrolling)
        menuHandler.postDelayed(menuRunnable, QUERY_INTERVAL);
    else
        this.onMenuSlidingComplete();
}

// Called when sliding is complete
private void onMenuSlidingComplete() {
    switch (currentMenuState) {
    case SHOWING:
        currentMenuState = MenuState.SHOWN;
        break;
    case HIDING:
        currentMenuState = MenuState.HIDDEN;
        menu.setVisibility(View.GONE);
        break;
    default:
        return;
    }
}

// Make scrolling more natural. Move more quickly at the end
// See the formula here http://cyrilmottier.com/2012/05/22/the-making-of-prixing-fly-in-app-menu-part-1/
protected class EaseInInterpolator implements Interpolator {
    @Override
    public float getInterpolation(float t) {
        return (float)Math.pow(t-1, 5) + 1;
    }

}

// Is menu completely shown
public boolean isMenuShown() {
    return currentMenuState == MenuState.SHOWN;
}

// Handle touch event on content View
public boolean onContentTouch(View v, MotionEvent event) {
    // Do nothing if sliding is in progress
    if(currentMenuState == MenuState.HIDING || currentMenuState == MenuState.SHOWING)
        return false;

    // getRawX returns X touch point corresponding to screen
    // getX sometimes returns screen X, sometimes returns content View X
    int curX = (int)event.getRawX();
    int diffX = 0;

    switch(event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        //Log.d("MainLayout.java onContentTouch()", "Down x " + curX);

        prevX = curX;
        return true;

    case MotionEvent.ACTION_MOVE:
        //Log.d("MainLayout.java onContentTouch()", "Move x " + curX);

        // Set menu to Visible when user start dragging the content View
        if(!isDragging) {
            isDragging = true;
            menu.setVisibility(View.VISIBLE);
        }

        // How far we have moved since the last position
        diffX = curX - prevX;

        // Prevent user from dragging beyond border
        if(contentXOffset + diffX <= 0) {
            // Don't allow dragging beyond left border
            // Use diffX will make content cross the border, so only translate by -contentXOffset
            diffX = -contentXOffset;
        } else if(contentXOffset + diffX > mainLayoutWidth - menuRightMargin) {
            // Don't allow dragging beyond menu width
            diffX = mainLayoutWidth - menuRightMargin - contentXOffset;
        }

        // Translate content View accordingly
        content.offsetLeftAndRight(diffX);

        contentXOffset += diffX;

        // Invalite this whole MainLayout, causing onLayout() to be called
        this.invalidate();

        prevX = curX;
        lastDiffX = diffX;
        return true;

    case MotionEvent.ACTION_UP:
        //Log.d("MainLayout.java onContentTouch()", "Up x " + curX);

        Log.d("MainLayout.java onContentTouch()", "Up lastDiffX " + lastDiffX);

        // Start scrolling
        // Remember that when content has a chance to cross left border, lastDiffX is set to 0
        if(lastDiffX > 0) {
            // User wants to show menu
            currentMenuState = MenuState.SHOWING;

            // No need to set to Visible, because we have set to Visible in ACTION_MOVE
            //menu.setVisibility(View.VISIBLE);

            //Log.d("MainLayout.java onContentTouch()", "Up contentXOffset " + contentXOffset);

            // Start scrolling from contentXOffset
            menuScroller.startScroll(contentXOffset, 0, menu.getLayoutParams().width - contentXOffset,
                    0, SLIDING_DURATION);
        } else if(lastDiffX < 0) {
            // User wants to hide menu
            currentMenuState = MenuState.HIDING;
            menuScroller.startScroll(contentXOffset, 0, -contentXOffset, 
                    0, SLIDING_DURATION);
        }

        // Begin querying
        menuHandler.postDelayed(menuRunnable, QUERY_INTERVAL);

        // Invalite this whole MainLayout, causing onLayout() to be called
        this.invalidate();

        // Done dragging
        isDragging = false;
        prevX = 0;
        lastDiffX = 0;
        return true;

    default:
        break;
    }

    return false;
}}

1 个答案:

答案 0 :(得分:0)

这不是官方Android SDK的Sliding Drawer。这是一个自定义的。正如文档中所述,您需要阅读资源以添加滑动。为此,我建议您阅读this文章。