সফট কীবোর্ড থেকে ইন্টারসেপ্ট ব্যাক বোতাম


84

বেশ কয়েকটি ইনপুট ক্ষেত্র সহ আমার ক্রিয়াকলাপ রয়েছে। ক্রিয়াকলাপ শুরু হলে নরম কীবোর্ড প্রদর্শিত হয়। যখন পিছনে বোতাম টিপিত নরম কীবোর্ড বন্ধ হয় এবং ক্রিয়াকলাপ বন্ধ করতে আমাকে আরও একবার ব্যাক বোতাম টিপতে হবে।

সুতরাং প্রশ্ন: কাস্টম তৈরি না করে সফট কীবোর্ড বন্ধ করতে এবং ব্যাক বোতামের একটি প্রেসে ক্রিয়াকলাপ শেষ করতে ব্যাক বোতামটি আটকানো সম্ভব InputMethodService?

PS আমি জানি কীভাবে অন্যান্য ক্ষেত্রে ব্যাক বোতামটি আটকানো যায়: onKeyDown()বা onBackPressed()তবে এটি এই ক্ষেত্রে কার্যকর হয় না: ব্যাক বোতামের কেবল দ্বিতীয় প্রেসটি বাধা দেওয়া হয়।

উত্তর:


78

হ্যাঁ, কীবোর্ডটি দেখানো এবং আড়াল করা এবং পিছনের বোতামে কলগুলি আটকানো সম্পূর্ণভাবে সম্ভব। এটি একটু অতিরিক্ত প্রচেষ্টা হিসাবে এটি উল্লেখ করা হয়েছে যে এপিআইতে এটি করার সরাসরি কোনও উপায় নেই। কীটি boolean dispatchKeyEventPreIme(KeyEvent)একটি বিন্যাসের মধ্যে ওভাররাইড করা হয়। আমরা যা করি তা হল আমাদের বিন্যাস তৈরি করা create এটি আমার ক্রিয়াকলাপের ভিত্তি হওয়ায় আমি রিলেটিভলআউটকে বেছে নিয়েছি।

<?xml version="1.0" encoding="utf-8"?>
<com.michaelhradek.superapp.utilities.SearchLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/com.michaelhradek.superapp"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@color/white">

আমাদের ক্রিয়াকলাপের ভিতরে আমরা আমাদের ইনপুট ক্ষেত্রগুলি সেট আপ করি এবং setActivity(...)ফাংশনটি কল করি ।

private void initInputField() {
    mInputField = (EditText) findViewById(R.id.searchInput);        

    InputMethodManager imm = 
        (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); 
    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 
            InputMethodManager.HIDE_IMPLICIT_ONLY);

    mInputField.setOnEditorActionListener(new OnEditorActionListener() {

        @Override
        public boolean onEditorAction(TextView v, int actionId,
                KeyEvent event) {
            if (actionId == EditorInfo.IME_ACTION_SEARCH) {
                performSearch();
                return true;
            }

            return false;
        }
    });

    // Let the layout know we are going to be overriding the back button
    SearchLayout.setSearchActivity(this);
}

স্পষ্টতই, initInputField()ফাংশনটি ইনপুট ক্ষেত্র সেট আপ করে। এটি কার্যকারিতা (আমার ক্ষেত্রে একটি অনুসন্ধান) চালাতে এন্টার কীটিকে সক্ষম করে।

@Override
public void onBackPressed() {
    // It's expensive, if running turn it off.
    DataHelper.cancelSearch();
    hideKeyboard();
    super.onBackPressed();
}

সুতরাং যখন onBackPressed()আমাদের বিন্যাসের মধ্যে ডাকা হয় তখন আমরা কীবোর্ডটি লুকানোর মতো যা কিছু করতে চাই তা করতে পারি:

private void hideKeyboard() {
    InputMethodManager imm = (InputMethodManager) 
        getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(mInputField.getWindowToken(), 0);
}

যাইহোক, এখানে আমার সম্পর্কিত রিয়েলটিভ লেআউট over

package com.michaelhradek.superapp.utilities;

import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.RelativeLayout;

/**
 * The root element in the search bar layout. This is a custom view just to 
 * override the handling of the back button.
 * 
 */
public class SearchLayout extends RelativeLayout {

    private static final String TAG = "SearchLayout";

    private static Activity mSearchActivity;;

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

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

    public static void setSearchActivity(Activity searchActivity) {
        mSearchActivity = searchActivity;
    }

    /**
     * Overrides the handling of the back key to move back to the 
     * previous sources or dismiss the search dialog, instead of 
     * dismissing the input method.
     */
    @Override
    public boolean dispatchKeyEventPreIme(KeyEvent event) {
        Log.d(TAG, "dispatchKeyEventPreIme(" + event + ")");
        if (mSearchActivity != null && 
                    event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
            KeyEvent.DispatcherState state = getKeyDispatcherState();
            if (state != null) {
                if (event.getAction() == KeyEvent.ACTION_DOWN
                        && event.getRepeatCount() == 0) {
                    state.startTracking(event, this);
                    return true;
                } else if (event.getAction() == KeyEvent.ACTION_UP
                        && !event.isCanceled() && state.isTracking(event)) {
                    mSearchActivity.onBackPressed();
                    return true;
                }
            }
        }

        return super.dispatchKeyEventPreIme(event);
    }
}

দুর্ভাগ্যক্রমে আমি সমস্ত কৃতিত্ব নিতে পারি না। আপনি যদি দ্রুত অনুসন্ধান ডায়ালগ বক্সের জন্য অ্যান্ড্রয়েড উত্সটি পরীক্ষা করেন তবে আপনি দেখতে পাবেন যে ধারণাটি এসেছে।


4
এটি খুব ভাল কাজ করেছে, এবং বাস্তবায়ন করা খুব কঠিন ছিল না (কিছুটা ভীতিজনক সত্ত্বেও)।
সিজার

এর জন্য আপনাকে অনেক ধন্যবাদ, আমি কেবল চাই যে অ্যান্ড্রয়েডের পুরানো সংস্করণগুলির সাথে কাজ করার মতো কিছু পাওয়ার উপায় আমার ছিল।
zidarsk8

4
কোড শুধু কাস্ট করে সরলীকৃত করা যাবে getContext()থেকে Activity। প্রদানের বিন্যাসের প্রসঙ্গটি অবশ্যই প্রশ্নটির ক্রিয়াকলাপ। তবে তা না পারলে আমার জানা নেই।
এমএক্সসিএল

4
স্থিতিশীল অনুসন্ধান অনুসন্ধান - এটি কোনও সমস্যার দ্বারা ভুল গন্ধ পাচ্ছে। আপনার যদি লেআউটে এই দুটি থাকে? পরিবর্তে অ স্থিতিশীল ভেরিয়েবল ব্যবহার করুন।
পয়েন্টার নুল

একটি যাদুমন্ত্র মত কাজ করে. তবে, আমি মনে করি স্থানীয় স্ট্যাটিক ইন্টারফেস ব্যবহার করা এবং স্থিতিশীল অ্যাকটিসিটি ব্যবহার না করে অভ্যন্তরীণ ক্রিয়াকলাপ থেকে এটি প্রয়োগ করা আরও ভাল ...
সর্পিলদেব

81

onKeyDown () এবং onBackPressed () এই ক্ষেত্রে কাজ করে না। আপনাকে অনি কিপ্রিম ব্যবহার করতে হবে ।

প্রাথমিকভাবে, আপনাকে কাস্টম সম্পাদনা পাঠ্য তৈরি করতে হবে যা এডিটেক্সট প্রসারিত করে। এবং তারপরে আপনাকে কী-পেনটাইম পদ্ধতিটি প্রয়োগ করতে হবে যা কী- সেভেন্টকে নিয়ন্ত্রণ করে KEYCODE_BACK । এর পরে, আপনার সমস্যার সমাধানের জন্য এক পিছনে চাপুন। এই সমাধানটি আমার পক্ষে নিখুঁতভাবে কাজ করে।

কাস্টমএডিটটেক্সট.জভা

public class CustomEditText extends EditText {

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

    @Override
    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            // User has pressed Back key. So hide the keyboard
            InputMethodManager mgr = (InputMethodManager)         

           getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
            mgr.hideSoftInputFromWindow(this.getWindowToken(), 0);
            // TODO: Hide your view as you do it in your activity
        }
        return false;
}

আপনার এক্সএমএলে

<com.YOURAPP.CustomEditText
     android:id="@+id/CEditText"
     android:layout_height="wrap_content"
     android:layout_width="match_parent"/> 

আপনার ক্রিয়াকলাপে

public class MainActivity extends Activity {
   private CustomEditText editText;

   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      editText = (CustomEditText) findViewById(R.id.CEditText);
   }
}

4
এই উত্তরটি অনেক পছন্দ। এটি একটি খণ্ডের পাশাপাশি ব্যবহার করা (অনুসন্ধান বারের মধ্যে যা সর্বদা প্রদর্শিত হয় না), এবং সম্পাদনা পাঠ্যটিকে ওভাররাইড করার পরামর্শ দিয়ে, এটি যখন প্রয়োজনীয় তখনই এই আচরণটি সহজেই সংযুক্ত করে তোলে
জাওয়াদ

4
সবার জন্য নোট: এতে একটি দ্রুত ইন্টারফেস যুক্ত করা জীবনকে আরও উন্নত করে তোলে এবং এটি ভাগ্যক্রমে করা খুব সহজ
জাওয়াদ

onKeyPreIme () যা মেইনএকটিভিটি.জভাতে আছে একটি পদ্ধতিতে কল করবেন কীভাবে?
অভিজ্ঞান

ক্রিয়াকলাপে আপনাকে কী-প্লেআইমে কল করার দরকার নেই। আপনি যদি আপনার ক্রিয়াকলাপে কাস্টমএডিটটেক্সট ব্যবহার করেন, আপনি কীবোর্ডের যে কোনও বোতাম টিপলে পদ্ধতিটি ট্রিগার হয়।
অ্যালিকান তেমেল

4
আমি মনে করি এটি সেরা উত্তর, কারণ এটি প্রয়োগ করা আরও অনেক সহজ। আসলে আপনাকে কেবল "কাস্টমএডিটটেক্সট" ক্লাসটি অনুলিপি করতে হবে (এবং আপনার সম্পাদনাটি এক্সএমএলে নতুন নামকরণ করতে হবে) এবং // টডো অঞ্চলে আপনি যা চান তা তৈরি করতে হবে। এবং আপনি যদি আপনার ক্রিয়াকলাপ বন্ধ করতে না চান তবে কেবলমাত্র TODO অঞ্চলে "সত্য প্রত্যাবর্তন করুন" যুক্ত করুন। ধন্যবাদ!
ক্রিসোট্রিব্যাক্স

10

আমি জানতে পেরেছি যে লেআউট ক্লাসের ডিসপ্যাচকিএভেন্টপ্রিম পদ্ধতিটি ওভাররাইড করাও ভাল কাজ করে। কেবলমাত্র আপনার প্রধান ক্রিয়াকলাপকে একটি বৈশিষ্ট্য হিসাবে সেট করুন এবং একটি পূর্বনির্ধারিত পদ্ধতি চালু করুন launch

public class LinearLayoutGradient extends LinearLayout {
    MainActivity a;

    public void setMainActivity(MainActivity a) {
        this.a = a;
    }

    @Override
    public boolean dispatchKeyEventPreIme(KeyEvent event) {
        if (a != null) {
            InputMethodManager imm = (InputMethodManager) a
                .getSystemService(Context.INPUT_METHOD_SERVICE);

            if (imm.isActive() && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
                a.launchMethod;
            }
        }

        return super.dispatchKeyEventPreIme(event);
    }
}

এই লেআউটটির জন্য আপনি কি আমাকে আপনার এক্সএমএল দেখাতে পারেন? আমি এই পদ্ধতিটি যাচাই করার চেষ্টা করছি এবং আমার কাস্টম লেআউটে আমার পৃষ্ঠের দৃষ্টিভঙ্গি রয়েছে, তবে এটি কিছুতেই বাধা দিচ্ছে না
জেডজেডজেড

মূলত কাস্টম ভিউটি হল xML এর পার্শ্ববর্তী উপাদান। <?xml version="1.0" encoding="utf-8"?> <view class="package.LinearLayoutGradient"...
কিরিল রাখমান

এটি কেবলমাত্র যদি আমরা একটি একক দৃষ্টিভঙ্গি প্রসারিত করি এবং এটি ডিসপ্যাচকিএভেন্টপ্রিম () ওভাররাইড করি তবে এটিও কাজ করে। লেআউটটি নিজেই প্রসারিত করার প্রয়োজন হয় না।
ফিজাল

7

ডিসপ্যাচকিএভেন্ট ওভাররাইড করে আমার সাফল্য ছিল :

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
        finish();
        return true;
    }
    return super.dispatchKeyEvent(event);
}

এটি কীবোর্ডটি লুকিয়ে রাখে এবং ক্রিয়াকলাপ শেষ করে।


এটি কেবলমাত্র এইচটিসি ডিজায়ার মতো নির্দিষ্ট ডিভাইসে কাজ করে বলে মনে হচ্ছে।
অভিজিৎ

4
স্যামসাং নোট ২ তে কাজ করে না soft
ফিজাল

ঠিক আছে, আমি এটি Nexus 6 Emulator (Lollipop 5.0) -> দিয়ে কাজ করে এবং নোট 4 (সিএম 12 ললিপপ 5.0.2) - এর সাথে চেষ্টা করেছিলাম -> ঠিক তেমন সমাধান হয়নি - তবে যাইহোক .. ধন্যবাদ :)
মার্টিন ফেফার

কীবোর্ড খারিজ করার সময় বাটন ক্লিক গ্রাস হয়
স্লট

4

আপনি কীভাবে নরম কীবোর্ড দেখাচ্ছে?

আপনি যদি ব্যবহার করে থাকেন তবে আপনি হ্যান্ডেল করতে পেরিয়ে InputMethodManager.showSoftInput()একটি ResultReceiverপ্রয়োগ onReceiveResult()করার চেষ্টা করতে পারেনRESULT_HIDDEN

http://developer.android.com/references/android/view/inputmethod/InputMethodManager.html


ভাল লাগছে, তবে showSoftInput()আমার ফোন এবং এমুলেটরটিতে কীবোর্ড দেখাচ্ছে না, তাই আমি ব্যবহার করিtoggleSoftInput()
সের্গেই গ্লোটোভ

4
আমার জন্য কাজ করে না। @ রিসিপ রিসাল্ট () কে RESULT_SHOWN এর সাথে ডাকা হয়, তবে পরে আর কখনও RESULT_HIDDEN
ইউুলিয়া রোগোভাইয়া

2

আমারও একই সমস্যা ছিল তবে পিছনের কী টিপে বাধা দিয়ে এটিকে ঘিরে ধরলাম। আমার ক্ষেত্রে (এইচটিসি ডিজায়ার, অ্যান্ড্রয়েড 2.2, অ্যাপ্লিকেশন এপিআই স্তর 4) এটি কীবোর্ডটি বন্ধ করে দেয় এবং তত্ক্ষণাত ক্রিয়াকলাপ শেষ করে। কেন জানি এটি আপনার পক্ষে কাজ করে না:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        onBackPressed();
        return true;
    }
    return super.onKeyUp(keyCode, event);
}

/**
 * Called when the activity has detected the user's press of the back key
 */
private void onBackPressed() {
    Log.e(TAG, "back pressed");
    finish();
}

এই স্যামসং আকাশগঙ্গা উল্লেখ্য 2. onkeydown () বা onbackpressed কাজ করে না () আলোড়ন নেই যখন নরম কীবোর্ড দৃশ্যমান এবং ব্যাক বোতাম টেপা হলে
Faizal

1

onKeyPreIme(int keyCode, KeyEvent event)পদ্ধতি ব্যবহার করুন এবং KeyEvent.KEYCODE_BACKইভেন্টের জন্য পরীক্ষা করুন । কোনও অভিনব কোডিং না করে এটি খুব সহজ।


0

আপনার ব্যাকপ্রেস বাস্তবায়নে এই কোডটি ব্যবহার করে দেখুন ( অ্যান্ড্রয়েডে ফিরে আসা বাটনটি ব্লক করুন ):

InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(myEditText.getWindowToken(), 0);

আমি আপনাকে অ্যান্ড্রয়েড সফট কীবোর্ডটি বন্ধ / লুকিয়ে রাখার পরামর্শ দিচ্ছি


4
আমি ইতিমধ্যে এটি চেষ্টা করেছি, তবে এটির পিছনে বোতামটিতে দুটি টিপস দরকার। যেহেতু আমি এটি বুঝতে পারি প্রথম ক্লিকটি নরম কীবোর্ড দ্বারা আটকানো হয় তাই onBackPressed()কাজ করে না। এবং কেবল দ্বিতীয় প্রেস প্রোগ্রামটি পড়ে যায় onBackPressed()
সের্গেই গ্লোটোভ

@ সের্গে গ্লোটোভ আমি সমস্যার জন্য প্রচুর পরামর্শ দিয়েছি এবং শেষ পর্যন্ত এতো ভালো সমাধানের সমাধান নিয়ে এসেছি যেখানে আমাকে নিজের সফটকিবার্ড প্রয়োগ করতে হবে। তবে আমি আশা করি অ্যান্ড্রয়েড সম্প্রদায় খুব শীঘ্রই আরও ভাল সমাধান নিয়ে আসবে।
100rabh

0

আমার @ মিহরেক সমাধানের সংস্করণ:

লেআউট

class BazingaLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
    ConstraintLayout(context, attrs, defStyleAttr) {

var activity: Activity? = null

override fun dispatchKeyEventPreIme(event: KeyEvent): Boolean {
    activity?.let {
        if (event.keyCode == KeyEvent.KEYCODE_BACK) {
            val state = keyDispatcherState
            if (state != null) {
                if (event.action == KeyEvent.ACTION_DOWN
                    && event.repeatCount == 0) {
                    state.startTracking(event, this)
                    return true
                } else if (event.action == KeyEvent.ACTION_UP && !event.isCanceled && state.isTracking(event)) {
                    it.onBackPressed()
                    return true
                }
            }
        }
    }
    return super.dispatchKeyEventPreIme(event)
}

}

এক্সএমএল ফাইল

<com... BazingaLayout 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"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/grey">
 </com... BazingaLayout>

টুকরা

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        (view as BazingaLayout).activity = activity
        super.onViewCreated(view, savedInstanceState)
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.