Converter

This commit is contained in:
serso 2016-02-10 17:41:32 +01:00
parent a327a9b97b
commit 441ccdfc8a
8 changed files with 309 additions and 445 deletions

View File

@ -67,6 +67,7 @@ dependencies {
compile('ch.acra:acra:4.7.0') {
exclude group: 'org.json'
}
compile ':measure:'
compile ':drag-button:1.1@aar'
compile ':square-otto:1.3.9-SNAPSHOT'
apt ':square-otto-compiler:1.3.9-SNAPSHOT'

BIN
app/misc/libs/measure.jar Normal file

Binary file not shown.

View File

@ -45,7 +45,6 @@ import org.solovyev.android.calculator.calculations.CalculationFailedEvent;
import org.solovyev.android.calculator.calculations.CalculationFinishedEvent;
import org.solovyev.android.calculator.errors.FixableErrorsActivity;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.calculator.view.NumeralBaseConverterDialog;
import dagger.Lazy;
import jscl.math.Generic;
@ -264,7 +263,8 @@ public class Display implements CalculatorEventListener, View.OnClickListener, V
return true;
case R.string.c_convert:
if (result != null) {
new NumeralBaseConverterDialog(result.toString()).show(App.getApplication());
// FIXME: 2016-02-10
//new NumeralBaseConverterDialog(result.toString()).show(App.getApplication());
}
return true;
case R.string.c_plot:

View File

@ -24,10 +24,17 @@ package org.solovyev.android.calculator;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.*;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import org.solovyev.android.calculator.converter.ConverterFragment;
import butterknife.Bind;
import butterknife.ButterKnife;
import org.solovyev.android.calculator.view.NumeralBaseConverterDialog;
import javax.annotation.Nonnull;
import javax.inject.Inject;
@ -99,7 +106,7 @@ public class EditorFragment extends BaseFragment {
Locator.getInstance().getPlotter().plot();
return true;
case R.id.menu_conversion_tool:
new NumeralBaseConverterDialog(null).show(getActivity());
ConverterFragment.show(getActivity());
return true;
case R.id.menu_about:
launcher.showAbout();

View File

@ -0,0 +1,252 @@
package org.solovyev.android.calculator.converter;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.TextInputLayout;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AlertDialog;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import org.solovyev.android.Check;
import org.solovyev.android.calculator.App;
import org.solovyev.android.calculator.BaseDialogFragment;
import org.solovyev.android.calculator.R;
import butterknife.Bind;
import butterknife.ButterKnife;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.measure.unit.Dimension;
import javax.measure.unit.NonSI;
import javax.measure.unit.SI;
import javax.measure.unit.Unit;
public class ConverterFragment extends BaseDialogFragment
implements AdapterView.OnItemSelectedListener, View.OnClickListener,
MenuItem.OnMenuItemClickListener {
private static final Map<MyDimension, List<Unit<?>>> units = new HashMap<>();
private enum MyDimension {
TIME(Dimension.TIME, "Time"),
AMOUNT_OF_SUBSTANCE(Dimension.AMOUNT_OF_SUBSTANCE, "Amount of substance"),
ELECTRIC_CURRENT(Dimension.ELECTRIC_CURRENT, "Electric current"),
LENGTH(Dimension.LENGTH, "Length"),
MASS(Dimension.MASS, "Mass"),
TEMPERATURE(Dimension.TEMPERATURE, "Temperature");
@NonNull
public final Dimension dimension;
@NonNull
public final String name;
MyDimension(@NonNull Dimension dimension, @NonNull String name) {
this.dimension = dimension;
this.name = name;
}
@Nullable
public static MyDimension getByDimension(@NonNull Unit<?> unit) {
for (MyDimension myDimension : values()) {
if (myDimension.dimension.equals(unit.getDimension())) {
return myDimension;
}
}
return null;
}
@Nullable
public static MyDimension getByGroup(int group) {
final int ordinal = group - Menu.FIRST;
final MyDimension[] values = values();
if (ordinal >= 0 && ordinal < values.length) {
return values[ordinal];
}
return null;
}
public int group() {
return Menu.FIRST + ordinal();
}
}
@Bind(R.id.converter_spinner_from)
Button spinnerFrom;
@Bind(R.id.converter_label_from)
TextInputLayout labelFrom;
@Bind(R.id.converter_edittext_from)
EditText editTextFrom;
@Bind(R.id.converter_spinner_to)
Spinner spinnerTo;
@Bind(R.id.converter_label_to)
TextInputLayout labelTo;
@Bind(R.id.converter_edittext_to)
EditText editTextTo;
private ArrayAdapter<Unit<?>> adapterTo;
private static void addUnit(@NonNull Unit<?> unit) {
final MyDimension dimension = MyDimension.getByDimension(unit);
if (dimension == null) {
return;
}
List<Unit<?>> unitsInDimension = units.get(dimension);
if (unitsInDimension == null) {
unitsInDimension = new ArrayList<>();
units.put(dimension, unitsInDimension);
}
unitsInDimension.add(unit);
}
public static void show(@Nonnull FragmentActivity activity) {
App.showDialog(new ConverterFragment(), "converter",
activity.getSupportFragmentManager());
}
@Override
protected void onPrepareDialog(@NonNull AlertDialog.Builder builder) {
}
@SuppressLint("InflateParams")
@Nullable
@Override
protected View onCreateDialogView(@NonNull Context context, @NonNull LayoutInflater inflater,
@Nullable Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.cpp_unit_converter, null);
ButterKnife.bind(this, view);
adapterTo = makeAdapter(context);
spinnerTo.setAdapter(adapterTo);
spinnerFrom.setOnClickListener(this);
return view;
}
@Nonnull
private static ArrayAdapter<Unit<?>> makeAdapter(@NonNull Context context) {
final ArrayAdapter<Unit<?>> adapter =
new ArrayAdapter<>(context, R.layout.support_simple_spinner_dropdown_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
return adapter;
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
adapterTo.clear();
/*final Unit<?> unitFrom = adapterFrom.getItem(position);
final List<Unit<?>> units = ConverterFragment.units.get(unitFrom.getDimension());
for (Unit<?> unitTo : units) {
if (!unitTo.equals(unitFrom)) {
adapterTo.add(unitTo);
}
}*/
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.converter_spinner_from:
showDimensions();
break;
}
}
private void showDimensions() {
spinnerFrom.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenu.ContextMenuInfo menuInfo) {
Check.isTrue(v.getId() == R.id.converter_spinner_from);
menu.clear();
// can't use sub-menus as AlertDialog doesn't support them
for (MyDimension dimension : units.keySet()) {
menu.add(Menu.NONE, dimension.group(), Menu.NONE, dimension.name)
.setOnMenuItemClickListener(ConverterFragment.this);
}
unregisterForContextMenu(spinnerFrom);
}
});
spinnerFrom.showContextMenu();
}
@Override
public boolean onMenuItemClick(MenuItem item) {
if (item.getGroupId() == Menu.NONE) {
final MyDimension dimension = MyDimension.getByGroup(item.getItemId());
if (dimension == null) {
return false;
}
spinnerFrom.post(new Runnable() {
@Override
public void run() {
showUnits(dimension);
}
});
return true;
}
final MyDimension dimension = MyDimension.getByGroup(item.getGroupId());
final List<Unit<?>> unitsInDimension = units.get(dimension);
final Unit<?> unit = unitsInDimension.get(item.getItemId());
spinnerFrom.setText(unit.toString());
adapterTo.clear();
for (Unit<?> unitInDimension : unitsInDimension) {
if (!unitInDimension.equals(unit)) {
adapterTo.add(unitInDimension);
}
}
return true;
}
private void showUnits(@NonNull final MyDimension dimension) {
spinnerFrom.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenu.ContextMenuInfo menuInfo) {
Check.isTrue(v.getId() == R.id.converter_spinner_from);
menu.clear();
final int group = dimension.group();
final List<Unit<?>> get = units.get(dimension);
for (int i = 0; i < get.size(); i++) {
final Unit<?> unit = get.get(i);
menu.add(group, i, Menu.NONE, unit.toString())
.setOnMenuItemClickListener(ConverterFragment.this);
}
unregisterForContextMenu(spinnerFrom);
}
});
spinnerFrom.showContextMenu();
}
static {
for (Unit<?> unit : SI.getInstance().getUnits()) {
addUnit(unit);
}
for (Unit<?> unit : NonSI.getInstance().getUnits()) {
addUnit(unit);
}
}
}

View File

@ -1,118 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* 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.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator.view;
import android.content.Context;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.view.WindowManager;
import org.solovyev.android.calculator.App;
import org.solovyev.android.calculator.Locator;
import org.solovyev.android.calculator.ParseException;
import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.ToJsclTextProcessor;
import org.solovyev.android.calculator.units.CalculatorNumeralBase;
import org.solovyev.common.MutableObject;
import org.solovyev.common.text.Strings;
import org.solovyev.common.units.Unit;
import org.solovyev.common.units.UnitImpl;
import java.util.Arrays;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class NumeralBaseConverterDialog {
@Nullable
private String initialFromValue;
public NumeralBaseConverterDialog(@Nullable String initialFromValue) {
this.initialFromValue = initialFromValue;
}
public void show(@Nonnull Context context) {
final UnitConverterViewBuilder b = new UnitConverterViewBuilder();
b.setFromUnitTypes(Arrays.asList(CalculatorNumeralBase.values()));
b.setToUnitTypes(Arrays.asList(CalculatorNumeralBase.values()));
if (!Strings.isEmpty(initialFromValue)) {
String value = initialFromValue;
try {
value = ToJsclTextProcessor.getInstance().process(value).getValue();
b.setFromValue(UnitImpl.newInstance(value, CalculatorNumeralBase.valueOf(Locator.getInstance().getEngine().getMathEngine().getNumeralBase())));
} catch (ParseException e) {
b.setFromValue(UnitImpl.newInstance(value, CalculatorNumeralBase.valueOf(Locator.getInstance().getEngine().getMathEngine().getNumeralBase())));
}
} else {
b.setFromValue(UnitImpl.newInstance("", CalculatorNumeralBase.valueOf(Locator.getInstance().getEngine().getMathEngine().getNumeralBase())));
}
b.setConverter(CalculatorNumeralBase.getConverter());
final MutableObject<AlertDialog> alertDialogHolder = new MutableObject<AlertDialog>();
b.setOkButtonOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final AlertDialog alertDialog = alertDialogHolder.getObject();
if (alertDialog != null) {
alertDialog.dismiss();
}
}
});
b.setCustomButtonData(new UnitConverterViewBuilder.CustomButtonData(context.getString(R.string.c_use_short), new UnitConverterViewBuilder.CustomButtonOnClickListener() {
@Override
public void onClick(@Nonnull Unit<String> fromUnits, @Nonnull Unit<String> toUnits) {
String toUnitsValue = toUnits.getValue();
if (!toUnits.getUnitType().equals(CalculatorNumeralBase.valueOf(Locator.getInstance().getEngine().getMathEngine().getNumeralBase()))) {
toUnitsValue = ((CalculatorNumeralBase) toUnits.getUnitType()).getNumeralBase().getJsclPrefix() + toUnitsValue;
}
Locator.getInstance().getKeyboard().buttonPressed(toUnitsValue);
final AlertDialog alertDialog = alertDialogHolder.getObject();
if (alertDialog != null) {
alertDialog.dismiss();
}
}
}));
final AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context, App.getTheme().alertDialogTheme);
alertBuilder.setView(b.build(context));
alertBuilder.setTitle(R.string.c_conversion_tool);
final AlertDialog alertDialog = alertBuilder.create();
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.copyFrom(alertDialog.getWindow().getAttributes());
lp.width = WindowManager.LayoutParams.FILL_PARENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
alertDialogHolder.setObject(alertDialog);
alertDialog.show();
alertDialog.getWindow().setAttributes(lp);
}
}

View File

@ -1,253 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* 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.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator.view;
import android.app.Activity;
import android.content.Context;
import android.text.ClipboardManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import org.solovyev.android.calculator.R;
import org.solovyev.android.view.ViewBuilder;
import org.solovyev.android.view.ViewFromLayoutBuilder;
import org.solovyev.common.units.ConversionException;
import org.solovyev.common.units.Conversions;
import org.solovyev.common.units.Unit;
import org.solovyev.common.units.UnitConverter;
import org.solovyev.common.units.UnitImpl;
import org.solovyev.common.units.UnitType;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 4/20/12
* Time: 4:50 PM
*/
public class UnitConverterViewBuilder implements ViewBuilder<View> {
@Nonnull
private List<? extends UnitType<String>> fromUnitTypes = Collections.emptyList();
@Nonnull
private List<? extends UnitType<String>> toUnitTypes = Collections.emptyList();
@Nullable
private Unit<String> fromValue;
@Nonnull
private UnitConverter<String> converter = UnitConverter.Dummy.getInstance();
@Nullable
private View.OnClickListener okButtonOnClickListener;
@Nullable
private CustomButtonData customButtonData;
private static void doConversion(@Nonnull View main, @Nonnull Context context, @Nonnull UnitConverter<String> converter) {
final EditText fromEditText = (EditText) main.findViewById(R.id.units_from);
final EditText toEditText = (EditText) main.findViewById(R.id.units_to);
final String from = fromEditText.getText().toString();
try {
toEditText.setText(Conversions.doConversion(converter, from, getFromUnitType(main), getToUnitType(main)));
} catch (ConversionException e) {
toEditText.setText(context.getString(R.string.c_error));
}
}
@Nonnull
private static Unit<String> getToUnit(@Nonnull View main) {
final EditText toUnits = (EditText) main.findViewById(R.id.units_to);
return UnitImpl.newInstance(toUnits.getText().toString(), getToUnitType(main));
}
@Nonnull
private static UnitType<String> getToUnitType(@Nonnull View main) {
final Spinner toSpinner = (Spinner) main.findViewById(R.id.unit_types_to);
return (UnitType<String>) toSpinner.getSelectedItem();
}
@Nonnull
private static Unit<String> getFromUnit(@Nonnull View main) {
final EditText fromUnits = (EditText) main.findViewById(R.id.units_from);
return UnitImpl.newInstance(fromUnits.getText().toString(), getFromUnitType(main));
}
@Nonnull
private static UnitType<String> getFromUnitType(@Nonnull View main) {
final Spinner fromSpinner = (Spinner) main.findViewById(R.id.unit_types_from);
return (UnitType<String>) fromSpinner.getSelectedItem();
}
public void setFromUnitTypes(@Nonnull List<? extends UnitType<String>> fromUnitTypes) {
this.fromUnitTypes = fromUnitTypes;
}
public void setToUnitTypes(@Nonnull List<? extends UnitType<String>> toUnitTypes) {
this.toUnitTypes = toUnitTypes;
}
public void setFromValue(@Nullable Unit<String> fromValue) {
this.fromValue = fromValue;
}
public void setConverter(@Nonnull UnitConverter<String> converter) {
this.converter = converter;
}
public void setOkButtonOnClickListener(@Nullable View.OnClickListener okButtonOnClickListener) {
this.okButtonOnClickListener = okButtonOnClickListener;
}
public void setCustomButtonData(@Nullable CustomButtonData customButtonData) {
this.customButtonData = customButtonData;
}
@Nonnull
@Override
public View build(@Nonnull final Context context) {
final View main = ViewFromLayoutBuilder.newInstance(R.layout.cpp_unit_converter).build(context);
final Spinner fromSpinner = (Spinner) main.findViewById(R.id.unit_types_from);
final EditText fromEditText = (EditText) main.findViewById(R.id.units_from);
fromEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
doConversion(main, context, UnitConverterViewBuilder.this.converter);
}
});
fillSpinner(main, context, R.id.unit_types_from, fromUnitTypes);
fillSpinner(main, context, R.id.unit_types_to, toUnitTypes);
if (fromValue != null) {
fromEditText.setText(fromValue.getValue());
int i = fromUnitTypes.indexOf(fromValue.getUnitType());
if (i >= 0) {
fromSpinner.setSelection(i);
}
}
final Button copyButton = (Button) main.findViewById(R.id.unit_converter_copy_button);
copyButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final EditText toEditText = (EditText) main.findViewById(R.id.units_to);
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
clipboard.setText(toEditText.getText().toString());
Toast.makeText(context, context.getText(R.string.c_result_copied), Toast.LENGTH_SHORT).show();
}
});
final Button okButton = (Button) main.findViewById(R.id.unit_converter_ok_button);
if (okButtonOnClickListener == null) {
((ViewGroup) okButton.getParent()).removeView(okButton);
} else {
okButton.setOnClickListener(this.okButtonOnClickListener);
}
final Button customButton = (Button) main.findViewById(R.id.unit_converter_custom_button);
if (customButtonData == null) {
((ViewGroup) customButton.getParent()).removeView(customButton);
} else {
customButton.setText(customButtonData.text);
customButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
customButtonData.clickListener.onClick(getFromUnit(main), getToUnit(main));
}
});
}
return main;
}
private void fillSpinner(@Nonnull final View main,
@Nonnull final Context context,
final int spinnerId,
@Nonnull List<? extends UnitType<String>> unitTypes) {
final Spinner spinner = (Spinner) main.findViewById(spinnerId);
final ArrayAdapter<UnitType<String>> adapter = new ArrayAdapter<UnitType<String>>(context, R.layout.support_simple_spinner_dropdown_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
for (UnitType<String> fromUnitType : unitTypes) {
adapter.add(fromUnitType);
}
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
doConversion(main, context, UnitConverterViewBuilder.this.converter);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
spinner.setAdapter(adapter);
}
public interface CustomButtonOnClickListener {
void onClick(@Nonnull Unit<String> fromUnits, @Nonnull Unit<String> toUnits);
}
public static class CustomButtonData {
@Nonnull
private String text;
@Nonnull
private CustomButtonOnClickListener clickListener;
public CustomButtonData(@Nonnull String text, @Nonnull CustomButtonOnClickListener clickListener) {
this.text = text;
this.clickListener = clickListener;
}
}
}

View File

@ -22,88 +22,63 @@
~ Site: http://se.solovyev.org
-->
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
a:layout_width="fill_parent"
a:layout_height="fill_parent"
a:orientation="vertical"
a:paddingLeft="10dp"
a:paddingRight="10dp">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
a:layout_width="fill_parent"
a:layout_height="fill_parent"
a:orientation="horizontal"
a:paddingBottom="10dp">
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:paddingBottom="10dp">
<Spinner
a:id="@+id/unit_types_from"
a:layout_width="wrap_content"
a:layout_height="fill_parent" />
<Button
android:id="@+id/converter_spinner_from"
android:layout_width="wrap_content"
android:layout_height="match_parent"
style="?android:attr/spinnerStyle" />
<EditText
a:id="@+id/units_from"
a:layout_width="fill_parent"
a:layout_height="fill_parent"
a:inputType="text"
a:singleLine="true" />
<android.support.design.widget.TextInputLayout
android:id="@+id/converter_label_from"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/converter_edittext_from"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:inputType="text"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>
<LinearLayout
a:layout_width="fill_parent"
a:layout_height="fill_parent"
a:orientation="horizontal"
a:paddingBottom="10dp">
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:paddingBottom="10dp">
<Spinner
a:id="@+id/unit_types_to"
a:layout_width="wrap_content"
a:layout_height="fill_parent" />
android:id="@+id/converter_spinner_to"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
<EditText
a:id="@+id/units_to"
a:layout_width="fill_parent"
a:layout_height="fill_parent"
a:editable="false"
a:inputType="none"
a:singleLine="true" />
<android.support.design.widget.TextInputLayout
android:id="@+id/converter_label_to"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</LinearLayout>
<LinearLayout
a:layout_width="fill_parent"
a:layout_height="fill_parent"
a:gravity="center"
a:orientation="horizontal"
a:paddingBottom="10dp">
<Button
a:id="@+id/unit_converter_copy_button"
a:layout_width="wrap_content"
a:layout_height="wrap_content"
a:paddingLeft="15dp"
a:paddingRight="15dp"
a:singleLine="true"
a:text="@android:string/copy" />
<Button
a:id="@+id/unit_converter_custom_button"
a:layout_width="wrap_content"
a:layout_height="wrap_content"
a:ellipsize="end"
a:paddingLeft="15dp"
a:paddingRight="15dp"
a:singleLine="true" />
<Button
a:id="@+id/unit_converter_ok_button"
a:layout_width="wrap_content"
a:layout_height="wrap_content"
a:paddingLeft="15dp"
a:paddingRight="15dp"
a:singleLine="true"
a:text="@android:string/ok" />
<EditText
android:id="@+id/converter_edittext_to"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:editable="false"
android:inputType="none"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>