After upgrading to Gradle 2.3. My project cannot compile. I'm having the log in the console
incompatible types: ObservableInt cannot be converted to int
Look at the generated file
android.databinding.ObservableInt viewModelLoadingVisibility;
this.vLoading.getRoot().setVisibility(viewModelLoadingVisibility);
In xml file
<android.support.v7.widget.RecyclerView
android:id="#+id/rvProducts"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:visibility="#{viewModel.contentVisibility}"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
/>
I tried in method in my binding class
#BindingAdapter("app:visibility")
public static void setViewVisible(View view, ObservableInt visible) {
int visibility = visible.get();
view.setVisibility(visibility);
}
and got log
warning: Application namespace for attribute app:visibility will be ignored.
public static void setViewVisible(View view, ObservableInt visible) {
warning: Use of ObservableField and primitive cousins directly as method parameters is deprecated and support will be removed soon. Use the contents as parameters instead in method public static void setViewVisible(android.view.View,android.databinding.ObservableInt)
public static void setViewVisible(View view, ObservableInt visible) {
Anyone encounters this?
This looks like a bug. Please file it. There are many tests and we don't expect this kind of regression. It is important that we get your specific example so we can be sure it is caught.
You can ignore the warnings for now.
The first is caused because of this:
#BindingAdapter("app:visibility")
You should use this instead:
#BindingAdapter("visibility")
The second is because we support ObservableInt as a parameter. You typically don't want to accept ObservableInt, but rather int instead. I'd love to see use cases where ObservableInt is necessary. We may just remove that warning and support it always or we may pull the plug on supporting ObservableInt as a parameter if there are no valid uses.
----- edit -----
I tested this with a little application and I didn't have any issue without any BindingAdapter. Here is the layout:
<layout>
<data>
<variable name="model" type="com.example.gmount.testobservableint.MyModel"/>
</data>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:onClick="#{model::clicked}"
tools:context="com.example.gmount.testobservableint.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:visibility="#{model.visibility}"
/>
</android.support.constraint.ConstraintLayout>
</layout>
Here is my model:
public class MyModel {
public final ObservableInt visibility = new ObservableInt(View.VISIBLE);
public void clicked(View view) {
int oldVisibility = visibility.get();
int newVisibility = oldVisibility == View.VISIBLE ? View.GONE : View.VISIBLE;
visibility.set(newVisibility);
}
}
Even when I used a BindingAdapter taking an ObservableInt, it worked. Here's my BindingAdapter:
#BindingAdapter("visiblity")
public static void setVisibility(View view, ObservableInt visibility) {
view.setVisibility(visibility.get());
}
And I changed the View's binding to be:
<TextView ...
app:visibility="#{model.visibility}"
/>
Is there something different about your viewModel?
You just have to add this to the bottom of your build.gradle dependencies:
apt 'com.android.databinding:compiler:2.3.0'
See this: https://stackoverflow.com/a/42711830/376829 regarding GoMobile update to version "+eb90329 Mar 7 2017" and GoBind plugin revert to version "0.2.6" (although the current version is "0.2.8")
android:visibility="#{viewModel.contentVisibility}"
remember this
dataBinding {
enabled = true
}
re-download the library from the Support repository in the Android SDK manager.
Related
The Code A and Code B are from the project https://github.com/android/databinding-samples.
The Code B display an icon based fun popularityIcon(view: ImageView, popularity: Popularity) and works well.
I find that project can still work well even if I rename #BindingAdapter("app:popularityIcon") to #BindingAdapter("myok:popularityIcon"), just like Code C, why?
Code A
object BindingAdapters {
#BindingAdapter("app:popularityIcon")
#JvmStatic fun popularityIcon(view: ImageView, popularity: Popularity) {
val color = getAssociatedColor(popularity, view.context)
ImageViewCompat.setImageTintList(view, ColorStateList.valueOf(color))
view.setImageDrawable(getDrawablePopularity(popularity, view.context))
}
...
}
Code B
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="24dp"
android:layout_marginTop="24dp"
android:contentDescription="#string/profile_avatar_cd"
android:minHeight="48dp"
android:minWidth="48dp"
app:layout_constraintBottom_toTopOf="#+id/likes_label"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintVertical_chainStyle="packed"
app:popularityIcon="#{viewmodel.popularity}"/>
Code C
object BindingAdapters {
#BindingAdapter("myok:popularityIcon")
#JvmStatic fun popularityIcon(view: ImageView, popularity: Popularity) {
val color = getAssociatedColor(popularity, view.context)
ImageViewCompat.setImageTintList(view, ColorStateList.valueOf(color))
view.setImageDrawable(getDrawablePopularity(popularity, view.context))
}
...
}
Databinding ignores namespaces. So it removes app: or myok: or anything else. Also, if you put both adapters with the same name but different namespaces, you would get an error telling you that there are more than one adapter for popularityIcon.
You can check the docs for more information.
Note: The Data Binding Library ignores custom namespaces for matching purposes.
you need to update your namespace in your XML were you using this binding.
like below
xmlns:myok="http://schemas.android.com/apk/res-auto"
check below code
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:myok="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
...
</androidx.constraintlayout.widget.ConstraintLayout>
While reading on Lint tool I tried to test it on a simple project in android studio. Just created a new project with empty activity. The xml for the mainActivity is as below:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
and Mainactivity.java :
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
From android studio when I try to run Analyze>>Inspect Code>> the whole project; it shows the following in inspection result: inspection result image
Shouldn't it also be showing the warning for hard-coded text("Hello World!") which is used for TextViews text?
As I wasn't getting the warning so I tried to change the severity level in settings>> editor>>Inspection as shown in this image. But still, the inspection result is the same. No warning or errors.
Where am I going wrong?
This happens because the string Hello World! is a special case:
if (value == "Hello World!") {
// This is the default text in new templates. Users are unlikely to
// leave this in, so let's not add warnings in the editor as their
// welcome to Android development greeting.
return
}
Found a reason which is weird. If I move the exclamation sign from the text("Hello World!") then it shows the error/warning. For some reason with the exclamation sign added to the text Lint doesn't show a warning for hardcoded text.
I am designing an cross-platform app for iOS aswell Android with a shared logic using MVVMCross (5.1.1).
Throughout my app I have a fixed toolbar at the top displaying the current view's title aswell a button. Below the bar the interface is changing from view to view
The Android part:
On Android I created a reuseable layout which I embed in my current layout using include.
In my portable project I have a BaseViewModel which has the properties the reuseable toolbar layout binds to. Every other ViewModel derives from this base class. This way I can have all bindable properties of a displayed screen in one ViewModel without the need of nesting but see for yourself:
activity_login.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar_login" />
<RelativeLayout
android:id="#+id/parentLoginLayout"
android:clickable="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/toolbar">
<EditText
android:layout_width="match_parent"
android:layout_height="match_parent"
app:MvxBind="Text Pin"
/>
</RelativeLayout>
</RelativeLayout>
toolbar_login.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/toolbar_login"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="0dp"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
android:minWidth="25px"
android:minHeight="25px">
<TextView
app:MvxBind="Click ToolbarMenuCommand"
/>
<!-- some other -->
</android.support.v7.widget.Toolbar>
ViewModels.cs
using System.Threading.Tasks;
using Mobile.Helpers;
using ViewModels.Base;
using MvvmCross.Core.Navigation;
using MvvmCross.Core.ViewModels;
using Plugin.MessageBox;
namespace Mobile.ViewModels
{
public abstract class BaseViewModel : MvxViewModel
{
protected void NavigateToMainView()
{
NavigateTo<MainViewModel>();
}
private readonly IMvxNavigationService _navigationService;
protected BaseViewModel(IMvxNavigationService navigationService)
{
_navigationService = navigationService;
}
public IMvxCommand ToolbarMenuCommand => new MvxCommand(OnMenuButtonClick);
protected abstract void OnMenuButtonClick();
}
public class LoginViewModel : BaseViewModel
{
private bool _menuVisibility;
private string _pin;
public LoginViewModel(IMvxNavigationService navigationService) : base(navigationService)
{
}
public bool MenuVisibility
{
get => _menuVisibility;
set => SetProperty(ref _menuVisibility, value);
}
public string Pin
{
get => _pin;
set => SetProperty(ref _pin, value);
}
protected override void OnMenuButtonClick()
{
MenuVisibility = !MenuVisibility;
}
}
}
The iOS part:
I am not entirely sure how to realise above behavior on iOS. I hope someone has a good idea or a good example project for me which I can take a look at. In general it is no problem to refactorise the ViewModels incase my idea is just not possible at iOS.
A few facts about the iOS project:
I am not using storyboards but single .xib's being independent
from each other
In my .xib's files I use autolayout constraints for positioning and
sizing entirely
A few ideas I already had (cant test them right now):
1. idea:
Create a base .xib with the above bar, the constraints aswell the
outlets
Create each new xib Design based on the previously created file
This would mean I need to adjust every view incase I decide to change something about the toolbar but so far I found no other way to embed a .xib in another .xib without having two different ViewControllers. Also I read that inheritance cause problems with outlets.
2. idea
Each .xib has an empty view at the top which acts as a container for
the toolbar
Have a Base ViewController which constructs the toolbar from code and
adds it as a child to the container view, and binds the properties
from the BaseViewModel
In a previous iOS project I noticed that adding views to the layout can cause problems with autolayout. Probably also a not that good solution?
3. idea
Create a xib with the toolbar and a container below and use it as a master page which would probably mean having a MasterViewModel with the toolbar properties and a nested ChildViewModel.
This is probably the way to go but I have to admit that I have no clue what is the best way to approach it (stil pretty new to iOS and MVVMCross).
Does someone have a few useful hints for me? Thanks a lot!
From what I understood I think you should try to use ScrollView for iOS part and try to imitate the ViewPager's behavior from Android, an example.
I have a library with an LegendActivity using layout legend.xml which references a view with id "icons". Now, in my app, I subclass this activity with "AppLegendActivity" and use the app's overriding legend.xml which does not include any view with id "icons".
Library
public class LegendActivity extends Activity {
#Override
public void onCreate(Bundle b) {
setContentView(R.layout.legend);
View icons_view = findViewById(R.id.icons);
}
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="#+id/icons"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
App
public class AppLegendActivity extends LegendActivity {
#Override
public void onCreate(Bundle b) {
super.onCreate(Bundle b);
View app_icons_view = findViewById(R.id.app_icons);
}
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="#+id/app_icons"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
This is an over-simplification of my actual code, but this is the crux of the problem. When I run pro-guard I get the following error:
Warning: com.example.activity.LegendActivity: can't find referenced field 'int icons' in program class com.example.R$id
If I add the "-dontwarn" flag in proguard, I can get the app to compile, but as soon as the AppLegendActivity calls super.onCreate, the reference to R.id.icons gets called and the app crashes with:
ava.lang.NoSuchFieldError: com.example.r.icons
App's build.grade referencing proguard section:
buildTypes {
release {
// Proguard
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
My proguard-rules.pro
-dontwarn com.example.**
Can this code be re-factored to avoid this crash? Yes. Can I simply rename a few resources files and get this conflict to go away? Sure. But in the actual project, this much more complicated and I don't know the full extend of the implications of such a refactor. Is there a way to get the library's R file to not remove/obfuscate IDs that are no longer visible after the app's overriding of resources?
In AppLegendActivity class you override LegendActivity you need change setContentView(R.layout.....); or remove super.onCreate(Bundle b);
I'm having a tough time getting a basic MvvmCross Android example working where the BackgroundColor of the RelativeLayout is bound to the ViewModel.
The app runs, some text appears, and I'm expecting my background to turn Yellow. The background color, however, remains unchanged.
I have included the Hot Tuna starter pack in both my Core and Droid projects as well as the MvvmCross - Color Plugin. My Droid project was automatically given ColorPluginBootstrap.cs
Layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
local:MvxBind="BackgroundColor NativeColor(BackgroundColor)">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textSize="20sp"
android:gravity="center"
android:text="Text to make sure the layout inflates" />
</RelativeLayout>
ViewModel
public class ViewModel : MvxViewModel
{
RGBAColorConverter _rgbaConverter;
public ViewModel()
{
var color = "#ffedff00";
_rgbaConverter = new RGBAColorConverter();
BackgroundColor = _rgbaConverter.Convert(color);
}
private MvxColor _backgroundColor;
public MvxColor BackgroundColor
{
get { return _backgroundColor; }
set
{
_backgroundColor = value;
RaisePropertyChanged(() => BackgroundColor);
}
}
}
Binding works - I've tried making other ViewModel properties that were string to do simple text binding. All of that seems just fine.
I've placed debugging break points on the getter of the BackgroundColor ViewModel property and I can see the MvxColor as expected.
What am I missing for my color binding scenario?
I haven't done anything extra in the Setup.cs
I haven't created any other wiring up classes in my Droid project
I haven't created any Android-specific color converter implementations
I've just written a test app and it seems to work for me - using 3.0.14 nuget binaries.
Also, the ValueConverters test app seemed to work OK - https://github.com/MvvmCross/MvvmCross-Tutorials/tree/master/ValueConversion
Looking at your sample, the only thing I can think of is that maybe you are only testing transparent colours (RGBA #ffedff00 has Alpha=0)
If that isn't it, can you post more - perhaps a full sample somewhere?