แก้ไขข้อความโฟกัสชัดเจนเมื่อสัมผัสภายนอก


100

รูปแบบของฉันมีListView, และSurfaceView EditTextเมื่อฉันคลิกที่EditTextมันจะได้รับโฟกัสและแป้นพิมพ์บนหน้าจอจะปรากฏขึ้น เมื่อฉันคลิกที่ใดที่หนึ่งภายนอกEditTextมันยังคงมีโฟกัสอยู่ (ไม่ควร) ฉันเดาว่าฉันสามารถตั้งค่าOnTouchListenerในมุมมองอื่น ๆ ในเค้าโครงและล้างEditTextโฟกัสด้วยตนเองได้ แต่ดูเหมือนแฮ็คเกินไป ...

ฉันยังมีสถานการณ์เดียวกันในเค้าโครงอื่น ๆ - มุมมองรายการที่มีรายการประเภทต่างๆซึ่งบางส่วนมีEditTextอยู่ภายใน พวกเขาทำหน้าที่เหมือนที่ฉันเขียนไว้ข้างต้น

ภารกิจคือการEditTextสูญเสียโฟกัสเมื่อผู้ใช้สัมผัสกับสิ่งที่อยู่ภายนอก

ฉันเคยเห็นคำถามคล้าย ๆ กันที่นี่ แต่ไม่พบวิธีแก้ปัญหาใด ๆ ...

คำตอบ:


67

ฉันลองวิธีแก้ปัญหาเหล่านี้ทั้งหมดแล้ว edc598 นั้นใกล้เคียงกับการทำงานมากที่สุด แต่เหตุการณ์การสัมผัสไม่ได้เรียกใช้ในส่วนอื่น ๆViewที่มีอยู่ในเค้าโครง ในกรณีที่ใครก็ตามต้องการพฤติกรรมนี้นี่คือสิ่งที่ฉันทำ:

ฉันสร้าง (มองไม่เห็น) FrameLayoutเรียกว่าtouchInterceptorเป็นตัวสุดท้ายViewในเลย์เอาต์เพื่อให้มันซ้อนทับทุกอย่าง ( แก้ไข:คุณต้องใช้ a RelativeLayoutเป็นเค้าโครงหลักและให้แอตทริบิวต์touchInterceptor fill_parent ) จากนั้นฉันใช้มันเพื่อสกัดกั้นการสัมผัสและตรวจสอบว่าการสัมผัสนั้นอยู่ด้านบนของEditTextหรือไม่:

FrameLayout touchInterceptor = (FrameLayout)findViewById(R.id.touchInterceptor);
touchInterceptor.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            if (mEditText.isFocused()) {
                Rect outRect = new Rect();
                mEditText.getGlobalVisibleRect(outRect);
                if (!outRect.contains((int)event.getRawX(), (int)event.getRawY())) {
                    mEditText.clearFocus();
                    InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 
                    imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
                }
            }
        }
        return false;
    }
});

ส่งกลับเท็จเพื่อให้การจัดการการสัมผัสผ่านไป

มันแฮ็ก แต่เป็นสิ่งเดียวที่เหมาะกับฉัน


21
คุณสามารถทำสิ่งเดียวกันได้โดยไม่ต้องเพิ่มเค้าโครงเพิ่มเติมโดยการแทนที่ dispatchTouchEvent (MotionEvent ev) ในกิจกรรมของคุณ
pcans

ขอบคุณสำหรับคำใบ้ clearFocus () มันใช้ได้กับฉันใน SearchView
Jimmy Ilenloa

1
ฉันอยากจะบอกใบ้ถึงคำตอบของ @ zMan ด้านล่างนี้ มันขึ้นอยู่กับสิ่งนี้ แต่ไม่ต้องการมุมมองstackoverflow.com/a/28939113/969016
Boy

นอกจากนี้หากใครพบกับสถานการณ์ที่แป้นพิมพ์ไม่ซ่อน แต่การล้างโฟกัสให้เรียกใช้hideSoftInputFromWindow()โฟกัสที่ชัดเจนก่อน
Ahmet Gokdayi

234

จากคำตอบของ Ken นี่คือโซลูชันการคัดลอกและวางแบบแยกส่วนที่สุด

ไม่จำเป็นต้องใช้ XML

ใส่ไว้ในกิจกรรมของคุณและจะนำไปใช้กับ EditTexts ทั้งหมดรวมถึงที่อยู่ภายในส่วนย่อยภายในกิจกรรมนั้น

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        View v = getCurrentFocus();
        if ( v instanceof EditText) {
            Rect outRect = new Rect();
            v.getGlobalVisibleRect(outRect);
            if (!outRect.contains((int)event.getRawX(), (int)event.getRawY())) {
                v.clearFocus();
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
            }
        }
    }
    return super.dispatchTouchEvent( event );
}

12
ดูเหมือนจะดี ฉันยังคงมีปัญหาหนึ่งข้อความแก้ไขทั้งหมดของฉันอยู่ในมุมมองแบบเลื่อนและข้อความแก้ไขด้านบนจะมองเห็นเคอร์เซอร์ได้เสมอ แม้ว่าฉันจะคลิกด้านนอกโฟกัสจะหายไปและแป้นพิมพ์ก็หายไป แต่เคอร์เซอร์ยังคงมองเห็นได้ในข้อความแก้ไขด้านบน
Vaibhav Gupta

1
ทางออกที่ดีที่สุดที่ฉันเจอ !! ก่อนหน้านี้ฉันใช้ @Override บูลีนสาธารณะ onTouch (View v, MotionEvent event) {if (v.getId ()! = search_box.getId ()) {if (search_box.hasFocus ()) {InputMethodManager imm = (InputMethodManager) getSystemService ( Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow (search_box.getWindowToken (), 0); search_box.clearFocus (); } กลับเท็จ; } กลับเท็จ; }
Pradeep Kumar Kushwaha

1
One shot solution :)
karthik kolanji

15
ทางออกที่ดีที่สุดที่ฉันไม่เคยเห็นมาก่อน! ฉันจะบันทึกรหัสนี้ไว้ในส่วนสำคัญของฉันเพื่อส่งต่อไปยังลูกชายและหลานชายของฉัน
Fan Applelin

3
หากผู้ใช้คลิก EditText อื่นคีย์บอร์ดจะปิดและเปิดใหม่ทันที เพื่อแก้ปัญหานี้ฉันเปลี่ยนMotionEvent.ACTION_DOWNเป็นMotionEvent.ACTION_UPรหัสของคุณ คำตอบที่ดี btw!
Thanasis1101

35

สำหรับมุมมองหลักของ EditText ให้แอตทริบิวต์ 3 รายการต่อไปนี้เป็น " true ":
clickable , focusable , focusableInTouchMode focusableInTouchMode

หากมุมมองต้องการรับโฟกัสต้องเป็นไปตามเงื่อนไข 3 ข้อนี้

ดูandroid.view :

public boolean onTouchEvent(MotionEvent event) {
    ...
    if (((viewFlags & CLICKABLE) == CLICKABLE || 
        (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
        ...
        if (isFocusable() && isFocusableInTouchMode()
            && !isFocused()) {
                focusTaken = requestFocus();
        }
        ...
    }
    ...
}

หวังว่าจะช่วยได้


ถูกต้องทั้งหมด: grepcode.com/file/repository.grepcode.com/java/ext/…
AxeEffect

2
ในการล้างโฟกัสมุมมองที่โฟกัสได้อื่น ๆ จะต้องเป็นพาเรนต์ของมุมมองที่โฟกัส จะใช้ไม่ได้หากมุมมองที่จะโฟกัสอยู่บนลำดับชั้นอื่น
AxeEffect

ในทางเทคนิคคำสั่งของคุณไม่ถูกต้อง มุมมองของผู้ปกครองต้องเป็น(clickable) *OR* (focusable *AND* focusableInTouchMode);)
Martin Marconcini

25

เพียงใส่คุณสมบัติเหล่านี้ไว้ในพาเรนต์สูงสุด

android:focusableInTouchMode="true"
android:clickable="true"
android:focusable="true" 

ขอบคุณผู้ชาย. ฉันกำลังดิ้นรนกับปัญหานี้ตั้งแต่สองชั่วโมงที่แล้ว การเพิ่มบรรทัดเหล่านี้ในพาเรนต์ชั้นนำได้ผล
DäñishShärmà

FYI: แม้ว่าจะใช้ได้กับกรณีส่วนใหญ่ แต่ก็ไม่สามารถใช้งานได้กับองค์ประกอบภายในของเค้าโครง
SV Madhava Reddy

17

คำตอบของเคนใช้ได้ แต่แฮ็ค ในขณะที่ pcans พาดพิงถึงในความคิดเห็นของคำตอบสิ่งเดียวกันนี้สามารถทำได้ด้วย dispatchTouchEvent โซลูชันนี้สะอาดกว่าเนื่องจากไม่ต้องแฮ็ก XML ด้วย FrameLayout ที่โปร่งใสและโปร่งใส นี่คือสิ่งที่ดูเหมือน:

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    EditText mEditText = findViewById(R.id.mEditText);
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        View v = getCurrentFocus();
        if (mEditText.isFocused()) {
            Rect outRect = new Rect();
            mEditText.getGlobalVisibleRect(outRect);
            if (!outRect.contains((int)event.getRawX(), (int)event.getRawY())) {
                mEditText.clearFocus();
                //
                // Hide keyboard
                //
                InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 
                imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
            }
        }
    }
    return super.dispatchTouchEvent(event);
}

7

สำหรับฉันด้านล่างสิ่งที่ทำงาน -

1. การเพิ่มandroid:clickable="true"และandroid:focusableInTouchMode="true"ไปparentLayoutของEditTextIEandroid.support.design.widget.TextInputLayout

<android.support.design.widget.TextInputLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clickable="true"
    android:focusableInTouchMode="true">
<EditText
    android:id="@+id/employeeID"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:ems="10"
    android:inputType="number"
    android:hint="Employee ID"
    tools:layout_editor_absoluteX="-62dp"
    tools:layout_editor_absoluteY="16dp"
    android:layout_marginTop="42dp"
    android:layout_alignParentTop="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"
    android:layout_marginRight="36dp"
    android:layout_marginEnd="36dp" />
    </android.support.design.widget.TextInputLayout>

2. การแทนที่dispatchTouchEventในคลาสกิจกรรมและการแทรกhideKeyboard()ฟังก์ชัน

@Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            View view = getCurrentFocus();
            if (view != null && view instanceof EditText) {
                Rect r = new Rect();
                view.getGlobalVisibleRect(r);
                int rawX = (int)ev.getRawX();
                int rawY = (int)ev.getRawY();
                if (!r.contains(rawX, rawY)) {
                    view.clearFocus();
                }
            }
        }
        return super.dispatchTouchEvent(ev);
    }

    public void hideKeyboard(View view) {
        InputMethodManager inputMethodManager =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
        inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }

3. การเพิ่มsetOnFocusChangeListenerEditText

EmployeeId.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (!hasFocus) {
                    hideKeyboard(v);
                }
            }
        });

5

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

สิ่งที่ฉันทำมีดังต่อไปนี้ (นี่เป็นเรื่องทั่วไปมากวัตถุประสงค์คือเพื่อให้คุณทราบวิธีดำเนินการคัดลอกและวางโค้ดทั้งหมดจะไม่ทำงาน O: D):

ขั้นแรกให้ EditText และมุมมองอื่น ๆ ที่คุณต้องการในโปรแกรมของคุณรวมไว้ด้วยมุมมองเดียว ในกรณีของฉันฉันใช้ LinearLayout เพื่อรวมทุกอย่าง

<LinearLayout 
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/mainLinearLayout">
 <EditText
  android:id="@+id/editText"/>
 <ImageView
  android:id="@+id/imageView"/>
 <TextView
  android:id="@+id/textView"/>
 </LinearLayout>

จากนั้นในโค้ดของคุณคุณต้องตั้งค่า Touch Listener เป็น LinearLayout หลักของคุณ

final EditText searchEditText = (EditText) findViewById(R.id.editText);
mainLinearLayout.setOnTouchListener(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            if(searchEditText.isFocused()){
                if(event.getY() >= 72){
                    //Will only enter this if the EditText already has focus
                    //And if a touch event happens outside of the EditText
                    //Which in my case is at the top of my layout
                    //and 72 pixels long
                    searchEditText.clearFocus();
                    InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
                }
            }
            Toast.makeText(getBaseContext(), "Clicked", Toast.LENGTH_SHORT).show();
            return false;
        }
    });

ฉันหวังว่านี่จะช่วยบางคนได้ หรืออย่างน้อยก็ช่วยให้พวกเขาเริ่มแก้ปัญหาได้


ใช่ฉันเจอวิธีแก้ปัญหาที่คล้ายกันด้วย จากนั้นฉันก็พอร์ตระบบมุมมอง Android ส่วนหนึ่งเป็น c ++ บน opengl และสร้างคุณสมบัตินี้ขึ้นมา)
note173

นี่เป็นตัวอย่างที่เรียบร้อยมาก ฉันกำลังมองหารหัสแบบนี้ แต่ทั้งหมดที่ฉันพบคือวิธีแก้ปัญหาที่ซับซ้อน ฉันใช้ทั้งพิกัด XY เพื่อให้แม่นยำยิ่งขึ้นเนื่องจากฉันมี EditText หลายบรรทัดเช่นกัน ขอบคุณ!
สุมิตร

3

เพียงกำหนดคุณสมบัติสองประการของพาเรนต์ของสิ่งนั้นEditTextเป็น:

android:clickable="true"
android:focusableInTouchMode="true"

ดังนั้นเมื่อผู้ใช้จะสัมผัสภายนอก EditTextพื้นที่โฟกัสจะถูกลบออกเนื่องจากโฟกัสจะถูกโอนไปยังมุมมองหลัก


2

ฉันมีListViewประกอบด้วยEditTextมุมมอง สถานการณ์บอกว่าหลังจากแก้ไขข้อความในแถวหนึ่งแถวขึ้นไปเราควรคลิกปุ่มที่เรียกว่า "เสร็จสิ้น" ฉันใช้onFocusChangedกับEditTextมุมมองภายในlistViewแต่หลังจากคลิกที่เสร็จสิ้นข้อมูลจะไม่ถูกบันทึก ปัญหาได้รับการแก้ไขโดยการเพิ่ม

listView.clearFocus();

ภายในonClickListenerปุ่ม "เสร็จสิ้น" และบันทึกข้อมูลเรียบร้อยแล้ว


ขอบคุณ. คุณประหยัดเวลาของฉันฉันมีสถานการณ์นี้ในมุมมองรีไซเคิลและสูญเสียค่า editText ล่าสุดหลังจากคลิกที่ปุ่มเนื่องจากแก้ไขล่าสุดโฟกัสข้อความไม่เปลี่ยนแปลงและอื่น ๆ ไม่ได้เรียก FocusChanged ฉันต้องการค้นหาวิธีแก้ปัญหาที่ทำให้ข้อความแก้ไขล่าสุดสูญเสียโฟกัสเมื่ออยู่นอกนั้นคลิกปุ่มเดียวกัน ... และค้นหาวิธีแก้ปัญหาของคุณ มันทำงานได้ดีมาก!
Reyhane Farshbaf

2

ผมคิดว่ามันเป็นวิธีที่มีประสิทธิภาพมากขึ้นในการใช้มากกว่าgetLocationOnScreen getGlobalVisibleRectเพราะฉันเจอปัญหา มี Listview ที่มี Edittext บางส่วนและและตั้งค่าไว้ajustpanในกิจกรรม ฉันพบว่าgetGlobalVisibleRectส่งคืนค่าที่ดูเหมือนว่ามี scrollY อยู่ด้วย แต่ event.getRawY อยู่ข้างหน้าจอเสมอ รหัสด้านล่างทำงานได้ดี

public boolean dispatchTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        View v = getCurrentFocus();
        if ( v instanceof EditText) {
            if (!isPointInsideView(event.getRawX(), event.getRawY(), v)) {
                Log.i(TAG, "!isPointInsideView");

                Log.i(TAG, "dispatchTouchEvent clearFocus");
                v.clearFocus();
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
            }
        }
    }
    return super.dispatchTouchEvent( event );
}

/**
 * Determines if given points are inside view
 * @param x - x coordinate of point
 * @param y - y coordinate of point
 * @param view - view object to compare
 * @return true if the points are within view bounds, false otherwise
 */
private boolean isPointInsideView(float x, float y, View view) {
    int location[] = new int[2];
    view.getLocationOnScreen(location);
    int viewX = location[0];
    int viewY = location[1];

    Log.i(TAG, "location x: " + location[0] + ", y: " + location[1]);

    Log.i(TAG, "location xWidth: " + (viewX + view.getWidth()) + ", yHeight: " + (viewY + view.getHeight()));

    // point is inside view bounds
    return ((x > viewX && x < (viewX + view.getWidth())) &&
            (y > viewY && y < (viewY + view.getHeight())));
}

ขอบคุณมาก! มันใช้ได้กับทุกสถานการณ์เลย์เอาต์เช่น RecyclerView ฯลฯ ฯลฯ ฉันลองใช้วิธีอื่น แต่อันนี้เหมาะกับทุกคน! :) เยี่ยมมาก!
Woppi

1

หากต้องการสูญเสียโฟกัสเมื่อสัมผัสมุมมองอื่นควรตั้งค่ามุมมองทั้งสองเป็น view.focusableInTouchMode (จริง)

แต่ดูเหมือนว่าไม่แนะนำให้ใช้โฟกัสในโหมดสัมผัส โปรดดูที่นี่: http://android-developers.blogspot.com/2008/12/touch-mode.html


ใช่ฉันอ่านแล้ว แต่มันไม่ตรงกับที่ฉันต้องการ ฉันไม่ต้องการให้มุมมองอื่นกลายเป็นโฟกัส แม้ว่าฉันจะไม่เห็นทางเลือกอื่นในตอนนี้ ... อาจจะทำให้มุมมองรูทเพื่อจับโฟกัสเมื่อผู้ใช้คลิกที่ลูกที่ไม่สามารถโฟกัสได้?
note173

ตราบใดที่ฉันรู้ว่าคลาสไม่สามารถจัดการโฟกัสได้มันถูกจัดการโดย android ... ไม่มีความคิด :(
forumercio

0

วิธีที่ดีที่สุดคือใช้วิธีเริ่มต้น clearFocus()

คุณรู้วิธีแก้รหัสใน onTouchListenerใช่มั้ย?

เพียงโทรEditText.clearFocus(). last EditTextมันจะชัดเจนในการมุ่งเน้น


0

ตามที่ @pcans แนะนำคุณสามารถลบล้างสิ่งนี้dispatchTouchEvent(MotionEvent event)ในกิจกรรมของคุณได้

ที่นี่เราได้รับพิกัดการสัมผัสและเปรียบเทียบเพื่อดูขอบเขต หากสัมผัสนอกมุมมองให้ทำบางอย่าง

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        View yourView = (View) findViewById(R.id.view_id);
        if (yourView != null && yourView.getVisibility() == View.VISIBLE) {
            // touch coordinates
            int touchX = (int) event.getX();
            int touchY = (int) event.getY();
            // get your view coordinates
            final int[] viewLocation = new int[2];
            yourView.getLocationOnScreen(viewLocation);

            // The left coordinate of the view
            int viewX1 = viewLocation[0];
            // The right coordinate of the view
            int viewX2 = viewLocation[0] + yourView.getWidth();
            // The top coordinate of the view
            int viewY1 = viewLocation[1];
            // The bottom coordinate of the view
            int viewY2 = viewLocation[1] + yourView.getHeight();

            if (!((touchX >= viewX1 && touchX <= viewX2) && (touchY >= viewY1 && touchY <= viewY2))) {

                Do what you want...

                // If you don't want allow touch outside (for example, only hide keyboard or dismiss popup) 
                return false;
            }
        }
    }
    return super.dispatchTouchEvent(event);
}

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


0

ข้อมูลโค้ดง่ายๆนี้ทำในสิ่งที่คุณต้องการ

GestureDetector gestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapConfirmed(MotionEvent e) {
                KeyboardUtil.hideKeyboard(getActivity());
                return true;
            }
        });
mScrollView.setOnTouchListener((v, e) -> gestureDetector.onTouchEvent(e));

0

ตั้งอยู่ใน Kotlin

hidekeyboard ()เป็นส่วนขยายของ Kotlin

fun Activity.hideKeyboard() {
    hideKeyboard(currentFocus ?: View(this))
}

ในกิจกรรมให้เพิ่มdispatchTouchEvent

override fun dispatchTouchEvent(event: MotionEvent): Boolean {
    if (event.action == MotionEvent.ACTION_DOWN) {
        val v: View? = currentFocus
        if (v is EditText) {
            val outRect = Rect()
            v.getGlobalVisibleRect(outRect)
            if (!outRect.contains(event.rawX.toInt(), event.rawY.toInt())) {
                v.clearFocus()
                hideKeyboard()
            }
        }
    }
    return super.dispatchTouchEvent(event)
}

เพิ่มคุณสมบัติเหล่านี้ในพาเรนต์สูงสุด

android:focusableInTouchMode="true"
android:focusable="true"

0

นี่คือเวอร์ชันของฉันตามรหัสของ zMan จะไม่ซ่อนแป้นพิมพ์หากมุมมองถัดไปเป็นข้อความแก้ไข นอกจากนี้ยังจะไม่ซ่อนแป้นพิมพ์หากผู้ใช้เพียงแค่เลื่อนหน้าจอ

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        downX = (int) event.getRawX();
    }

    if (event.getAction() == MotionEvent.ACTION_UP) {
        View v = getCurrentFocus();
        if (v instanceof EditText) {
            int x = (int) event.getRawX();
            int y = (int) event.getRawY();
            //Was it a scroll - If skip all
            if (Math.abs(downX - x) > 5) {
                return super.dispatchTouchEvent(event);
            }
            final int reducePx = 25;
            Rect outRect = new Rect();
            v.getGlobalVisibleRect(outRect);
            //Bounding box is to big, reduce it just a little bit
            outRect.inset(reducePx, reducePx);
            if (!outRect.contains(x, y)) {
                v.clearFocus();
                boolean touchTargetIsEditText = false;
                //Check if another editText has been touched
                for (View vi : v.getRootView().getTouchables()) {
                    if (vi instanceof EditText) {
                        Rect clickedViewRect = new Rect();
                        vi.getGlobalVisibleRect(clickedViewRect);
                        //Bounding box is to big, reduce it just a little bit
                        clickedViewRect.inset(reducePx, reducePx);
                        if (clickedViewRect.contains(x, y)) {
                            touchTargetIsEditText = true;
                            break;
                        }
                    }
                }
                if (!touchTargetIsEditText) {
                    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
                }
            }
        }
    }
    return super.dispatchTouchEvent(event);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.