/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.inputmethodservice;

import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.annotation.FractionRes;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.widget.LinearLayout;

A special purpose layout for the editor extract view for tiny (sub 250dp) screens. The layout is based on sizes proportional to screen pixel size to provide for the best layout fidelity on varying pixel sizes and densities.
@hide
/** * A special purpose layout for the editor extract view for tiny (sub 250dp) screens. * The layout is based on sizes proportional to screen pixel size to provide for the * best layout fidelity on varying pixel sizes and densities. * * @hide */
public class CompactExtractEditLayout extends LinearLayout { private View mInputExtractEditText; private View mInputExtractAccessories; private View mInputExtractAction; private boolean mPerformLayoutChanges; public CompactExtractEditLayout(Context context) { super(context); } public CompactExtractEditLayout(Context context, AttributeSet attrs) { super(context, attrs); } public CompactExtractEditLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onFinishInflate() { super.onFinishInflate(); mInputExtractEditText = findViewById(com.android.internal.R.id.inputExtractEditText); mInputExtractAccessories = findViewById(com.android.internal.R.id.inputExtractAccessories); mInputExtractAction = findViewById(com.android.internal.R.id.inputExtractAction); if (mInputExtractEditText != null && mInputExtractAccessories != null && mInputExtractAction != null) { mPerformLayoutChanges = true; } } private int applyFractionInt(@FractionRes int fraction, int whole) { return Math.round(getResources().getFraction(fraction, whole, whole)); } private static void setLayoutHeight(View v, int px) { ViewGroup.LayoutParams lp = v.getLayoutParams(); lp.height = px; v.setLayoutParams(lp); } private static void setLayoutMarginBottom(View v, int px) { ViewGroup.MarginLayoutParams lp = (MarginLayoutParams) v.getLayoutParams(); lp.bottomMargin = px; v.setLayoutParams(lp); } private void applyProportionalLayout(int screenWidthPx, int screenHeightPx) { if (getResources().getConfiguration().isScreenRound()) { setGravity(Gravity.BOTTOM); } setLayoutHeight(this, applyFractionInt( com.android.internal.R.fraction.input_extract_layout_height, screenHeightPx)); setPadding( applyFractionInt(com.android.internal.R.fraction.input_extract_layout_padding_left, screenWidthPx), 0, applyFractionInt(com.android.internal.R.fraction.input_extract_layout_padding_right, screenWidthPx), 0); setLayoutMarginBottom(mInputExtractEditText, applyFractionInt(com.android.internal.R.fraction.input_extract_text_margin_bottom, screenHeightPx)); setLayoutMarginBottom(mInputExtractAccessories, applyFractionInt(com.android.internal.R.fraction.input_extract_action_margin_bottom, screenHeightPx)); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (mPerformLayoutChanges) { Resources res = getResources(); Configuration cfg = res.getConfiguration(); DisplayMetrics dm = res.getDisplayMetrics(); int widthPixels = dm.widthPixels; int heightPixels = dm.heightPixels; // Percentages must be based on the pixel height of the full (apparent) display height // which is sometimes different from display metrics. // // On a round device, a display height smaller than width indicates a chin (cropped // edge of the display) for which there is no screen buffer allocated. This is // typically 25-35px in height. // // getRootWindowInsets() does not function for InputMethod windows (always null). // Instead just set height to match width if less. This is safe because round wear // devices are by definition 1:1 aspect ratio. if (cfg.isScreenRound() && heightPixels < widthPixels) { heightPixels = widthPixels; } applyProportionalLayout(widthPixels, heightPixels); } } }