If you use Evernote android app you might have noticed, that when, on a login screen, soft keyboard gets shown (to type password or username) the layout doesn't just scale, or scrolls. It changes (for example Evernotes logo is hidden).
Unfortunately, android api doesn't provide you with the specific tools to listen for a moment, when soft keyboard gets shown, or hidden. But there is a way (dirty hack) to assume that the keyboards state was changed. We can guess it by listening measure changes in layout. To do it, first, we need to make our layout to resize and scale instaed of scroll. Add android:windowSoftInputMode="adjustResize" parameter to your activity in manifest.xml. This way, when soft keyboard is called, content will be resized instead of scrolled.
Next step is to actually listen for this resizing. And again, there is a catch. There is no such thing as OnMeasureChangedListener , so the only way is to extend the container layout and do it inside. As an example I extended LinearLayout, and this is what I've got:
publicclassMyLayoutextendsLinearLayout{

publicMyLayout(finalContextcontext,finalAttributeSetattrs){
super(context,attrs);
}

publicMyLayout(Contextcontext){
super(context);
}

privateOnSoftKeyboardListeneronSoftKeyboardListener;

@Override
protectedvoidonMeasure(finalintwidthMeasureSpec,finalintheightMeasureSpec){
if(onSoftKeyboardListener!=null){
finalintnewSpec=MeasureSpec.getSize(heightMeasureSpec);
finalintoldSpec=getMeasuredHeight();
// If layout became smaller, that means something forced it to resize. Probably soft keyboard :)
if(oldSpec>newSpec){
onSoftKeyboardListener.onShown();
}else{
onSoftKeyboardListener.onHidden();
}
}
super.onMeasure(widthMeasureSpec,heightMeasureSpec);
}

publicfinalvoidsetOnSoftKeyboardListener(finalOnSoftKeyboardListenerlistener){
this.onSoftKeyboardListener=listener;
}

// Simplest possible listener :)
publicinterfaceOnSoftKeyboardListener{
publicvoidonShown();
publicvoidonHidden();
}
}


That's about it. Of course you need to use your layout (MyLayout) in your code/xml for it to work. And example from activity:

((MyLayout)findViewById(R.id.layout)).setOnSoftKeyboardListener(newOnSoftKeyboardListener(){
@Override
publicvoidonShown(){
// Do something here
}
@Override
publicvoidonHidden(){
// Do something here
}
});

P.S. It works pretty well as it is. But you should check it for different situations. For example screen rotations, or other possible changes in the layout, that might trigger resize of any sort.
=======================================================文二=====================================================

There might be better approaches, but a possibility is to add:android:configChanges="keyboardHidden"to the manifest. That will fire with any keyboard changes, so the you will need to query theConfigurationobject

static Configuration prevConf = Configuration(); static int ignoreMasks = Configuration.HARDKEYBOARDHIDDEN_NO|Configuration.HARDKEYBOARDHIDDEN_YES; onCreate() { prevConf = setToDefaults(); } // all your code here @Override public void onConfigurationChanged (Configuration newConfig) { int deltas = newConfig.diff (prevConf); // what changed? prevConf = newConfig; if (delta & ignoreMasks) return; // you're not interested in hard keyboards. // your code here  }

I suck at bitwise operators, so you might need to work around that.

This is the API documentation:

http://developer.android.com/reference/android/R.attr.html#configChanges

http://developer.android.com/reference/android/app/Activity.html#onConfigurationChanged%28android.content.res.Configuration%29

http://developer.android.com/reference/android/content/res/Configuration.html

================================================文三==============================================================

Since writing the below answer, someone clued me in to the existence ofViewTreeObserverand friends, APIs which have been lurking in the SDK since version 1.

Rather than requiring a custom Layout type, a much simpler solution is to give your activity's root view a known ID, say '@+id/activityRoot', hook a GlobalLayoutListener into the ViewTreeObserver, and from there calculate the size diff between your activity's view root and the window size:

final View activityRootView = findViewById(R.id.activityRoot); activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight(); if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard... ... do something here } } });

Easy!

ORIGINAL ANSWER

Yes it's possible, but it's far harder than it ought to be.

If I need to care about when the keyboard appears and disappears (which is quite often) then what I do is customize my top-level layout class into one which overridesonMeasure(). The basic logic is that if the layout finds itself filling significantly less than the total area of the window, then a soft keyboard is probably showing.

import android.app.Activity; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.widget.LinearLayout; /* * LinearLayoutThatDetectsSoftKeyboard - a variant of LinearLayout that can detect when * the soft keyboard is shown and hidden (something Android can't tell you, weirdly). */ public class LinearLayoutThatDetectsSoftKeyboard extends LinearLayout { public LinearLayoutThatDetectsSoftKeyboard(Context context, AttributeSet attrs) { super(context, attrs); } public interface Listener { public void onSoftKeyboardShown(boolean isShowing); } private Listener listener; public void setListener(Listener listener) { this.listener = listener; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int height = MeasureSpec.getSize(heightMeasureSpec); Activity activity = (Activity)getContext(); Rect rect = new Rect(); activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect); int statusBarHeight = rect.top; int screenHeight = activity.getWindowManager().getDefaultDisplay().getHeight(); int diff = (screenHeight - statusBarHeight) - height; if (listener != null) { listener.onSoftKeyboardShown(diff>128); // assume all soft keyboards are at least 128 pixels high } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }

Then in your Activity class...

public class MyActivity extends Activity implements LinearLayoutThatDetectsSoftKeyboard.Listener { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... LinearLayoutThatDetectsSoftKeyboard mainLayout = (LinearLayoutThatDetectsSoftKeyboard)findViewById(R.id.main); mainLayout.setListener(this); ... } @Override public void onSoftKeyboardShown(boolean isShowing) { // do whatever you need to do here } ... }
29
This wasn't working for me until I realized that you must set the following attribute on your activity: android:windowSoftInputMode="adjustResize"– ajh158 May 13 '11 at 19:28
7
Seems to be doing the trick. Also, if you don't know the root view's ID, here's how you can get the view:((ViewGroup) findViewById(android.R.id.content)).getChildAt(0)– Goldsmith Jan 26 '12 at 13:20
3
increased if (heightDiff > 200) to 200... 100 didnt work for me tested it on QVGA (wildfire etc) devices, works as well .. :)– cV2 Apr 14 '12 at 23:56
5
If you try this using theactualroot view (android.R.id.content) you will be able to more confidently say that theSystemrather than your application is the entity changing it's height. Would be much safer for the Android team to give us a break and let us know at least basic things about the SoftKeyboard input.– Graeme Jul 30 '12 at 10:06
4
Beware thatheightDiffwill always include the height of the action bar. In the new answer that has been ignored by testing if that height is greater than some constant, but 100 pixels is not sufficient for xxhdpi devices such as the Nexus 4. Consider converting that value to DPs if you really want to use this hacky work-around.– Paul Lammertsma Jan 3 '13 at 10:41

更多相关文章

  1. 代码中设置drawableleft
  2. android 3.0 隐藏 系统标题栏
  3. Android开发中activity切换动画的实现
  4. Android(安卓)学习 笔记_05. 文件下载
  5. Android中直播视频技术探究之—摄像头Camera视频源数据采集解析
  6. 技术博客汇总
  7. android 2.3 wifi (一)
  8. AndRoid Notification的清空和修改
  9. Android中的Chronometer

随机推荐

  1. Android(安卓)微信支付
  2. ListView的Adapter使用 之 初学ArrayAdap
  3. [置顶] Android之SharedPreferences两个
  4. 处理JNI ERROR (app bug): accessed stal
  5. 使用zipalign对齐应用程序
  6. Android面试常客之Handler全解
  7. Android(安卓)应用中十大常见 UX 错误
  8. Android欢迎界面,一个Activity搞定
  9. Android(安卓)学习之路 之 第2组UI组件:Te
  10. 定制Android关机界面