OnCloseListener của SearchView không hoạt động


101

Tôi đang cố gắng thêm hỗ trợ cho Thanh hành động SearchViewtrên Android 3.0+, nhưng tôi không thể OnCloseListenerhoạt động được.

Đây là mã của tôi:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu, menu);
    searchView = (SearchView) menu.findItem(R.id.search_textbox).getActionView();
    searchView.setOnQueryTextListener(new OnQueryTextListener() {
        @Override
        public boolean onQueryTextChange(String newText) {
            searchLibrary(newText);
            return false;
        }
        @Override
        public boolean onQueryTextSubmit(String query) { return false; }
    });
    searchView.setOnCloseListener(new OnCloseListener() {
        @Override
        public boolean onClose() {
            System.out.println("Testing. 1, 2, 3...");
            return false;
        }
    });
    return true;
}

Tìm kiếm hoạt động tốt và mọi thứ đều hoạt động ngoại trừ OnCloseListener. Không có gì được in vào Logcat. Đây là Logcat khi tôi nhấn nút "Đóng":

02-17 13:01:52.914: I/TextType(446): TextType = 0x0
02-17 13:01:57.344: I/TextType(446): TextType = 0x0
02-17 13:02:02.944: I/TextType(446): TextType = 0x0

Tôi đã xem qua tài liệu và mẫu, nhưng dường như không có gì thay đổi được. Tôi đang chạy nó trên Asus Transformer Prime và Galaxy Nexus, cả trên Ice Cream Sandwich. Bất kỳ ý tưởng?

Cập nhật:

Có - System.out.println() không hoạt động. Đây là bằng chứng:

   @Override
 public boolean onQueryTextChange(String newText) {
    System.out.println(newText + "hello");
    searchLibrary(newText);
    return false;
 }

Kết quả trong Logcat này:

02-17 13:04:20.094: I/System.out(21152): hello
02-17 13:04:24.914: I/System.out(21152): thello
02-17 13:04:25.394: I/System.out(21152): tehello
02-17 13:04:25.784: I/System.out(21152): teshello
02-17 13:04:26.064: I/System.out(21152): testhello

Rất tiếc, hoạt động tốt đối với tôi với Android 3.2 nhưng KHÔNG hoạt động với 4.0+
PJL

10
Lỗi phát sinh, 25758
PJL

3
Tôi rất vui vì không phải chỉ có tôi gặp vấn đề này. Có ai có bất kỳ cách hack nào khác ngoài cách hack dưới đây không?
bencallis

2
Tôi đã học được hai điều nếu showAsActionđược đặt thành always. Hộp tìm kiếm có một nút đóng của riêng nó nhưng nếu nó được đặt thành ifRoom | collapseActionViewnó sẽ mở rộng trên thanh tác vụ.
Beraki

Câu trả lời:


153

Tôi cũng gặp vấn đề này, và tôi không có lựa chọn nào khác ngoài việc từ bỏ "oncloselistener". Thay vào đó, bạn có thể lấy menuItem của mình setOnActionExpandListener. Sau đó ghi đè các phương thức unimplents.

@Override
public boolean onMenuItemActionExpand(MenuItem item) {
    // TODO Auto-generated method stub
    Log.d("*******","onMenuItemActionExpand");
    return true;
}

@Override
public boolean onMenuItemActionCollapse(MenuItem item) {
    //do what you want to when close the sesarchview
    //remember to return true;
    Log.d("*******","onMenuItemActionCollapse");
    return true;
}

Tôi tin rằng chúng tôi chỉ nói về SearchView ActionBar của mà chỉ tổ ong +
NKijak

không cần sử dụng onCloseListener, chỉ cần sử dụng cái này với mục menu của bạn.
Robert

12
Tôi nghĩ bạn có thể sử dụng MenuItemCompat.OnActionExpandListener cho các cấp API trước đó: developer.android.com/reference/android/support/v4/view/…
Ripityom

2
Full câu trả lời:if (Build.VERSION.SdkInt > BuildVersionCodes.NMr1) item.SetOnActionExpandListener(this); else MenuItemCompat.SetOnActionExpandListener(item, this);
FindOutIslamNow

61

Đối với Android API 14+ (ICS trở lên), hãy sử dụng mã này:

// When using the support library, the setOnActionExpandListener() method is
// static and accepts the MenuItem object as an argument
MenuItemCompat.setOnActionExpandListener(menuItem, new OnActionExpandListener() {
    @Override
    public boolean onMenuItemActionCollapse(MenuItem item) {
        // Do something when collapsed
        return true;  // Return true to collapse action view
    }

    @Override
    public boolean onMenuItemActionExpand(MenuItem item) {
        // Do something when expanded
        return true;  // Return true to expand action view
    }
});

Để biết thêm thông tin: http://developer.android.com/guide/topics/ui/actionbar.html#ActionView

Tham khảo: onActionCollapse / onActionExpand


31

Đối với vấn đề này, tôi đã nghĩ ra một cái gì đó như thế này,

private SearchView mSearchView;

@TargetApi(14)
@Override
public boolean onCreateOptionsMenu(Menu menu)
{

    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.conversation_index_activity_menu, menu);

    mSearchView = (SearchView) menu.findItem(R.id.itemSearch).getActionView();

    MenuItem menuItem = menu.findItem(R.id.itemSearch);

    int currentapiVersion = android.os.Build.VERSION.SDK_INT;
    if (currentapiVersion >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    {
        menuItem.setOnActionExpandListener(new OnActionExpandListener()
        {

            @Override
            public boolean onMenuItemActionCollapse(MenuItem item)
            {
                // Do something when collapsed
                Log.i(TAG, "onMenuItemActionCollapse " + item.getItemId());
                return true; // Return true to collapse action view
            }

            @Override
            public boolean onMenuItemActionExpand(MenuItem item)
            {
                // TODO Auto-generated method stub
                Log.i(TAG, "onMenuItemActionExpand " + item.getItemId());
                return true;
            }
        });
    } else
    {
        // do something for phones running an SDK before froyo
        mSearchView.setOnCloseListener(new OnCloseListener()
        {

            @Override
            public boolean onClose()
            {
                Log.i(TAG, "mSearchView on close ");
                // TODO Auto-generated method stub
                return false;
            }
        });
    }


    return super.onCreateOptionsMenu(menu);

}

1
Điều gì xảy ra nếu bạn luôn mở rộng bằng setIconofiedByDefault (false)? Nó không hoạt động ... :(
Joan Casadellà

19

Tôi gặp phải vấn đề tương tự trên Android 4.1.1. Có vẻ như đó là một lỗi đã biết: https://code.google.com/p/android/issues/detail?id=25758

Dù sao, như một giải pháp thay thế, tôi đã sử dụng trình nghe thay đổi trạng thái (khi SearchView được tách khỏi thanh tác vụ, nó cũng bị đóng rõ ràng).

view.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {

    @Override
    public void onViewDetachedFromWindow(View arg0) {
        // search was detached/closed
    }

    @Override
    public void onViewAttachedToWindow(View arg0) {
        // search was opened
    }
});

Mã trên hoạt động tốt trong trường hợp của tôi.


Tôi đăng câu trả lời tương tự ở đây: https://stackoverflow.com/a/24573266/2162924


Có, lỗi đó được tạo ra ngay sau khi tôi đăng câu hỏi này. Xem các bình luận về câu hỏi ban đầu.
Michell Bak

Ồ được rồi, xem ngay. Nhưng dù sao đi nữa, có thể cách giải quyết này với trình nghe thay đổi trạng thái cũng có thể hữu ích cho những người khác.
Dario

Mặc dù đáng thất vọng rằng OnCloseListener không hoạt động như bạn nghĩ, nhưng đây thực sự là một giải pháp tốt và sạch sẽ. Thanh danh!
welshk91

10

Tôi đã sử dụng một chút bản hack, hoạt động tốt cho mục đích của tôi - không chắc nó sẽ hoạt động với mọi mục đích. Dù sao, tôi đang kiểm tra xem truy vấn tìm kiếm có trống không. Đây không phải là thực sự liên quan đến việc SearchView's OnCloseListenermặc dù - mà vẫn không làm việc!

searchView.setOnQueryTextListener(new OnQueryTextListener() {
            @Override
            public boolean onQueryTextChange(String newText) {
                if (newText.length() > 0) {
                    // Search
                } else {
                    // Do something when there's no input
                }
                return false;
            }
            @Override
            public boolean onQueryTextSubmit(String query) { return false; }
        });

7

Chà, điều này đã giải quyết được vấn đề của tôi:

Mục menu với showAsAction="always"

<item
    android:id="@+id/action_search"
    android:icon="@drawable/ic_action_search"
    android:title="Search"
    app:actionViewClass="android.support.v7.widget.SearchView"
    app:showAsAction="always"/>

và đang hoạt động

searchView.setOnCloseListener(new OnCloseListener() {

        @Override
        public boolean onClose() {

            Log.i("SearchView:", "onClose");
            searchView.onActionViewCollapsed();
            return false;
        }
    });

1
Đặt alwaysgiá trị cho showAsActionthuộc tính sẽ giải quyết được vấn đề. Điều quan trọng là khi alwaysgiá trị is notcó trong showAsAction, được mở rộng SearchViewhiển thị nút đóng (biểu tượng chéo) chỉ khi truy vấn trong SearchViewkhông phải là Chuỗi rỗng. Các SearchView.onCloseClickedrằng tay cầm nút đóng kiện nói rằng callback để OnCloseListenerđược gọi là chỉ khi truy vấn là trống rỗng, nếu nó không - nó xóa đầu tiên - nhưng sau đó, sau khi truy vấn thanh toán bù trừ gần nút biến mất và chúng tôi không thể cung cấp onClosegọi lại đểOnCloseListener
bpawlowski

1
Chỉ là một gợi ý: phương thức này được gọi khi người dùng đóng chế độ xem tìm kiếm (khá rõ ràng, nhưng tôi phải mất một vài lần để nhận ra). Khi người dùng nhấp vào X, nó sẽ xóa văn bản và tôi không nhận được bản cập nhật đó, trong lần nhấp thứ hai vào X, nó sẽ đóng SearchView và onClose được gọi. Hy vọng nó giúp!
Federico Alvarez,

4

Để thực hiện OnCloseListenercông việc, hãy đảm bảo rằng điều đó showAsActionđược đặt alwaystrong mục menu tìm kiếm.

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      xmlns:tools="http://schemas.android.com/tools"
      tools:context=".SearchActivity">

    <item
        android:id="@+id/search"
        android:title="@string/search"
        android:icon="@drawable/ic_search_toolbar"
        app:showAsAction="always"
        app:actionViewClass="android.support.v7.widget.SearchView"/>
</menu>

2

Tôi đã gặp phải sự cố tương tự với việc onCloseListener không gọi SearchView. Hiểu từ vấn đề lỗi được nêu ra trong 25758 và một số bài đăng tôi đã đọc, để gọi onCloseListener, bạn cần đặt:

searchView.setIconifiedByDefault(true);

Nhưng đối với trường hợp của tôi, tôi muốn mở chế độ xem tìm kiếm và không phải biểu tượng hóa mọi lúc. Tôi quản lý để giải quyết vấn đề này bằng cách thêm một dòng nữa bên dưới:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.search_bar, menu);
    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    searchView = (SearchView) menu.findItem(R.id.search).getActionView();
    searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
    searchView.setOnQueryTextListener(queryTextListener);
    searchView.setIconifiedByDefault(true);
    searchView.setIconified(false);
    return true;
}

SearchView.setIconified (false) sẽ làm cho searchView mở ra, mặc dù đã đặt giá trị mặc định thành iconified thành true trong dòng trước. Bằng cách này, tôi đã quản lý để có cả một SearchView luôn mở và nó gọi onCloseListener.


2

Tạo mục menu với app:showAsActionbộ luôn luôn.

<item   
 android:id="@+id/action_search"  
 android:title="..."  
 android:icon="..."  
 app:actionViewClass="android.support.v7.widget.SearchView"  
 app:showAsAction="always"/>

Khi tạo SearchViewtrong onCreateOptionsMenuphương thức, hãy làm điều gì đó tương tự

inflater.inflate(R.menu.menu_search, menu);
final MenuItem item = menu.findItem(R.id.action_search);
final SearchView search = (SearchView) item.getActionView();
search.setQueryHint(getString(R.string.search_brand_item));
search.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
  @Override
  public boolean onQueryTextSubmit(String query) {
    // add your code
    return false;
  }

  @Override
  public boolean onQueryTextChange(String newText) {
    // add your code 
    return false;
  }
});
search.setOnCloseListener(new SearchView.OnCloseListener() {
  @Override
  public boolean onClose() {
    // add your code here
    return false;
  }
});
search.setIconifiedByDefault(true); // make sure to set this to true

Các search.setIconifiedByDefault(true)nhu cầu được đặt thànhtrue gọi các onClose()phương pháp trên SearchView.OnCloseListener()đã tạo ở trên.



0

Lý do OnCloseListenerkhông được gọi là do có một lỗi trong mã Android - người nghe chỉ được gọi nếu bạn cũng gọi setIconifiedByDefault(true).


7
Tôi chỉ cố gắng thêm setIconifiedByDefault (true) nhưng nó không được gọi là
Giuseppe

@Joseph Earl: Tôi đang gặp sự cố tương tự ở đây: stackoverflow.com/questions/43702055/… . Bất kỳ suy nghĩ hoặc ý tưởng về cách sửa chữa?
AJW

0

Có vẻ như một chủ đề cũ đã có, nhưng tôi nghĩ rằng tôi đã gặp vấn đề tương tự API 18 ngay từ đầu. Sau khi googled xung quanh, tìm thấy chủ đề này, một giờ nữa đọc javadoc đã thử và mắc lỗi vì điều gì đó mà tôi không giả vờ hoàn toàn hiểu trong javadoc, công việc sau đây đối với tôi:

searchView.setIconifiedByDefault(true);

   // OnQueryTextListener
   @Override
   public boolean onQueryTextSubmit(String query) {
      Log.d(tag, "onQueryTextSubmit: " + query);
      return true;
   }

   @Override
   public boolean onQueryTextChange(String query) {
      Log.d(tag, "onQueryTextChange: " + query);
      return true;
   }

   // OnCloseListener
   @Override
   public boolean onClose() {
      Log.w(tag, "onClose: ");
      return false;
   }

Tôi đã chơi với true / false một chút, điều đó bằng cách nào đó tạo ra sự khác biệt, và nó phù hợp với tôi bây giờ. Hy vọng rằng, nó có thể tiết kiệm thời gian cho ai đó.


0

Đó là một giải pháp thay thế nhưng đã hiệu quả với tôi

  searchView.setOnQueryTextListener(new android.widget.SearchView.OnQueryTextListener() {

                String lastText;

                @Override
                public boolean onQueryTextChange(final String newText) {
                    if (lastText != null && lastText.length() > 1 && newText.isEmpty()) {
                        // close ctn clicked

                        return true;
                    }
}

0
    searchView.setOnCloseListener {
        d("click", "close clicked")
        return@setOnCloseListener false
    }

nếu bạn nhấp vào đóng searchView ->

D / click: đóng được nhấp


1
Các câu trả lời với một đoạn mã và một số từ khó hiểu không đặc biệt rõ ràng. Chỉ cần sử dụng ngôn ngữ tự nhiên để mô tả lý do tại sao bạn nghĩ rằng điều này giải quyết được vấn đề và sau đó chỉ ra việc thực hiện giải pháp.

0

Tôi gặp sự cố này khi cố gắng phát hiện việc hiển thị / loại bỏ SearchView. Cuối cùng tôi đã sử dụng một trình nghe khác và nó hoạt động cho những gì tôi cần:

        setOnQueryTextFocusChangeListener { _, hasFocus ->
            if (hasFocus) {
                // SearchView is being shown
            } else {
                // SearchView was dismissed
            }
        }

0

Tôi đã sử dụng nút đóng SearchView và đặt setOnClickListener trên đó

searchView.findViewById<ImageView>(R.id.search_close_btn).setOnClickListener {
    searchView.setQuery("", false)
    searchView.clearFocus()
}

-2

Không có bảng điều khiển nào trong Android để đăng nhập. Thay vào đó, hãy sử dụng khung ghi nhật ký android:

Log.d("Test Tag", "Testing.  1, 2, 3...");

Xem thêm câu hỏi này: Tại sao "System.out.println" không hoạt động trong Android?


2
Không đúng, nó hoạt động tốt. Vui lòng xem câu hỏi cập nhật của tôi - Tôi đã thêm một dòng trong phương thức onQueryTextChange để chứng minh điều đó. Cũng đã thử thêm Log.d (), nhưng điều đó cũng không hiển thị bất cứ điều gì.
Michell Bak

Ôi lỗi của tôi! Có vẻ như ở đâu đó trên đường đi họ đã quyết định xuất System.out.println vào Log.i. Chúc may mắn
Chris Knight

-3

Có hai mẫu phổ biến cho SearchView.setOnCloseListener() . Điều này thực sự đúng với tất cả những người nghe, nhưng tôi đang giải quyết câu hỏi của bạn một cách cụ thể. Cách đầu tiên là tạo một hàm lắng nghe và gắn nó vào một biến thành viên, và cách thứ hai là làm cho lớp triển khai giao diện và có trình xử lý là một hàm thành viên.

Tạo một đối tượng người nghe trông giống như sau:

private SearchView mSearchView;
private final SearchView.OnCloseListener mOnCloseListener = 
    new SearchView.OnCloseListener() {
        public boolean onClose() {
            doStuff();
            return myBooleanResult;
        }
    };
mSearchView.setOnCloseListener(mOnCloseListener);

Việc triển khai trình nghe ở cấp lớp trông giống như sau:

public class MyClass implements OnCloseListener {
    private SearchView mSearchView;

    public MyClass(...) {
        mSearchView.setOnCloseListener(this);
    }

    @Override
    public boolean onClose() {
        doStuff();
        return false;
    }
}

Tôi chưa thấy bất kỳ ví dụ nào tạo ra OnCloseListenerđặc biệt, như bạn đã làm trong câu hỏi của mình.


Này Sparky, cảm ơn vì đã bình luận về điều này. Tôi không thực sự thấy điều đó sẽ thay đổi bất cứ điều gì. Trình nghe lồng nhau cũng là một cách hợp lệ để tạo ra nó và nó hoạt động trên Honeycomb như bạn có thể thấy dựa trên các nhận xét ở đây. Tôi không gặp bất kỳ vấn đề nào với trình nghe lồng nhau trên ICS ngoài điều này - tính năng này lại hoạt động trên Honeycomb.
Michell Bak

Bởi các trình nghe lồng nhau, ý tôi là các lớp ẩn danh bên trong.
Michell Bak

Tôi đồng ý rằng điều đó không quan trọng. Tôi chỉ bình luận về những gì có trong cơ sở mã. Tôi sẽ xem xét liệu có thể các điều kiện mà onClose được xác định lại hay không.
Sparky

Tôi không chắc bạn hiểu Java - nó được gọi là lớp bên trong ẩn danh.
Joseph Earl,
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.