0

I have a custom View extending from RelativeLayout. It consists of an ImageView, a PullToRefresh View and an EditText. When my app receives push notification from GCM, I use WindowManager to add the custom View. Everything works fine except the fact that when I touch the EditText the Soft Keyboard shows up and covers the EditText, not resizes other views as it should be. I search around the internet, some people had the same problem as me but their solution didn't help me so I'm confused now. Please show me where I did wrong.

Here is my code:

-Add View using WindowManager:

WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                    WindowManager.LayoutParams.WRAP_CONTENT,
                    WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, PixelFormat.TRANSLUCENT);

ChatHeadCancelView chatheadTrashView = new ChatHeadCancelView(this, windowManager, params);

ChatHeadView chatheadView = new ChatHeadView(this, chatheadTrashView, windowManager, params, id);
chatheadView.setOnChatheadClickListener(this);

params.gravity = Gravity.TOP | Gravity.CENTER;
windowManager.addView(chatheadTrashView, params);

params.gravity = Gravity.TOP | Gravity.LEFT;
params.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
params.x = 0;
params.y = 100;
windowManager.addView(chatheadView, params);

Part of my custom View constructor:

public ChatHeadView(Context context, ChatHeadCancelView trashView,
        WindowManager windowManager, WindowManager.LayoutParams params, int id) {
    super(context);
    this.context = context;
    Activity parent = (Activity)this.context;
    // using the activity, get Window reference
    Window window = parent.getWindow();

    window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);

    this.chatheadView = this;
    id = id;

    this.windowManager = windowManager;
    this.params = params;

    this.trashView = trashView;

    LayoutInflater inflater = (LayoutInflater) getContext()
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    inflater.inflate(R.layout.chat_head_fragment_layout, this, true);

    // capture views
    this.primarySenderAvatar = (ImageView) findViewById(R.id.chathead_sender_user_avatar);

    this.chatView = (LinearLayout) findViewById(R.id.chat_view);

    this.chatView.setScaleX(0.0f);
    this.chatView.setScaleY(0.0f);

    ViewGroup.LayoutParams contentParams = chatView.getLayoutParams();
    contentParams.width = getDisplayWidth();
    contentParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
    chatView.setLayoutParams(contentParams);

    getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @SuppressWarnings("deprecation")
        @SuppressLint("NewApi")
        @Override
        public void onGlobalLayout() {
            chatView.setPivotX(findViewById(R.id.chathead_sender_user_avatar).getWidth() / 2);
            if (Build.VERSION.SDK_INT >= 16) {
                getViewTreeObserver().removeOnGlobalLayoutListener(this);
            } else {
                getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
        }
    });

    this.bubbleSpringParams = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_PHONE,
            WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                    | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
            PixelFormat.TRANSLUCENT);
    this.bubbleSpringParams.gravity = Gravity.TOP | Gravity.LEFT;
    this.bubbleSpringParams.x = mPos[0];
    this.bubbleSpringParams.y = mPos[1];
    this.bubbleSpringParams.dimAmount = 0.6f;

    SpringSystem system;
    Spring sBubbleSpring;
    Spring sContentSpring;
    system = SpringSystem.create();
    SpringConfig springConfig = new SpringConfig(sSpringTension, sSpringFriction);

    sContentSpring = system.createSpring();
    sContentSpring.setSpringConfig(springConfig);
    sContentSpring.setCurrentValue(0.0);

    sBubbleSpring = system.createSpring();
    sBubbleSpring.setSpringConfig(springConfig);
    sBubbleSpring.setCurrentValue(1.0);

    this.mPullToRefreshListView = (PullToRefreshListView) findViewById(R.id.list_messages);
    this.postMessageBoxView = (PostMessageBoxView) findViewById(R.id.post_message_layout);
    this.topLayout = (LinearLayout) findViewById(R.id.top_layout);


    this.messageListView = (ListView) mPullToRefreshListView
            .getRefreshableView();
    this.messageListView.setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);

    this.mPullToRefreshListView.setMode(Mode.PULL_FROM_START);
    this.mPullToRefreshListView.setScrollingWhileRefreshingEnabled(false);

    this.messageListView.setAdapter(messageAdapter);
    this.messageListView.setSelection(messageAdapter.getCount() - 1);
    this.messageListView.setCacheColorHint(Color.TRANSPARENT);

    this.setListeners(id, sContentSpring, sBubbleSpring);

    this.removeTrash();

}

After received push notification, I will show the ImageView as a ChatHead. Then when user touch it it will pop up the chat view using Spring:

private void setListeners(final int id, final Spring sContentSpring, final Spring sBubbleSpring) {

    sContentSpring.addListener(new SpringListener() {
        @Override
        public void onSpringUpdate(Spring spring) {
            float value = (float) spring.getCurrentValue();
            float clampedValue = (float) SpringUtil.clamp(value, 0.0, 1.0);
            chatView.setScaleX(value);
            chatView.setScaleY(value);
            chatView.setAlpha(clampedValue);
        }

        @Override
        public void onSpringAtRest(Spring spring) {
            chatView.setLayerType(View.LAYER_TYPE_NONE, null);
            if (spring.currentValueIsApproximately(0.0)) {
                chatView.setVisibility(View.GONE);
            }
        }

        @Override
        public void onSpringActivate(Spring spring) {
            chatView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
        }

        @Override
        public void onSpringEndStateChange(Spring spring) {

        }
    });

    this.primarySenderAvatar.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {

            sBubbleSpring.addListener(new SpringListener() {
                @Override
                public void onSpringUpdate(Spring spring) {
                    double value = spring.getCurrentValue();
                    bubbleSpringParams.x = (int) (SpringUtil.mapValueFromRangeToRange(value, 0.0, 1.0, 0.0, mPos[0]));
                    bubbleSpringParams.y = (int) (SpringUtil.mapValueFromRangeToRange(value, 0.0, 1.0, 0.0, mPos[1]));
                    windowManager.updateViewLayout(chatheadView, bubbleSpringParams);
                    if (spring.isOvershooting() && sContentSpring.isAtRest()) {
                        sContentSpring.setEndValue(1.0);
                    }
                }

                @Override
                public void onSpringAtRest(Spring spring) {

                }

                @Override
                public void onSpringActivate(Spring spring) {

                }

                @Override
                public void onSpringEndStateChange(Spring spring) {

                }
            });

            if (onChatheadListener != null) {
                onChatheadListener.onClick(chatheadView);
            }
            chatView.setVisibility(VISIBLE);
            if (! mbExpanded) {
                getLocationOnScreen(mPos);
                mPos[1] -= 72;
                bubbleSpringParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
                bubbleSpringParams.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
                sBubbleSpring.setEndValue(0.0);
            } else {
                bubbleSpringParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
                bubbleSpringParams.flags &= ~WindowManager.LayoutParams.FLAG_DIM_BEHIND;
                sBubbleSpring.setEndValue(1.0);
                sContentSpring.setEndValue(0.0);
            }
            mbExpanded = ! mbExpanded;
        }
    });

I know my code is clumsy and ugly, I was testing to create a ChatHead. Any help is very much appreciated. Thanks in advanced.

DucTran
  • 68
  • 10

1 Answers1

1

About your problem: You should replace following code:

params.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;

By this:

params.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;

And put your layout in a ScrollView.

Cuong Huynh
  • 159
  • 6
  • Hi Cuong, thanks for your reply. I did change from using 2 input modes to 1 only but it's still the same. My Edittext is behind the keyboard so I have to press back to see what I typed. As for adding Views 2 times, actually I add 2 different views, "trash" is the cancel icon to cancel Chat Heads (like facebook), the other is my Chat Heads. – DucTran Oct 07 '14 at 06:58
  • @DucTran After some testing, I thing you should change code to 1 input mode and put ChatHeadView in a ScrollView. – Cuong Huynh Oct 07 '14 at 07:51