मैं वर्चुअल कीबोर्ड दिखाया गया है या नहीं, इसके आधार पर लेआउट को बदलना चाहूंगा। मैंने एपीआई और विभिन्न ब्लॉग खोजे हैं, लेकिन कुछ भी उपयोगी नहीं लगता है।
क्या यह संभव है?
धन्यवाद!
मैं वर्चुअल कीबोर्ड दिखाया गया है या नहीं, इसके आधार पर लेआउट को बदलना चाहूंगा। मैंने एपीआई और विभिन्न ब्लॉग खोजे हैं, लेकिन कुछ भी उपयोगी नहीं लगता है।
क्या यह संभव है?
धन्यवाद!
जवाबों:
यह समाधान सॉफ्ट कीबोर्ड के लिए काम नहीं करेगा और
onConfigurationChanged
इसे सॉफ्ट (वर्चुअल) कीबोर्ड के लिए नहीं बुलाया जाएगा।
आपको कॉन्फ़िगरेशन परिवर्तन स्वयं संभालना है।
http://developer.android.com/guide/topics/resources/runtime-changes.html#HandlingTheChange
नमूना:
// from the link above
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks whether a hardware keyboard is available
if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
Toast.makeText(this, "keyboard visible", Toast.LENGTH_SHORT).show();
} else if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
Toast.makeText(this, "keyboard hidden", Toast.LENGTH_SHORT).show();
}
}
फिर बस कुछ दृश्यों की दृश्यता को बदलें, एक फ़ील्ड अपडेट करें, और अपनी लेआउट फ़ाइल बदलें।
newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO
~ क्रिस
यह सबसे प्रभावी समाधान नहीं हो सकता है। लेकिन इसने मेरे लिए हर बार काम किया ... मैं इस फ़ंक्शन को कॉल करता हूं जहां कभी मुझे सॉफ्टकबोर्ड को सुनने की आवश्यकता होती है।
boolean isOpened = false;
public void setListenerToRootView() {
final View activityRootView = getWindow().getDecorView().findViewById(android.R.id.content);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
if (heightDiff > 100) { // 99% of the time the height diff will be due to a keyboard.
Toast.makeText(getApplicationContext(), "Gotcha!!! softKeyboardup", 0).show();
if (isOpened == false) {
//Do two things, make the view top visible and the editText smaller
}
isOpened = true;
} else if (isOpened == true) {
Toast.makeText(getApplicationContext(), "softkeyborad Down!!!", 0).show();
isOpened = false;
}
}
});
}
नोट: यदि उपयोगकर्ता फ़्लोटिंग कीबोर्ड का उपयोग करता है, तो यह दृष्टिकोण समस्याएँ पैदा करेगा।
android:windowSoftInputMode="adjustPan"
या उसके adjustResize
साथ सेट की गई गतिविधियों के लिए भी काम नहीं करेगा ।
यदि आप अपनी गतिविधि से IMM (वर्चुअल) कीबोर्ड विंडो के शो / हिडन को हैंडल करना चाहते हैं, तो आपको अपने लेआउट को उप-लिंक करना होगा और ऑनमेसर विधि को ओवरराइड करना होगा (ताकि आप मापी गई चौड़ाई और अपने लेआउट की मापित ऊँचाई निर्धारित कर सकें)। उसके बाद सेटक्वेंट व्यू () द्वारा आपकी गतिविधि के लिए मुख्य दृश्य के रूप में उपवर्गित लेआउट सेट करें। अब आप IMM शो / विंडो घटनाओं को छिपाने में सक्षम होंगे। यदि यह जटिल लगता है, तो यह वास्तव में नहीं है। यहाँ कोड है:
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<EditText
android:id="@+id/SearchText"
android:text=""
android:inputType="text"
android:layout_width="fill_parent"
android:layout_height="34dip"
android:singleLine="True"
/>
<Button
android:id="@+id/Search"
android:layout_width="60dip"
android:layout_height="34dip"
android:gravity = "center"
/>
</LinearLayout>
अब आपकी गतिविधि के अंदर आपके लेआउट के लिए उपवर्ग घोषित करें (main.xml)
public class MainSearchLayout extends LinearLayout {
public MainSearchLayout(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.main, this);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.d("Search Layout", "Handling Keyboard Window shown");
final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
final int actualHeight = getHeight();
if (actualHeight > proposedheight){
// Keyboard is shown
} else {
// Keyboard is hidden
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
आप उस कोड से देख सकते हैं जिसे हम सबक्लास कंस्ट्रक्टर में अपनी गतिविधि के लिए लेआउट देते हैं
inflater.inflate(R.layout.main, this);
और अब बस हमारी गतिविधि के लिए उपवर्ग लेआउट का सामग्री दृश्य सेट करें।
public class MainActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MainSearchLayout searchLayout = new MainSearchLayout(this, null);
setContentView(searchLayout);
}
// rest of the Activity code and subclassed layout...
}
android:windowSoftInputMode="adjustPan"
या adjustResize
फुलस्क्रीन विंडो के साथ सेट की गई गतिविधियों के लिए काम नहीं करेगा ।
मैंने इस तरह किया:
OnKeyboardVisibilityListener
इंटरफ़ेस जोड़ें ।
public interface OnKeyboardVisibilityListener {
void onVisibilityChanged(boolean visible);
}
होमअक्टिविटी.जावा :
public class HomeActivity extends Activity implements OnKeyboardVisibilityListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sign_up);
// Other stuff...
setKeyboardVisibilityListener(this);
}
private void setKeyboardVisibilityListener(final OnKeyboardVisibilityListener onKeyboardVisibilityListener) {
final View parentView = ((ViewGroup) findViewById(android.R.id.content)).getChildAt(0);
parentView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
private boolean alreadyOpen;
private final int defaultKeyboardHeightDP = 100;
private final int EstimatedKeyboardDP = defaultKeyboardHeightDP + (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? 48 : 0);
private final Rect rect = new Rect();
@Override
public void onGlobalLayout() {
int estimatedKeyboardHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, EstimatedKeyboardDP, parentView.getResources().getDisplayMetrics());
parentView.getWindowVisibleDisplayFrame(rect);
int heightDiff = parentView.getRootView().getHeight() - (rect.bottom - rect.top);
boolean isShown = heightDiff >= estimatedKeyboardHeight;
if (isShown == alreadyOpen) {
Log.i("Keyboard state", "Ignoring global layout change...");
return;
}
alreadyOpen = isShown;
onKeyboardVisibilityListener.onVisibilityChanged(isShown);
}
});
}
@Override
public void onVisibilityChanged(boolean visible) {
Toast.makeText(HomeActivity.this, visible ? "Keyboard is active" : "Keyboard is Inactive", Toast.LENGTH_SHORT).show();
}
}
आशा है कि यह आपकी मदद करेगा।
Nebojsa Tomcic के कोड के आधार पर मैंने निम्नलिखित RelativeLayout-Subclass विकसित किया है:
import java.util.ArrayList;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
public class KeyboardDetectorRelativeLayout extends RelativeLayout {
public interface IKeyboardChanged {
void onKeyboardShown();
void onKeyboardHidden();
}
private ArrayList<IKeyboardChanged> keyboardListener = new ArrayList<IKeyboardChanged>();
public KeyboardDetectorRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public KeyboardDetectorRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public KeyboardDetectorRelativeLayout(Context context) {
super(context);
}
public void addKeyboardStateChangedListener(IKeyboardChanged listener) {
keyboardListener.add(listener);
}
public void removeKeyboardStateChangedListener(IKeyboardChanged listener) {
keyboardListener.remove(listener);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
final int actualHeight = getHeight();
if (actualHeight > proposedheight) {
notifyKeyboardShown();
} else if (actualHeight < proposedheight) {
notifyKeyboardHidden();
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private void notifyKeyboardHidden() {
for (IKeyboardChanged listener : keyboardListener) {
listener.onKeyboardHidden();
}
}
private void notifyKeyboardShown() {
for (IKeyboardChanged listener : keyboardListener) {
listener.onKeyboardShown();
}
}
}
यह काफी ठीक काम करता है ... निशान, कि यह समाधान बस तब काम करेगा जब आपकी गतिविधि का सॉफ्ट इनपुट मोड "WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE" पर सेट हो
android:windowSoftInputMode="adjustPan"
या उसके adjustResize
साथ सेट की गई गतिविधियों के लिए भी काम नहीं करेगा ।
@ AmalBit के उत्तर की तरह, एक श्रोता को वैश्विक लेआउट में पंजीकृत करें और dectorView के दृश्यमान तल और उसके प्रस्तावित तल के अंतर की गणना करें, यदि अंतर कुछ मान से बड़ा है (IME की ऊँचाई का अनुमान लगाया गया है), हमें लगता है कि IME ऊपर है:
final EditText edit = (EditText) findViewById(R.id.edittext);
edit.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (keyboardShown(edit.getRootView())) {
Log.d("keyboard", "keyboard UP");
} else {
Log.d("keyboard", "keyboard Down");
}
}
});
private boolean keyboardShown(View rootView) {
final int softKeyboardHeight = 100;
Rect r = new Rect();
rootView.getWindowVisibleDisplayFrame(r);
DisplayMetrics dm = rootView.getResources().getDisplayMetrics();
int heightDiff = rootView.getBottom() - r.bottom;
return heightDiff > softKeyboardHeight * dm.density;
}
ऊंचाई सीमा 100 IME की अनुमानित न्यूनतम ऊंचाई है।
यह दोनों समायोजन और समायोजन के लिए काम करता है।
नोबजसा का समाधान मेरे लिए लगभग काम कर गया। जब मैंने एक बहु-पंक्ति EditText के अंदर क्लिक किया, तो यह पता था कि कीबोर्ड प्रदर्शित किया गया था, लेकिन जब मैंने EditText के अंदर लिखना शुरू किया, तो वास्तविक हाइट और प्रस्तावितहाइट अभी भी वही थे, इसलिए यह नहीं पता था कि वे अभी भी प्रदर्शित किए गए थे। मैंने अधिकतम ऊंचाई को स्टोर करने के लिए एक मामूली संशोधन किया और यह ठीक काम करता है। यहाँ संशोधित उपवर्ग है:
public class CheckinLayout extends RelativeLayout {
private int largestHeight;
public CheckinLayout(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.checkin, this);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
largestHeight = Math.max(largestHeight, getHeight());
if (largestHeight > proposedheight)
// Keyboard is shown
else
// Keyboard is hidden
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
यकीन नहीं होता अगर कोई इसे पोस्ट करता है। इस समाधान का उपयोग करने के लिए सरल पाया ! । SoftKeyboard वर्ग gist.github.com पर है । लेकिन कीबोर्ड पॉपअप / ईवेंट कॉलबैक को छिपाने के दौरान हमें UI पर चीजों को ठीक से करने के लिए एक हैंडलर की आवश्यकता होती है:
/*
Somewhere else in your code
*/
RelativeLayout mainLayout = findViewById(R.layout.main_layout); // You must use your root layout
InputMethodManager im = (InputMethodManager) getSystemService(Service.INPUT_METHOD_SERVICE);
/*
Instantiate and pass a callback
*/
SoftKeyboard softKeyboard;
softKeyboard = new SoftKeyboard(mainLayout, im);
softKeyboard.setSoftKeyboardCallback(new SoftKeyboard.SoftKeyboardChanged()
{
@Override
public void onSoftKeyboardHide()
{
// Code here
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
// Code here will run in UI thread
...
}
});
}
@Override
public void onSoftKeyboardShow()
{
// Code here
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
// Code here will run in UI thread
...
}
});
}
});
मैं अपने कस्टम EditText में onKeyPreIme (int keyCode, KeyEvent इवेंट) को ओवरराइड करके इसे हल करता हूं।
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
//keyboard will be hidden
}
}
मेरे पास ऐसा करने के लिए एक हैक है। हालांकि जब नरम कुंजीपटल दिखाए या छिपा दिया है पता लगाने के लिए एक तरीका हो प्रतीत नहीं होता है, तो आप कर सकते हैं वास्तव में पता लगाने जब यह है के बारे में पता चला या नहीं देने के लिए एक निर्धारित करके OnFocusChangeListener
पर EditText
है कि आप करने जा रहे हैं सुनने के।
EditText et = (EditText) findViewById(R.id.et);
et.setOnFocusChangeListener(new View.OnFocusChangeListener()
{
@Override
public void onFocusChange(View view, boolean hasFocus)
{
//hasFocus tells us whether soft keyboard is about to show
}
});
नोट: इस हैक से अवगत होने के लिए एक बात यह है कि इस कॉलबैक को तुरंत निकाल दिया जाता है जब EditText
लाभ या फोकस खो देता है। सॉफ्ट कीबोर्ड शो या हाइड होने से पहले यह वास्तव में सही फायर करेगा । कीबोर्ड शो या हाइड के बाद कुछ करने के लिए मैंने सबसे अच्छा तरीका पाया है कि कुछ का उपयोग करें Handler
और देरी करें ~ 400ms, जैसे:
EditText et = (EditText) findViewById(R.id.et);
et.setOnFocusChangeListener(new View.OnFocusChangeListener()
{
@Override
public void onFocusChange(View view, boolean hasFocus)
{
new Handler().postDelayed(new Runnable()
{
@Override
public void run()
{
//do work here
}
}, 400);
}
});
OnFocusChangeListener
केवल बताता है कि क्या EditText
राज्य बदलने के बाद ध्यान केंद्रित किया गया है। लेकिन ध्यान केंद्रित किया IME
जा सकता है EditText
कि इस मामले का पता कैसे लगाया जाए?
सैंडर, मेरा मानना है कि आप नरम कीबोर्ड द्वारा अवरुद्ध दृश्य को दिखाने की कोशिश कर रहे हैं। यह प्रयास करें http://android-developers.blogspot.com/2009/04/updating-applications-for-on-screen.html ।
मैंने सिंगल लाइन टेक्स्टव्यू बैक कोडिंग पर समस्या का समाधान किया है।
package com.helpingdoc;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
public class MainSearchLayout extends LinearLayout {
int hieght = 0;
public MainSearchLayout(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.main, this);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.d("Search Layout", "Handling Keyboard Window shown");
if(getHeight()>hieght){
hieght = getHeight();
}
final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
final int actualHeight = getHeight();
System.out.println("....hieght = "+ hieght);
System.out.println("....actualhieght = "+ actualHeight);
System.out.println("....proposedheight = "+ proposedheight);
if (actualHeight > proposedheight){
// Keyboard is shown
} else if(actualHeight<proposedheight){
// Keyboard is hidden
}
if(proposedheight == hieght){
// Keyboard is hidden
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
आप पहले डेकोरव्यू के चाइल्ड बॉटम पैडिंग के लिए भी देख सकते हैं। कीबोर्ड दिखाए जाने पर इसे गैर-शून्य मान पर सेट किया जाएगा।
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
View view = getRootView();
if (view != null && (view = ((ViewGroup) view).getChildAt(0)) != null) {
setKeyboardVisible(view.getPaddingBottom() > 0);
}
super.onLayout(changed, left, top, right, bottom);
}
छिपाएँ। कीबोर्ड के लिए शो की घटनाओं को OnGlobalLayoutListener में सरल हैक के माध्यम से सुना जा सकता है:
final View activityRootView = findViewById(R.id.top_root);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
public void onGlobalLayout() {
int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
if (heightDiff > 100) {
// keyboard is up
} else {
// keyboard is down
}
}
});
यहाँ activityRootView आपकी गतिविधि का मूल दृश्य है।
आसानी से कीबोर्ड ईवेंट प्राप्त करने के लिए viewTreeObserver का उपयोग करना ।
layout_parent.viewTreeObserver.addOnGlobalLayoutListener {
val r = Rect()
layout_parent.getWindowVisibleDisplayFrame(r)
if (layout_parent.rootView.height - (r.bottom - r.top) > 100) { // if more than 100 pixels, its probably a keyboard...
Log.e("TAG:", "keyboard open")
} else {
Log.e("TAG:", "keyboard close")
}
}
** लेआउट_परेंट आपके विचार जैसा हैedit_text.parent
नोबजसा टॉमिक का जवाब मेरे लिए मददगार नहीं था। मैं RelativeLayout
के साथ TextView
और AutoCompleteTextView
इसके अंदर। TextView
जब कीबोर्ड दिखाया जाता है और जब वह छिपा होता है, तो मुझे नीचे स्क्रॉल करना होगा। इसे पूरा करने के लिए मैं ओवररोड onLayout
विधि करता हूं और यह मेरे लिए ठीक काम करता है।
public class ExtendedLayout extends RelativeLayout
{
public ExtendedLayout(Context context, AttributeSet attributeSet)
{
super(context, attributeSet);
LayoutInflater inflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.main, this);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
super.onLayout(changed, l, t, r, b);
if (changed)
{
int scrollEnd = (textView.getLineCount() - textView.getHeight() /
textView.getLineHeight()) * textView.getLineHeight();
textView.scrollTo(0, scrollEnd);
}
}
}