OnCloseListener ของ SearchView ไม่ทำงาน


101

ฉันกำลังพยายามเพิ่มการสนับสนุนสำหรับSearchViewAndroid 3.0+ ActionBar แต่ไม่สามารถใช้OnCloseListenerงานได้

นี่คือรหัสของฉัน:

@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;
}

การค้นหาทำงานได้ดีและทุกอย่างใช้งานได้ยกเว้นไฟล์OnCloseListener. ไม่มีสิ่งใดถูกพิมพ์ไปยัง Logcat นี่คือ Logcat เมื่อฉันกดปุ่ม "ปิด":

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

ฉันได้ดูเอกสารและตัวอย่างแล้ว แต่ดูเหมือนจะไม่มีอะไรเปลี่ยนแปลง ฉันใช้งานบน Asus Transformer Prime และ Galaxy Nexus ทั้งบน Ice Cream Sandwich ความคิดใด ๆ ?

อัปเดต:

ใช่ - System.out.println() ไม่ทำงาน นี่คือหลักฐาน:

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

ผลลัพธ์ใน Logcat นี้:

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

อืมใช้งานได้ดีสำหรับฉันกับ Android 3.2 แต่ไม่ใช่สำหรับ 4.0+
PJL

10
Raised bug 25758
PJL

3
ฉันดีใจที่ไม่ใช่แค่ฉันที่มีปัญหานี้ ใครมีแฮ็กอื่น ๆ นอกเหนือจากด้านล่างนี้บ้าง?
bencallis

2
ฉันได้เรียนรู้สิ่งที่สองถ้ามีการตั้งค่าshowAsAction alwaysช่องค้นหามีปุ่มปิดเป็นของตัวเอง แต่หากตั้งค่าเป็นช่องจะifRoom | collapseActionViewขยายบนแถบการดำเนินการ
Beraki

คำตอบ:


153

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

@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;
}

ฉันเชื่อว่าเรากำลังพูดถึง SearchView ของ ActionBar ซึ่งเป็นเพียงรังผึ้งเท่านั้น +
NKijak

ไม่ต้องกังวลกับการใช้ onCloseListener เพียงใช้อันนี้กับรายการเมนูของคุณ
Robert

12
ฉันคิดว่าคุณสามารถใช้ MenuItemCompat.OnActionExpandListener ระดับ API ก่อนหน้านี้: developer.android.com/reference/android/support/v4/view/...
Ripityom

2
คำตอบแบบเต็ม:if (Build.VERSION.SdkInt > BuildVersionCodes.NMr1) item.SetOnActionExpandListener(this); else MenuItemCompat.SetOnActionExpandListener(item, this);
FindOutIslamNow

61

สำหรับ Android API 14+ (ICS ขึ้นไป) ให้ใช้รหัสนี้:

// 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
    }
});

สำหรับข้อมูลเพิ่มเติม: http://developer.android.com/guide/topics/ui/actionbar.html#ActionView

อ้างอิง: onActionCollapse / onActionExpand


31

สำหรับปัญหานี้ฉันคิดแบบนี้

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
จะเกิดอะไรขึ้นถ้าคุณขยายโดยใช้ setIconofiedByDefault (false) อยู่เสมอ มันไม่ได้ผล ... :(
Joan Casadellà

19

ฉันพบปัญหาเดียวกันใน Android 4.1.1 ดูเหมือนว่าจะเป็นข้อบกพร่องที่ทราบแล้ว: https://code.google.com/p/android/issues/detail?id=25758

อย่างไรก็ตามในฐานะที่เป็นวิธีแก้ปัญหาฉันใช้ตัวฟังการเปลี่ยนแปลงสถานะ (เมื่อ SearchView ถูกแยกออกจากแถบการกระทำมันจะถูกปิดอย่างชัดเจนเช่นกัน)

view.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {

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

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

รหัสด้านบนใช้งานได้ดีในกรณีของฉัน


ฉันโพสต์คำตอบเดียวกันที่นี่: https://stackoverflow.com/a/24573266/2162924


ใช่ข้อบกพร่องนั้นถูกสร้างขึ้นทันทีหลังจากที่ฉันโพสต์คำถามนี้ ดูความคิดเห็นในคำถามเดิม
Michell Bak

โอเคเห็นเลย แต่อย่างไรก็ตามบางทีวิธีแก้ปัญหานี้ด้วยตัวฟังการเปลี่ยนแปลงสถานะอาจเป็นประโยชน์สำหรับผู้อื่นด้วย
Dario

ในขณะที่น่าผิดหวังที่ OnCloseListener ไม่ทำงานอย่างที่คุณคิด แต่นี่เป็นวิธีที่ดีและสะอาด ความรุ่งโรจน์!
welshk91

10

ฉันลงเอยด้วยการใช้แฮ็คเล็กน้อยซึ่งทำงานได้ดีตามวัตถุประสงค์ของฉัน - ไม่แน่ใจว่าจะใช้ได้กับทุกวัตถุประสงค์ อย่างไรก็ตามฉันกำลังตรวจสอบเพื่อดูว่าคำค้นหาว่างเปล่า สิ่งนี้ไม่ได้เกี่ยวข้องกับสิ่งSearchViewนี้OnCloseListenerแต่ก็ยังใช้ไม่ได้!

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

สิ่งนี้ช่วยแก้ปัญหาของฉันได้:

รายการเมนูด้วย 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"/>

และในกิจกรรม

searchView.setOnCloseListener(new OnCloseListener() {

        @Override
        public boolean onClose() {

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

1
การตั้งalwaysค่าเป็นshowAsActionแอตทริบิวต์ช่วยแก้ปัญหาได้ สิ่งสำคัญคือเมื่อมีalwaysค่าis notอยู่ในshowAsActionตัวขยายSearchViewจะแสดงปุ่มปิด (ไอคอนกากบาท) เฉพาะในกรณีที่แบบสอบถามในSearchViewไม่ใช่สตริงว่าง สิ่งSearchView.onCloseClickedที่จัดการกับเหตุการณ์ปุ่มปิดจะบอกว่าการโทรกลับจะOnCloseListenerถูกเรียกก็ต่อเมื่อแบบสอบถามว่างเปล่าหากยังไม่ได้ - จะถูกล้างก่อน แต่หลังจากนั้นหลังจากล้างปุ่มปิดการค้นหาจะหายไปและเราไม่สามารถส่งการonCloseโทรกลับไปที่OnCloseListener
bpawlowski

1
คำใบ้: วิธีนี้เรียกว่าเมื่อผู้ใช้ปิดมุมมองการค้นหา (ค่อนข้างชัดเจน แต่ฉันต้องใช้เวลาสองสามครั้งกว่าจะรู้ตัว) เวลาที่ผู้ใช้คลิกที่ X เมื่อใช้กำปั้นมันจะลบข้อความและฉันไม่ได้รับการอัปเดตนั้นในการคลิกครั้งที่สองบน X มันจะปิด SearchView และมีการเรียก onClose หวังว่าจะช่วยได้!
Federico Alvarez

4

ในการOnCloseListenerทำงานตรวจสอบให้แน่ใจว่าshowAsActionได้ตั้งค่าเป็นalwaysในรายการเมนูการค้นหา

<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

ฉันพบปัญหาเดียวกันกับ onCloseListener ไม่เรียกใช้ SearchView ทำความเข้าใจจากปัญหาข้อผิดพลาดที่เกิดขึ้นในปี25758และการโพสต์บางส่วนที่ฉันได้อ่านเพื่อเรียกใช้ onCloseListener คุณต้องตั้งค่า:

searchView.setIconifiedByDefault(true);

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

@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) จะทำให้ searchView เปิดขึ้นแม้จะตั้งค่าเริ่มต้นเป็น iconified เป็น true ในบรรทัดก่อนหน้า ด้วยวิธีนี้ฉันจึงมีทั้ง SearchView ที่เปิดขึ้นตลอดเวลาและเรียกใช้ onCloseListener


2

สร้างรายการเมนูโดยapp:showAsActionตั้งค่าเป็นเสมอ

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

เมื่อสร้างSearchViewในonCreateOptionsMenuวิธีการให้ทำสิ่งที่คล้ายกัน

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

search.setIconifiedByDefault(true)ความต้องการที่จะตั้งเพื่อtrueที่จะเรียกonClose()วิธีการเกี่ยวกับการSearchView.OnCloseListener()สร้างดังกล่าวข้างต้น



0

สาเหตุที่OnCloseListenerไม่ถูกเรียกเนื่องจากมีข้อผิดพลาดในรหัส Android - ผู้ฟังจะถูกโทรเมื่อคุณโทรเข้าsetIconifiedByDefault(true)เท่านั้น


7
ฉันเพิ่งลองเพิ่ม setIconifiedByDefault (true) แต่มันไม่ถูกเรียก
Giuseppe

@ โจเซฟเอิร์ล: ฉันมีปัญหาที่คล้ายกันที่นี่: stackoverflow.com/questions/43702055/… . มีความคิดหรือความคิดในการแก้ไขอย่างไร?
AJW

0

ดูเหมือนว่าจะเป็นเธรดเก่าแล้ว แต่ฉันคิดว่าฉันมีปัญหาเดียวกันกับ API 18 ในการเริ่มต้นครั้งแรก หลังจาก googled ไปรอบ ๆ พบหัวข้อนี้อีกชั่วโมงอ่าน javadoc พยายามและผิดพลาดในสิ่งที่ฉันไม่ได้แสร้งทำเป็นเข้าใจอย่างถ่องแท้ใน javadoc งานต่อไปนี้สำหรับฉันตอนนี้:

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;
   }

ฉันเล่นด้วยความจริง / เท็จเล็กน้อยซึ่งทำให้เกิดความแตกต่างและมันก็ใช้ได้กับฉันในตอนนี้ หวังว่ามันจะช่วยประหยัดเวลาของใครบางคนได้


0

เป็นวิธีแก้ปัญหา แต่ได้ผลสำหรับฉัน

  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
    }

หากคุณคลิกที่ close searchView ->

D / click: คลิกปิด


1
คำตอบด้วยโค้ดหยดหนึ่งและคำที่คลุมเครือบางคำไม่ชัดเจนเป็นพิเศษ เพียงใช้ภาษาที่เป็นธรรมชาติเพื่ออธิบายว่าเหตุใดคุณจึงคิดว่าวิธีนี้ช่วยแก้ปัญหาได้จากนั้นจึงแสดงการใช้งานวิธีแก้ปัญหา

0

ฉันพบปัญหานี้ขณะพยายามตรวจหาการแสดง / ปิด SearchView ฉันลงเอยด้วยการใช้ผู้ฟังที่แตกต่างกันและได้ผลตามที่ฉันต้องการ:

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


-2

ไม่มีคอนโซลใน Android ให้เข้าสู่ระบบ ให้ใช้กรอบการบันทึกของ Android แทน:

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

ดูคำถามนี้ด้วยเหตุใด "System.out.println" จึงไม่ทำงานใน Android


2
ไม่เป็นความจริงมันใช้งานได้ดี โปรดดูคำถามที่อัปเดตของฉัน - ฉันได้เพิ่มบรรทัดในเมธอด onQueryTextChange เพื่อพิสูจน์แล้ว ลองเพิ่ม Log.d () ด้วย แต่ก็ไม่ได้แสดงอะไรเลย
Michell Bak

โอ้ฉันแย่! ดูเหมือนว่าจะมีที่ไหนสักแห่งระหว่างทางที่พวกเขาตัดสินใจที่จะส่งออก System.out.println ไปยัง Log.i. Good luck
Chris Knight

-3

มีสองรูปแบบทั่วไปสำหรับSearchView.setOnCloseListener(). นี่เป็นเรื่องจริงสำหรับผู้ฟังทุกคน แต่ฉันกำลังตอบคำถามของคุณโดยเฉพาะ วิธีแรกคือการสร้างฟังก์ชั่นผู้ฟังและแนบเข้ากับตัวแปรสมาชิกและวิธีที่สองคือทำให้คลาสใช้อินเทอร์เฟซและให้ตัวจัดการเป็นฟังก์ชันสมาชิก

การสร้างวัตถุผู้ฟังมีลักษณะดังนี้:

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

การใช้งานผู้ฟังในระดับชั้นเรียนมีลักษณะดังนี้:

public class MyClass implements OnCloseListener {
    private SearchView mSearchView;

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

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

ฉันไม่เห็นตัวอย่างใด ๆ ที่สร้างOnCloseListenerเฉพาะกิจอย่างที่คุณเคยทำในคำถามของคุณ


เฮ้ Sparky ขอบคุณสำหรับการแสดงความคิดเห็นเกี่ยวกับเรื่องนี้ ฉันไม่เห็นว่าควรเปลี่ยนแปลงอะไร Listener ที่ซ้อนกันเป็นวิธีที่ถูกต้องในการสร้างมันเช่นกันและใช้ได้กับ Honeycomb ดังที่คุณเห็นตามความคิดเห็นที่นี่ ฉันไม่มีปัญหาใด ๆ กับผู้ฟังที่ซ้อนกันบน ICS นอกเหนือจากนี้ซึ่งใช้งานได้กับ Honeycomb อีกครั้ง
Michell Bak

โดยผู้ฟังที่ซ้อนกันฉันหมายถึงคลาสภายในที่ไม่ระบุชื่อ
Michell Bak

ฉันยอมรับว่ามันไม่ควรสำคัญ ฉันแค่แสดงความคิดเห็นเกี่ยวกับสิ่งที่มีอยู่ในฐานรหัสเท่านั้น ฉันจะดูว่าเงื่อนไขที่ OnClose ถูกกำหนดใหม่หรือไม่
Sparky

ฉันไม่แน่ใจว่าคุณเข้าใจ Java - เรียกว่าคลาสภายในที่ไม่ระบุชื่อ
Joseph Earl
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.