Xamarin.Android: Changing a specific value in a list during runtime - list

I have a simple Xamarin.Android-App.
On the Activity of this app, there is a list displayed. Please see following MyActivity.axml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android ="http://schemas.android.com/apk/res/android"
android:orientation ="vertical"
android:layout_width ="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width ="match_parent"
android:layout_height="wrap_content"
android:text ="Click Me"
android:layout_marginTop ="20dp"
android:layout_marginLeft ="25dp"
android:layout_marginRight ="25dp"
android:id="#+id/button" />
<Space
android:layout_width="match_parent"
android:layout_height="25dp"
android:id="#+id/space" />
<ListView
android:minWidth="25px"
android:minHeight="25px"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/list" />
</LinearLayout>
One row of this list contains simply two entries, please see ListRow.axml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft ="5dp"
android:layout_marginTop ="10dp"
android:layout_marginBottom="10dp"
android:layout_marginRight ="5dp" />
<TextView
android:id="#+id/value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft ="5dp"
android:layout_marginTop ="10dp"
android:layout_marginBottom="10dp"
android:layout_marginRight ="5dp" />
</RelativeLayout>
So the code-behind of that activity looks like the following:
public class MyActivity : Activity
{
List<Entry> List = null;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.MyActivity);
List = PopulateList();
var lv = FindViewById<ListView>(Resource.Id.list);
var adapter = new ListAdapter(this, Resource.Layout.List, List);
lv.Adapter = adapter;
FindViewById<Button>(Resource.Id.button).Click += OnButtonClick;
}
}
For the sake of completeness, here is the code for my ListAdapter.cs-class:
class ListAdapter : ArrayAdapter
{
List<Entry> List;
public ListAdapter(Context Context, int ListId, List<Entry> List) : base(Context, ListId, List)
{
this.List = List;
}
public override int Count
{
get { return List.Count; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View v = convertView;
if (v == null)
{
LayoutInflater inflater = (LayoutInflater)Context.GetSystemService(Context.LayoutInflaterService);
v = inflater.Inflate(Resource.Layout.List, parent, false);
}
v.FindViewById<TextView>(Resource.Id.name).Text = List[position].Name;
v.FindViewById<TextView>(Resource.Id.value).Text = "Original Value";
return v;
}
}
So my question now is the following: Assuming that there is more than one item within that List. On click of the button, I want to change one specific text within that list. Let's say of the second entry in the list the (Resource.Id.value).Text (which now says "Original Value") to "Changed Value" or something like that. But only of the second one. All the other items should stay the same.
Please see following example of output aimed, maybe it's easier to understand what I am trying to do:
Name Value
- - - - - - - - - - - - - - - -
No.1 Original Value
No.2 Original Value
No.3 Original Value
[Button Click]
Name Value
- - - - - - - - - - - - - - - -
No.1 Original Value
No.2 Changed Value
No.3 Original Value
Can anyone maybe help me / tell me how to do this? What does my private void OnButtonClick(object sender, EventArgs e)-method have to look like? How can I access a single entry in that list?
Thanks in advance for all answers and best regards

you could add a method in adapter to notifyDataSetChanged(); :
class ListAdapter : ArrayAdapter
{
List<Entry> List;
private int ItemPositionToChange = -1;
public ListAdapter(Context Context, int ListId, List<Entry> List) :
base(Context, ListId, List)
{
this.List = List;
}
//this method to let adapter notify
public void ChangeItemValue(int position)
{
ItemPositionToChange = position;
NotifyDataSetChanged();
}
public override int Count
{
get { return List.Count; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View v = convertView;
if (v == null)
{
LayoutInflater inflater =
(LayoutInflater)Context.GetSystemService(Context.LayoutInflaterService);
v = inflater.Inflate(Resource.Layout.List, parent, false);
}
v.FindViewById<TextView>(Resource.Id.name).Text = List[position].Name;
//change the item value according to your needs
if(position == ItemPositionToChange ){
v.FindViewById<TextView>(Resource.Id.value).Text = "Changed Value";
}else{
v.FindViewById<TextView>(Resource.Id.value).Text = "Original Value";
}
return v;
}
}
then in your button click listener :
void OnButtonClick(object sender, EventArgs e)
{
//positionToChange is which item you want to change
adapter.ChangeItemValue(positionToChange);
}

I'm not too familiar with the Entry class, but it seems to have a Text property.
Assuming you know the index of the string (myIndex below):
private void OnButtonClick(object sender, EventArgs e) {
List[myIndex].Text = "Changed Value";
adapter.notifyDataSetChanged();
}

Related

ListView item as a progress bar

I was wondering if someone can maybe help me with the following intent:
I created an app which simply displays a table. It shows a table head and beyond that a list view which contains several items.
Is it possible, that if one clicks on one of these items, a progress bar is shown which loads smoothely in a certain time interval (lets say 30 seconds) from left to right?
Please see my screenshot below, maybe it's easier to understand what I am trying to do:
Finally, I don't know if it helps, but let me attach some code as well. I shortened it a little, if something is missing for understanding (like the list class) or if I removed to much, please let me know:
public class TableActivity : Activity
{
ListView lv;
ListAdapter adapter = null;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
//...
lv = FindViewById<ListView>(Resource.Id.geraeteListView);
adapter = new ListAdapter(this, Resource.Layout.List, geraeteliste.CurrentGeraeteliste, Intent.GetStringExtra("ServerIP"))
{
parentActivity = this
};
lv.Adapter = adapter;
}
private async void OnItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
if (geraeteliste.CurrentGeraeteliste[e.Position].bespielt == "J") return;
//…
await Task.Delay(0);
}
}
public class ListAdapter : ArrayAdapter
{
//...
public override View GetView(int position, View convertView, ViewGroup parent)
{
View v = convertView;
if (v == null)
{
LayoutInflater inflater = (LayoutInflater)Context.GetSystemService(Context.LayoutInflaterService);
v = inflater.Inflate(Resource.Layout.List, parent, false);
}
//...
v.FindViewById<ImageView>(Resource.Id.typeImageView).SetImageResource(Resource.Drawable.Icon);
v.FindViewById<TextView>(Resource.Id.numberTextView).Text = Geraetelist[position].geraeteplatz;
v.FindViewById<TextView>(Resource.Id.descriptionTextView).Text = Geraetelist[position].geraeteinformation;
ImageView iv = v.FindViewById<ImageView>(Resource.Id.bspImageView);
iv.SetImageResource(Geraetelist[position].bespielt == "N" ? Resource.Drawable.greenPoint : Resource.Drawable.redPoint);
//…
return v;
}
}
Can anyone maybe give me a short hint or something? How can I implement such a progress bar for every item on click?^^ Would be really happy for every helping effort.
Thanks in advance for every answer,
Best regards
Is it possible, that if one clicks on one of these items, a progress bar is shown which loads smoothly in a certain time interval (lets say 30 seconds) from left to right?
If you want to display progressbar when click Listview item, I do one sample for you, you can take a look:
1.Declare ListView layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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" android:orientation="vertical">
<ListView
android:minWidth="25px"
android:minHeight="25px"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/ListView" />
</LinearLayout>
2.Declare list row layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ProgressBar android:id="#+id/progressBar1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true" android:visibility="invisible"
style="#android:style/Widget.ProgressBar.Horizontal" />
</LinearLayout>
3.Define ListView Adapter
public class Post
{
public string title { get; set; }
public bool isselect { get; set; }
}
public class CusotmListAdapter : BaseAdapter<Post>
{
Activity context;
List<Post> list;
public CusotmListAdapter(Activity _context, List<Post> _list)
: base()
{
this.context = _context;
this.list = _list;
}
public override Post this[int position]
{
get { return list[position]; }
}
public override int Count
{
get { return list.Count; }
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View view = convertView;
// re-use an existing view, if one is available
// otherwise create a new one
if (view == null)
view = context.LayoutInflater.Inflate(Resource.Layout.ListItemRow, parent, false);
Post item = this[position];
view.FindViewById<TextView>(Resource.Id.textView1).Text = item.title;
if(item.isselect==true)
{
view.FindViewById<ProgressBar>(Resource.Id.progressBar1).Visibility = ViewStates.Visible;
}
else
{
view.FindViewById<ProgressBar>(Resource.Id.progressBar1).Visibility = ViewStates.Invisible;
}
return view;
}
}
4.Setting ListView Adapter
public class MainActivity : AppCompatActivity
{
private ListView listview;
List<Post> posts = new List<Post>();
private CusotmListAdapter adapter;
private int oldposition = -1;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
posts.Add(new Post() { title = "title 1", isselect = false });
posts.Add(new Post() { title = "title 2", isselect = false });
posts.Add(new Post() { title = "title 3", isselect = false });
posts.Add(new Post() { title = "title 4", isselect = false });
posts.Add(new Post() { title = "title 5", isselect = false });
posts.Add(new Post() { title = "title 6", isselect = false });
posts.Add(new Post() { title = "title 7", isselect = false });
posts.Add(new Post() { title = "title 8", isselect = false });
SetContentView(Resource.Layout.activity_main);
listview = FindViewById<ListView>(Resource.Id.ListView);
listview.ItemClick+= OnListItemClick;
adapter= new CusotmListAdapter(this, posts);
listview.Adapter = adapter;
}
private void OnListItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
if(oldposition!=-1)
{
Post p1 = adapter[oldposition];
p1.isselect = false;
}
oldposition = e.Position;
Post p = adapter[e.Position];
p.isselect = true;
adapter.NotifyDataSetChanged();
}
}
Update
You can change some code in CusotmListAdapter GetView event:
public override View GetView(int position, View convertView, ViewGroup parent)
{
View view = convertView;
// re-use an existing view, if one is available
// otherwise create a new one
if (view == null)
view = context.LayoutInflater.Inflate(Resource.Layout.ListItemRow, parent, false);
Post item = this[position];
view.FindViewById<TextView>(Resource.Id.textView1).Text = item.title;
ProgressBar p = view.FindViewById<ProgressBar>(Resource.Id.progressBar1);
p.Max = 100;
p.Progress = 100;
//p.IncrementProgressBy(-10);
if(item.isselect==true)
{
view.FindViewById<ProgressBar>(Resource.Id.progressBar1).Visibility = ViewStates.Visible;
new Thread(new ThreadStart(delegate
{
while (p.Progress > 0)
{
p.Progress -= 20;
Thread.Sleep(1000);
}
})).Start();
}
else
{
view.FindViewById<ProgressBar>(Resource.Id.progressBar1).Visibility = ViewStates.Invisible;
}
return view;
}
Then please look at the screenshot:
It's clear that you are missing some knowledge on ListViews. This Xamarin university course has some examples and a video that explain the different components.
But basically, you can put your background progress bar as a View in your row AXML layout file, and depending on the value of the Progress property, that view can change widths.
Let me know if you have questions

findViewbyId in custom adapter returns null

I am trying to retrieve a textView in a custom Adapter but it is returning null for some reason. Can you guys explain why? am new to Android and am stuck here. I am also attaching the view the adapter is connecting to, its called profile_listitem.xml and contains the textView I want.
Thank you
AdapterProfile.xml
public AdapterProfiles(Context context,ArrayList<Profile> profilesArray)
{
super(context, R.layout.profile_listitem, profilesArray);
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
Profile p= getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.profile_listitem , parent, false);
}
TextView textAppName=(TextView)convertView.findViewById(R.id.textViewApp);
ToggleButton appStatus =(ToggleButton)convertView.findViewById(R.id.toggleAppStatus);
if(convertView.findViewById(R.id.textViewApp)==null)
Log.d("Profile","Profile is null");
textAppName.setText(p.getName());
appStatus.setChecked(p.isActive());
return convertView;
}
profile_listitem.xml
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="#color/background"
android:textColor="#color/blue"
android:textSize="36dp"
android:id="#+id/textViewAppName"/>
<ToggleButton
android:layout_width="72dp"
android:layout_height="48dp"
android:layout_alignParentEnd="true"
android:textColor="#color/white"
android:background="#color/blue"
android:id="#+id/toggleAppStatus"/>
Because you have used
R.id.textViewApp
instead of what you defined in the xml file i.e.
R.id.textViewAppName
TextView textAppName=(TextView)convertView.findViewById('R.id.textViewApp');

How to set image in list view by using string

I have two activities namely mainactivity and main2activity. Mainactivity has three buttons and main2activity has list view.
When I click button string is passed to main2activity and is displayed in main2activity.
So now I want also image in listview. corresponding image for button selected. Below are my codes.
MainActivity
public class MainActivity extends AppCompatActivity {
EditText editText;
Button addButton;
String text1 ="Item 1";
String text2 ="Item 2";
String text3 ="Item 3";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Button button1 = (Button)findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,Main2Activity.class);
intent.putExtra("text",text1);
startActivity(intent);
}
});
Button button2 = (Button)findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,Main2Activity.class);
intent.putExtra("text",text2);
startActivity(intent);
}
});
Button button3 = (Button)findViewById(R.id.button3);
button3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,Main2Activity.class);
intent.putExtra("text",text3);
startActivity(intent);
}
});
}
Main2activity
public class Main2Activity extends AppCompatActivity {
ListView listView;
ArrayAdapter<String> adapter;
#Override
protected void onRestart() {
super.onRestart();
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, Global.list1);
listView.setAdapter(adapter);
if (Global.list1.size() < 1) {
Global.list1 = new ArrayList<>();
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Intent intent1 = getIntent();
listView = (ListView) findViewById(R.id.list);
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, Global.list1);
listView.setAdapter(adapter);
String havestring = intent1.getStringExtra("text");
if (havestring != null) {
Global.list1.add(havestring);
adapter.notifyDataSetChanged();
}
Button backbtn = (Button) findViewById(R.id.backbtn);
backbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Main2Activity.this, MainActivity.class);
startActivity(intent);
}
});
}
}
row.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="#+id/imageview"
android:layout_width="60dp"
android:layout_height="60dp"
android:padding="5dp" />
<TextView
android:id="#+id/textview2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp" />
</LinearLayout>
So how to set custom adapter that will add corresponding image with string added.
Can it be done using if else statement in custom adapter???
Please do help me
for same.
Can anyone help me out???

Standard way to render datasource of a sublayout - Sitecore

This works for me, but want to know it's the correct method or there is a better way, to display an item that is set as a datasource to a sublayout.
sample.ascx
<sc:Text ID="txtHeader" runat="server" Field="Header" />
<br/>
<sc:Image ID="imgMotif" runat="server" Field="Motif Left" />
<br/>
<!-- some more controls -->
sample.ascx.cs
private void BindData()
{
Item introItem = GetItemFromDatasource((Sublayout)this.Parent);
if(introItem != null)
{
txtHeader.Item = introItem;
imgMotif.Item = introItem;
//..and so on..
}
}
private Item GetItemFromDatasource(Sublayout sublayout)
{
Item dataSource = null;
if (sublayout != null)
{
Guid dataSourceId;
if (Guid.TryParse(sublayout.DataSource, out dataSourceId))
dataSource = Sitecore.Context.Database.GetItem(new ID(dataSourceId));
}
return dataSource;
}
I suggest your sublayouts to inherit from a sublayout base.
Your SublayoutBase will look like:
public class SublayoutBase : UserControl
{
private Item _dataSource;
public Item DataSource
{
get
{
if (_dataSource == null)
{
if (Parent is Sublayout)
{
var sublayout = (Sitecore.Web.UI.WebControls.Sublayout)Parent;
Guid dataSourceId;
if (Guid.TryParse(sublayout.DataSource, out dataSourceId))
{
_dataSource = Sitecore.Context.Database.GetItem(new ID(dataSourceId));
}
else
{
_dataSource = Sitecore.Context.Database.GetItem(sublayout.DataSource);
}
}
if (_dataSource == null)
{
_dataSource = Sitecore.Context.Item;
}
}
return _dataSource;
}
}

Maps v2 my-location layer Style

How to change the basic blue color of my-location layer.
And can I replace it with marker. Or i have to buld custom Tile.
And can i remove only pin with the radius and keep che locate-me tile
I didn't find any style cusomization. And the marker cannot be replaced.
I did a custom tile, and a custom getCurrentLocation function.
Here is my code:
First you need tile for the Locate me button in the top right corner. I add it to the Layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:context="android.support.v4.app.FragmentActivity" >
<fragment
android:id="#+id/tabs_fragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
class="com.bucons.savetime.MyMapFragment" />
<ImageButton
android:id="#+id/myLocationButton"
android:layout_width="40dp"
android:layout_height="40dp"
android:padding="4dp"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:scaleType="fitCenter"
android:src="#drawable/ic_menu_mylocation"
android:background="#drawable/map_tile_bg" />
</RelativeLayout>
Needed resources are #drawable/ic_menu_mylocation
You can get it from: https://docs.google.com/file/d/0BzGos46YSzYfWkRYS2ZMNmdZREk/edit
And for Background: #drawable/map_tile_bg:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="#android:integer/config_shortAnimTime">
<item android:state_pressed="true">
<shape android:shape="rectangle">
<stroke
android:width="1px"
android:color="#color/map_tile_bg_stroke_pressed"/>
<solid android:color="#color/map_tile_bg_solid_pressed"/>
<corners android:radius="1dp"/>
</shape>
</item>
<item>
<shape android:shape="rectangle">
<stroke
android:width="1px"
android:color="#color/map_tile_bg_stroke"/>
<solid android:color="#color/map_tile_bg_solid"/>
<corners android:radius="1dp"/>
</shape>
</item>
</selector>
Color resourser are:
<color name="map_tile_bg_solid">#aaffffff</color>
<color name="map_tile_bg_stroke">#ffcccccc</color>
<color name="map_tile_bg_solid_pressed">#aaFF9933</color>
<color name="map_tile_bg_stroke_pressed">#ffcccccc</color>
And here is my fragment:
public class MyMapFragment extends SupportMapFragment {
//Current location Marker
private Marker myLocationMarker;
GoogleMap map = null;
public MyMapFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setUpMapIfNeeded();
getCurrentLocation();
}
//set the map and set the tile for locate me button
private void setUpMapIfNeeded() {
// Do a null check to confirm that we have not already instantiated the map.
if (map == null) {
map = getMap();
// Check if we were successful in obtaining the map.
if (map != null) {
//Top right button for go to location
ImageButton locateMeTile = (ImageButton) getSherlockActivity().findViewById(R.id.myLocationButton);
locateMeTile.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
getCurrentLocation();
}
});
}
}
}
//retrieve the current position. Only once
private void getCurrentLocation() {
locationManager = (LocationManager) getSherlockActivity().getSystemService(Context.LOCATION_SERVICE);
Criteria crit = new Criteria();
String towers = locationManager.getBestProvider(crit, false);
Location location = locationManager.getLastKnownLocation(towers);
Double glat = null;
Double glon = null;
if(location != null){
glat = location.getLatitude();
glon = location.getLongitude();
}
CameraPosition pos = new CameraPosition.Builder()
.target(new LatLng(glat, glon))
.zoom(10)
.build();
if(pos != null) {
currLocationChange(pos.target);
map.animateCamera(CameraUpdateFactory.newCameraPosition(pos));
} else {
Toast.makeText(getSherlockActivity(), R.string.main_error, Toast.LENGTH_LONG).show();
}
}
//Add pin to the current Location or move existing
private void currLocationChange(LatLng loc) {
if(myLocationMarker != null) {
myLocationMarker.setPosition(new LatLng(loc.latitude,loc.longitude));
} else {
myLocationMarker = map.addMarker(new MarkerOptions()
.position(new LatLng(loc.latitude,loc.longitude)));
}
}
}