Custom view updating content of another view - android

I have the following situation:
in the main file I do
setContentView(R.layout.main);
which looks as follows:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/layout"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/result"
android:text="Gesamtstrecke: 0.0"
/>
<test.gustav.Spielfeld
android:id="#+id/spielfeld"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</test.gustav.Spielfeld>
</LinearLayout>
the View "test.gustav.Spielfeld" refers to a class "Spielfeld" extending "View".
I now need a method that updates the content of the TextView with id "result" if a something happens in the onTouchEvent(..)-method in the Spielfeld-View.
How to do this? I've tried making a public TextView in the Main-Class but the Spielfeld class won't accept Main.this.myTextView.

I would recommend a callback approach (just like android does for all events):
Create a interface which represents the callback:
public interface OnSpielfeldUpdate {
public void onSpielfeldUpdate(Object myEventData, ...);
}
Provide a setter for the callback in SpielFeld (which will be used to send updates):
public void setOnSpielfeldUpdate(OnSpielfeldUpdate callback) {
this.callback = callback;
}
Set your callback in your activity (or somewhere else):
mySpielfeld.setOnSpielfeldUpdate(new OnSpielfeldUpdate() {
public void onSpielfeldUpdate(Object myEventData, ...) {
// perform update on result view
}
}

Related

Binding event not firing on Adapter

I am following Android Archt. component to build a project. Following the guidelines I have created a custom Adapter named CataloguesAdapter extending DataBoundListAdapter as :
public class CataloguesAdapter extends DataBoundListAdapter<CatalogueEntity, CatalogueItemBinding> {
private final android.databinding.DataBindingComponent dataBindingComponent;
private final ContributorClickCallback callback;
private CatalogueItemBinding mBinding;
public CataloguesAdapter(DataBindingComponent dataBindingComponent,
ContributorClickCallback callback) {
this.dataBindingComponent = dataBindingComponent;
this.callback = callback;
}
#Override
protected CatalogueItemBinding createBinding(ViewGroup parent) {
mBinding = DataBindingUtil
.inflate(LayoutInflater.from(parent.getContext()),
R.layout.catalogue_item, parent, false,
dataBindingComponent);
//while this click event is working fine
mBinding.getRoot().setOnClickListener(v -> {
CatalogueEntity catalogueEntity = mBinding.getCatalogue();
if (catalogueEntity != null && callback != null) {
callback.onClick(catalogueEntity);
}
});
//todo:not working, this event is not firing
mBinding.deleteIcon.setOnClickListener(v-> callback.onItemDelete());
return mBinding;
}
}
I am implementing swipe to delete layout on Recycler view item. Below is the XML layout of list item:
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<variable
name="catalogue"
type="com.mindtree.igxbridge.traderapp.datasource.local.entity.CatalogueEntity" />
</data>
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardUseCompatPadding="true">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="#+id/view_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorRed">
<ImageView
android:id="#+id/delete_icon"
android:layout_width="#dimen/dimen_30_dp"
android:layout_height="#dimen/dimen_30_dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="#dimen/dimen_10_dp"
app:srcCompat="#drawable/ic_delete"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginEnd="#dimen/dimen_10_dp"
android:layout_toStartOf="#id/delete_icon"
android:text="#string/text_delete"
android:textColor="#color/Material.87.white"
android:textSize="14sp" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/view_foreground"
android:layout_width="match_parent"
android:background="#FFFFFF"
android:layout_height="wrap_content">
<android.support.v7.widget.AppCompatImageView
android:id="#+id/arrow_icon"
android:layout_width="#dimen/dimen_30_dp"
android:layout_height="#dimen/dimen_30_dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="#dimen/dimen_10_dp"
app:srcCompat="#drawable/ic_arrow_right" />
</RelativeLayout>
</FrameLayout>
</android.support.v7.widget.CardView>
</layout>
Another operation like swipe left/right is working fine but clicking on Delete button event is not getting called.
I tried checking findViewbyId and register click event by that, but no luck with that too.
While CatalogueItemBinding is registered correctly, I am not able to find any other source of error.
Thanks.
Correct me if I have misunderstood your code. You used a FrameLayout to host two relative layouts one top of each other (foreground and background). The delete button is in the background and foreground has match_parent in its width attribute. Therefore, I think the delete button is getting covered by the foreground, leading to "not firing of the event".
Possible Solution
Try incorporating the delete button in the foreground. It makes sense to put UI components in the front.
I think you forget to tell your adapter class to where your XML is set or not to adapter class. just create a variable in XML which will import your adapter class have look.
<variable
name="myAdapter"
type="import your adapter class">
</variable>
Now set this variable to your adapter.
#Override
protected CatalogueItemBinding createBinding(ViewGroup parent) {
mBinding = DataBindingUtil
.inflate(LayoutInflater.from(parent.getContext()),
R.layout.catalogue_item, parent, false,
dataBindingComponent);
mBinding .setmyAdapter(this);
return mBinding;
}
}
then your click will work. Hope it will help you.

Mvvm cross binding data context

I am trying to implement a mvvm cross solution. I am facing an issue with bindings..
I am trying to implement the solution in xamarin.android.
Below is my Main Layout page - Main.axml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
local:MvxBind="Text Title/>
<Mvx.MvxListView
android:id="#+id/SRMTypeList"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:fastScrollEnabled="true"
local:MvxItemTemplate="#layout/list_Item"
local:MvxBind="ItemsSource PersonCollection" />
</LinearLayout>
Below is my View Model:
public class MainViewModel :MvxViewModel
{
private string title;
public String Title
{
get{ return title;}
set
{
title = value;
RaisePropertyChanged (()=> Title);
}
}
List<Person> _personCollection;
List<Person> PersonCollection
{
get { return _personCollection; }
set
{
_personCollection = value;
RaisePropertyChanged (() => PersonCollection);
}
public MainViewModel()
{
_personCollection = new List<Person>();
PersonCollection.Add(new Person{Name="Steve", Salary=10000});
PersonCollection.Add(new Person{Name="Mary", Salary=20000});
}
}
MainView.cs
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
SetContentView (Resource.Layout.Main);
}
The issue starts here in the item template for my list view in the main screen list_Item.axml is shown below:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<CheckBox
android:id="#+id/checkbox2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
local:MvxBind="?" />
<TextView
android:textColor="#fff"
android:textSize="16sp"
local:MvxBind="?"/>
</LinearLayout>
How to make the binding for TextView's Text and CheckBox to parent's view model (ie. in the Main View Model class)?.
Any pointer/ help to solve this will be highly appreciated.
I have gone through below links .. but being a newbie was not able to understand the implementation.
Binding button click in ListView template MvvMCross
MVVMCross changing ViewModel within a MvxBindableListView
I am not able to understand how to create the wrapper class and how to set the data context of the item template (list_Item.axml) to this wrapper class.
Is their any way in mvvm cross so that i can refer bindings in the item template directly to the parent view model in my case which is MainViewModel.
Can anyone kindly post a simpler example?
Thanks
I'm not sure if that's what you are asking, but to make a binding of the person's name to the listitem textview:
local:MvxBind="Text Name"
And instead of using a List you should use an ObservableCollection
ObservableCollection<Person> _personCollection;
ObservableCollection<Person> PersonCollection
{
get { return _personCollection; }
set
{
_personCollection = value;
RaisePropertyChanged (() => PersonCollection);
}
}
For the checkbox i would add a field to the Person class such as IsSelected and bind it to the checkbox:
local:MvxBind="Checked IsSelected"

Android Custom ListView Rows: Text Style not being applied

Trying to create custom rows in my listview (to look like this). I've created a custom row layout & derived adapter class. The data loads and shows fine, but the text is not using any format/style specified in my custom row .xml layout file. It's all just the default size/weight, etc.
Here's the custom row layout (listview_desc.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#222222">
<TextView
android:id="#+id/name"
android:text="Name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_margin="10dip"
android:textStyle="bold"
android:textSize="20dip"
/>
<TextView
android:id="#+id/description"
android:text="Description"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_margin="10dip"
android:textSize="13dip" />
</LinearLayout>
Here's my main layout file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:theme="#android:style/Theme.NoTitleBar"
android:minWidth="25px"
android:minHeight="25px"
android:background="#drawable/gradient_darkbg">
<ListView
android:minWidth="25px"
android:minHeight="25px"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/listView1" />
</LinearLayout>
My adapter code (I'm using Xamarin, but I don't think that's the problem...)
public class ListViewFormAdapter : BaseAdapter<Form>
{
List<Form> mForms;
Activity context;
public ListViewFormAdapter(Activity context, List<Form> items)
: base()
{
this.context = context;
this.mForms = items;
}
public override long GetItemId(int position)
{
return position;
}
public override Form this[int position]
{
get { return mForms[position]; }
}
public override int Count
{
get { return mForms.Count; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var item = mForms[position];
View view = convertView;
if (view == null) // no view to re-use, create new
view = context.LayoutInflater.Inflate(Resource.Layout.listview_desc, null);
view.FindViewById<TextView>(Resource.Id.name).Text = item.Name;
view.FindViewById<TextView>(Resource.Id.description).Text = item.Description;
return view;
}
}
And finally the main activity where I load and use the adapter:
public class HomeScreenActivity : Activity
{
List<Form> mForms;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Create your application here
SetContentView (Resource.Layout.Home);
// Load all forms and populate the main menu
mForms = Utils.FormLoader.LoadForms("Forms");
ListView listView = FindViewById<ListView>(Resource.Id.listView1);
listView.Adapter = new ListViewFormAdapter(this, mForms);
}
}
Sorry for all the code, maybe it'll help someone in the future... thanks for any help.
I'm not sure that this is the problem, but you inflating the views incorrectly. it should be
view = inflater.inflate(R.layout.listview_desc, parent, false);
instead of
view = context.LayoutInflater.Inflate(Resource.Layout.listview_desc, null);
using the 3 parameter version of inflate
What styles aren't showing correctly? I'm not sure what you're expecting or what you're seeing from the question. If it is to do with alignment, you should bear in mind that android:layout_alignParentLeft="true" is not valid in a LinearLayout
Thanks for the response guys. Turns out it was some problem with Git/Xamarin. I committed my sources at another machine, came home, synced up and all my formatting in the row layout xml were gone. Who knows... maybe a cached version was being used or something. I actually had to use the code posted on this page to get it to work (since it was lost), so maybe someone can use this as example code. It works.

FindViewByID(...) returns null after setting content view and cleaning project

There are a number of questions like this but the solutions haven't worked for me.
Anyways, my main activity has a button that, in its onclick method, takes me to another activity, ViewPowerActivity. I have a layout xml file for it called power_view.xml. Inside that I have some layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/screen_margin"
android:layout_marginRight="#dimen/screen_margin"
android:layout_marginTop="#dimen/screen_margin"
android:orientation="vertical" >
...
ViewPowerActivity has the basic onCreateMethod:
public class ViewPowerActivity extends Activity {
private final static Powers powers=new StubPowers();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.power_view);
Power power=powers.getPowers().get(0);
View powerView = findViewById(R.layout.power_view);
...
}
...
}
The findViewById call above is returning null.
If I remove all the code after setContentView(...) and simply return there, it displays the empty layout just fine. I've setContentView, I've cleaned the project, I've tried setting the power view as the main activity, and all sorts of things. What else could it be?
From you code it is clear thar power_view is a layout ie. xml. So R.id.power_view is incorrect.
It seems you want to access the parent view of that layout. Then do the following.
You have to set an id to the parent LinearLayout.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/parentLinear"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/screen_margin"
android:layout_marginRight="#dimen/screen_margin"
android:layout_marginTop="#dimen/screen_margin"
android:orientation="vertical" >
...
Then,
View powerView = findViewById(R.id.parentLinear);
If you want to take some other view in powerView, you should set id to that view in xml layout and initialize your that view to power_view by findViewById(R.id.your_view)
power_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/screen_margin"
android:layout_marginRight="#dimen/screen_margin"
android:layout_marginTop="#dimen/screen_margin"
android:orientation="vertical" >
public class ViewPowerActivity extends Activity {
private final static Powers powers=new StubPowers();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.power_view);
Power power=powers.getPowers().get(0);
View powerView = (ViewGroup)findViewById(R.id.layout);
...
}
...
}

Communication between custom SurfaceView and default android's views

My problem is communication between custom GameView (extends SurfaceView) and TextView: I want to set TextView's text from inside of the GameView.
In main activity i'm using this layout file, it should explain structure of my app:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#00ff00"
>
<TextView
android:id="#+id/scoreTV"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="score: 0"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="back"
android:layout_alignParentRight="true" />
</RelativeLayout>
<org.gk.grApp.GameView
android:id="#+id/gameplayScreen"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
I can't change TextView's text in my GameView object, because it's impossible to touch UI thread from another.
Handler doesn't work too, because i can't give a handler's reference to GameView's constructor, that is performed after loading this xml file (a read about default constructor for xml files eg here How can I use GLSurfaceView in a LinearLayout together with other Views, such as TextView or Button?).
Do you have any idea what I should do now? Maybe my deduction is wrong, so please, tell me about this.
EDIT: I changed my xml file, instead of GameView I have now:
<LinearLayout
android:id="#+id/gameplayScreen"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
</LinearLayout>
Also I added an argument (third) into constructor's signature:
public GameView(Context context, AttributeSet as, Handler h) { ... }
and changed my onCreate in GameplayActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gameplay);
LinearLayout ll = (LinearLayout)findViewById(R.id.gameplayScreen);
GV = new GameView(this, null, scoreHandler);
ll.addView(GV);
}
It works, now I can set TextView's text but after clicking on the back button another exception is thrown:
"Performing pause of activity that is not resumed: {org.gk.grApp/org.gk.grApp.MainMenuActivity}". I just started searching information about this.
First make a reference to the TextView on the activity level:
TextView txv;
In onCreate assign this reference:
txv = (TextView) findViewById(R.id.MyTextView);
Then make a method in your Activity after onCreate like this:
public void setTextView(final String txt){
MyActivity.this.runOnUiThread(new Runnable() {
public void run() {
txv.setText(txt);
}
});
}
Then you make a call from your custom view:
((MyActivity) getContext()).setTextView(str);

Categories

Resources