X-Git-Url: http://nitlanguage.org diff --git a/lib/android/ui/ui.nit b/lib/android/ui/ui.nit index b655529..1c40827 100644 --- a/lib/android/ui/ui.nit +++ b/lib/android/ui/ui.nit @@ -13,7 +13,10 @@ # limitations under the License. # Views and services to use the Android native user interface -module ui +module ui is + # `adjustPan` allows to use EditText in a ListLayout + android_manifest_activity """android:windowSoftInputMode="adjustPan"""" +end # Implementation note: # @@ -37,18 +40,82 @@ redef class Control type NATIVE: JavaObject end +redef class NativeActivity + + private fun remove_title_bar in "Java" `{ + self.requestWindowFeature(android.view.Window.FEATURE_NO_TITLE); + `} + + # Insert a single layout as the root of the activity window + private fun insert_root_layout(root_layout_id: Int) + in "Java" `{ + android.widget.FrameLayout layout = new android.widget.FrameLayout(self); + layout.setId((int)root_layout_id); + self.setContentView(layout); + `} + + # Replace the currently visible fragment, if any, with `native_fragment` + private fun show_fragment(root_layout_id: Int, native_fragment: Android_app_Fragment) + in "Java" `{ + android.app.FragmentTransaction transaction = self.getFragmentManager().beginTransaction(); + transaction.replace((int)root_layout_id, native_fragment); + transaction.commit(); + `} +end + +redef class App + redef fun on_create + do + app.native_activity.remove_title_bar + native_activity.insert_root_layout(root_layout_id) + super + end + + # Identifier of the container holding the fragments + private var root_layout_id = 0xFFFF + + redef fun window=(window) + do + native_activity.show_fragment(root_layout_id, window.native) + super + end +end + +redef class Activity + redef fun on_back_pressed + do + var window = app.window + if window.enable_back_button then + window.on_back_button + return true + end + + return false + end +end + +# On Android, a window is implemented with the fragment `native` redef class Window - redef var native = app.native_activity.new_global_ref + redef var native = (new Android_app_Fragment(self)).new_global_ref - redef type NATIVE: NativeActivity + redef type NATIVE: Android_app_Fragment + + # Root high-level view of this window + var view: nullable View = null redef fun add(item) do + if item isa View then view = item super + end - # FIXME abstract the Android restriction where `content_view` must be a layout - assert item isa Layout - native.content_view = item.native + private fun on_create_fragment: NativeView + do + on_create + + var view = view + assert view != null else print_error "{class_name} needs a `view` after `Window::on_create` returns" + return view.native end end @@ -150,25 +217,90 @@ redef class TextView native.text = value.to_java_string end - # Size of the text - fun text_size: Float do return native.text_size + redef fun size=(size) do set_size_native(app.native_activity, native, size or else 1.0) - # Size of the text - fun text_size=(text_size: nullable Float) do - if text_size != null then native.text_size = text_size - end + private fun set_size_native(context: NativeContext, view: NativeTextView, size: Float) + in "Java" `{ + int s; + if (size == 1.0d) + s = android.R.style.TextAppearance_Medium; + else if (size < 1.0d) + s = android.R.style.TextAppearance_Small; + else // if (size > 1.0d) + s = android.R.style.TextAppearance_Large; + + view.setTextAppearance(context, s); + `} + + redef fun align=(align) do set_align_native(native, align or else 0.0) + + private fun set_align_native(view: NativeTextView, align: Float) + in "Java" `{ + int g; + if (align == 0.5d) + g = android.view.Gravity.CENTER_HORIZONTAL; + else if (align < 0.5d) + g = android.view.Gravity.LEFT; + else // if (align > 0.5d) + g = android.view.Gravity.RIGHT; + + view.setGravity(g); + `} end redef class Label redef type NATIVE: NativeTextView redef var native do return (new NativeTextView(app.native_activity)).new_global_ref +end + +redef class CheckBox + redef type NATIVE: Android_widget_CompoundButton + redef var native do return (new Android_widget_CheckBox(app.native_activity)).new_global_ref + init do set_callback_on_toggle(native) - init do native.set_text_appearance(app.native_activity, android_r_style_text_appearance_medium) + redef fun is_checked do return native.is_checked + redef fun is_checked=(value) do native.set_checked(value) + + private fun on_toggle do notify_observers new ToggleEvent(self) + + private fun set_callback_on_toggle(view: NATIVE) + import on_toggle in "Java" `{ + final int final_sender_object = self; + CheckBox_incr_ref(final_sender_object); + + view.setOnCheckedChangeListener( + new android.widget.CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(android.widget.CompoundButton buttonView, boolean isChecked) { + CheckBox_on_toggle(final_sender_object); + } + }); + `} end redef class TextInput redef type NATIVE: NativeEditText redef var native = (new NativeEditText(app.native_activity)).new_global_ref + + redef fun is_password=(value) + do + native.is_password = value or else false + super + end +end + +redef class NativeEditText + + # Configure this view to hide passwords + fun is_password=(value: Bool) in "Java" `{ + if (value) { + self.setInputType(android.text.InputType.TYPE_CLASS_TEXT | android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD); + self.setTransformationMethod(android.text.method.PasswordTransformationMethod.getInstance()); + } else { + self.setInputType(android.text.InputType.TYPE_CLASS_TEXT); + self.setTransformationMethod(null); + } + `} end redef class Button @@ -186,6 +318,7 @@ redef class NativeButton private new (context: NativeActivity, sender_object: Button) import Button.on_click in "Java" `{ final int final_sender_object = sender_object; + Button_incr_ref(final_sender_object); return new android.widget.Button(context){ @Override @@ -199,3 +332,19 @@ redef class NativeButton }; `} end + +redef class Android_app_Fragment + private new (nit_window: Window) + import Window.on_create_fragment in "Java" `{ + final int final_nit_window = nit_window; + + return new android.app.Fragment(){ + @Override + public android.view.View onCreateView(android.view.LayoutInflater inflater, + android.view.ViewGroup container, android.os.Bundle state) { + + return Window_on_create_fragment(final_nit_window); + } + }; + `} +end