Can't load image in ImageViewAsync - c#

I can't get an image to load into an ImageViewAsync. There's just a blank where the image should be. I've tried both synchronous and asychronous approaches.
I have the image placeholderProfileImage.png in the mipmap folders. I walked the debugger through the binding code and all appears to be in order. Note that I removed other code that populates the view with text. That part is working. What am I doing wrong with respect to the image?
profilePhotoImageView is defined in a layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/acquaintanceRow"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="60dp"
android:gravity="center">
<FFImageLoading.Views.ImageViewAsync
android:id="#+id/profilePhotoImageView"
android:scaleType="fitCenter"
android:layout_width="50dp"
android:layout_height="100dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:transitionName="#string/profilePhotoTransition" />
>
The view holder class contains ProfilePhotoImageView:
internal class MyViewHolder : RecyclerView.ViewHolder
{
// removed stuff for brevity
public ImageViewAsync ProfilePhotoImageView { get; }
public MyViewHolder(View itemView) : base(itemView)
{
MyRow = itemView;
// removed stuff for brevity
ProfilePhotoImageView = MyRow.FindViewById<ImageViewAsync>(Resource.Id.profilePhotoImageView);
}
}
Binding code:
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
var viewHolder = holder as MyViewHolder;
string photoUrl = "placeholderProfileImage.png:";
FFImageLoading.Work.TaskParameter taskParameter = ImageService.LoadFileFromApplicationBundle(photoUrl);
FFImageLoading.Work.TaskParameter taskParameter2 = taskParameter.Transform(new CircleTransformation());
taskParameter2.Into(viewHolder.ProfilePhotoImageView);
// tried asynchronous as well, nothing
//FFImageLoading.Work.TaskParameter taskParameter = ImageService.LoadUrl(photoUrl);
//FFImageLoading.Work.TaskParameter taskParameter2 = taskParameter.Transform(new CircleTransformation());
//taskParameter2.Into(viewHolder.ProfilePhotoImageView);
}

LoadFileFromApplicationBundle is loading the file from Assets not the mipmap folder. So you have to move the file to your Assets folder and set the build action to AndroidAsset.

Related

Return data from DialogFragment to calling activity

I have a DialogFragment that is working and need to return the selected item from a spinner. I've tried many methods that I've found on Stack Overflow and other places but they are all using java which doesn't (apparently) translate well to c# in Xamarin for Visual Studio 2017. To date, nothing has worked My DialogFragment layout is:
<?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"
android:minWidth="300dp"
android:minHeight="75dp">
<TextView
android:text="Select the department you are registering for."
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:textStyle="bold"
android:id="#+id/textView2" />
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:id="#+id/department_spinner" />
<Button
android:text="Ok"
android:layout_width="200px"
android:layout_gravity="center"
android:layout_height="34.5dp"
android:id="#+id/button_ok" />
</LinearLayout>
The class code is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
namespace MyProject
{
class selectDepartment : DialogFragment
{
static Spinner department;
public string selection = "";
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
base.OnCreateView(inflater, container, savedInstanceState);
View view = inflater.Inflate(Resource.Layout.selectDepartment, container, false);
Button ok = view.FindViewById<Button>(Resource.Id.button_ok);
department = view.FindViewById<Spinner>(Resource.Id.department_spinner);
List<string> list = new List<string>();
list.Add("Select Department");
list.Add("Dept. A");
list.Add("Dept. B");
var adapter = new ArrayAdapter<string>(this.Activity, Android.Resource.Layout.SimpleSpinnerItem, list.ToArray());
department.Adapter = adapter;
ok.Click += (sender, args) =>
{
selection = string.Format("{0}", department.GetItemAtPosition(department.SelectedItemPosition));
};
return view;
}
}
}
This is the code that shows the dialog:
FragmentTransaction getdepartment = FragmentManager.BeginTransaction();
selectDepartment getDept = new selectDepartment();
getDept.Show(getdepartment , "Select Department");
// Here I attempt to read a property which contains the selection
string selection = getDept.selection;
In my last attempt, I assigned the spinner selection to a property and I attempt to read that property to get the value selected, but the dialog is (apparently) displayed on a different thread and the selection isn't chosen when that line of code is executed. I tried making my method async and await the dialog, but that just made matters worse. What am I missing?
use a custom event
public class DialogEventArgs : EventArgs
{
public string Selection { get; set; }
}
and then in selectDepartment add:
public delegate void DialogEventHandler(object sender, DialogEventArgs args);
public event DialogEventHandler Dismissed;
Finally in the button's click handler add:
if (null != Dismissed)
Dismissed(this, new DialogEventArgs { Selection = selection });
when you create the dialog, attach an event handler
selectDepartment getDept = new selectDepartment();
getDept.Dismissed += (s, e) => { /* do something with e.Selection here */ };

Android Xamarin - How To Add Animations To View's Position Changes?

So I'm a bit of a newb in Android. I've read a few tutorials but found it extensively complicated to understand. I was hoping someone can help me understand on how to implement Animations to views on the current context I'm working on (noob friendly).
Let's say this is my .axml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/top_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:orientation="vertical" />
Now this is my activity (Not exactly but enough information to know what I want to do:
private LinearLayout _topContainer;
private IDictionary<string, FrameLayout> _framelayoutViewsDictionary = new Dictionary<string, FrameLayout>();
private LinearLayout.LayoutParams layoutParams;
protected override void OnCreate(Bundle bundle)
{
//SetContentView and other stuff...
layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent, 1);
_topContainer = FindViewById<LinearLayout>(Resource.Id.top_container);
}
public void CreateFirstVideoPlayer
{
_framelayoutViewsDictionary.Add(Constants.Views.TOP_FRAMELAYOUT, new FrameLayout(this)
{
Id = 1,
LayoutParameters = layoutParams
});
var fragmentManager = FragmentManager.BeginTransaction();
fragmentManager.Add(_framelayoutViewsDictionary[Constants.Views.TOP_FRAMELAYOUT].Id, /*Create New MediaPlayer Here*/, Constants.FragmentTag.TOP_FRAGMENT);
fragmentManager.Commit();
_topContainer.AddView(_framelayoutViewsDictionary[Constants.Views.TOP_FRAMELAYOUT]);
}
public void CreateSecondVideoPlayer
{
_framelayoutViewsDictionary.Add(Constants.Views.BOTTOM_FRAMELAYOUT, new FrameLayout(this)
{
Id = 2,
LayoutParameters = layoutParams
});
var fragmentManager = FragmentManager.BeginTransaction();
fragmentManager.Add(_framelayoutViewsDictionary[Constants.Views.BOTTOM_FRAMELAYOUT].Id, /*Create New MediaPlayer Here*/, Constants.FragmentTag.BOTTOM_FRAGMENT);
fragmentManager.Commit();
_topContainer.AddView(_framelayoutViewsDictionary[Constants.Views.BOTTOM_FRAMELAYOUT]);
}
As you can see. I'm programmatically creating a new FrameLayout, adding a fragment on top. And then putting that FrameLayout on top view which is a LinearLayout. Now when I add the second FrameLayout. The first FrameLayout is halved and the second one is added. So now each FrameLayout is taking 50:50 space. So what I want to do is. When the second FrameLayout is added, I want the first FrameLayout to animate so it slowly moves upwards to the top half of the screen instead of instantly appearing on the top. And when I remove the second FrameLayout the first FrameLayout will slowly animate back to the centre of the screen.
Hope this all makes sense. If you need more info please comment!
Using the Support Libraries to perform a fragment slide in/out is as easy as setting the Fragment's custom animations to the built-in resource abc_slide_in_bottom and abc_slide_out_bottom animations.
Example:
SupportFragmentManager
.BeginTransaction()
.SetCustomAnimations(
Resource.Animation.abc_slide_in_bottom,
Resource.Animation.abc_slide_out_bottom,
Resource.Animation.abc_slide_in_bottom,
Resource.Animation.abc_slide_out_bottom)
.AddToBackStack(count.ToString())
.Add(Resource.Id.linearLayout1, new AFragmentSubClass(), count.ToString())
.Commit();

Replacing a fragment - New instance of fragment class isn't instantiated

I'm trying to replace a fragment with a another fragment with the following lines of code:
FragmentTransaction ft = Activity.FragmentManager.BeginTransaction();
UploadCompleted ucompleted = new UploadCompleted();
ft.Replace(Resource.Id.CameraFragmentContainer, ucompleted, "uploadcompleted");
ft.AddToBackStack(null);
ft.Commit();
The fragment is being replaced inside another fragment which uses the Activity's fragment manager. The issue is that the OnCreate and OnCreateView methods of the replaced fragment aren't invoked and an old instance of fragment (the fragment which was instantiated the first time I replaced it) get's instantiated which is why I'm not able to pass any new values to the replaced fragment. Any idea what I'm doing wrong? I'm new to android development so my knowledge of fragments isn't that great.
As per your logic, OnCreate and OnCreateView of the new Fragment should get invoked. It is a good practice to do FragmentTransaction at Activity level rather than, at Fragment level. In the above snippet you are creating an instance of the new Fragment from within the already displayed Fragment and replacing itself from the parent Activity. This is not a recommended approach. I would suggest the following change.
public class ParentActivity:Activity
{
public void ChangeToUploadCompleted()
{
FragmentTransaction ft = FragmentManager.BeginTransaction();
UploadCompleted ucompleted = new UploadCompleted();
ft.Replace(Resource.Id.CameraFragmentContainer, ucompleted, "uploadcompleted");
ft.AddToBackStack(null);
ft.Commit();
}
}
public FirstFragment:Fragment
{
void CaptureCompleted ()
{
((ParentActivity)Activity).ChangeToUploadCompleted();
}
}
This is the good practice to switch fragments. This might fix your problem too
ft.Replace(Resource.Id.CameraFragmentContainer, ucompleted, "uploadcompleted");
In this R.id is the layout that you place in Fragment Activity or Activity and UploadCompleted is Fragment class which you want to replace so use xml like this in FRagmentActivity or ACtivity class
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="#+id/lin"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>
</LinearLayout>
when you want to replace use this
FragmentTransaction ft = Activity.FragmentManager.BeginTransaction();
UploadCompleted ucompleted = new UploadCompleted();
ft.Replace(Resource.Id.lin, ucompleted, "uploadcompleted");
ft.AddToBackStack(null);
ft.Commit();

Load CheckedTextView items in ListView with checked states set

When my activity starts and I initially load my ListView with items, I want to be able to set some of those items to checked however that doesn't seem to be working.
I'm using the simple_list_item_multiple_choice layout so the items are CheckedTextView.
Here's the adapter. Text displays properly however the Checked property doesn't seem to be doing anything visually despite it being set to true/false.
public class VehicleSubListAdapter : BaseAdapter<string>
{
// ...
public override View GetView(int position, View convertView, ViewGroup parent)
{
View view = convertView ?? _context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItemMultipleChoice, parent, false);
var checkedTextView = view.FindViewById<CheckedTextView>(Android.Resource.Id.Text1);
checkedTextView.Text = _items[position].Name;
// This doesn't seem to do anything
checkedTextView.Checked = _items[position].Checked;
// I've even tried this with no change visually
//checkedTextView.Checked = true;
return view;
}
}
Here's the activity which can be closed and re-opened but needs to resume from where it left off (some items checked, some items not). That is why things are stored in a global static variable.
If the global list is empty, manually update the lists. Else, load from the global list. It successfully loads from the global list and successfully stores the Checked property of that list as modified in the item click event. However, the checked items aren't shown as checked when the activity loads.
Also I've tried putting the call to FillList() in both OnCreate and OnResume and neither have worked.
public class VehicleConditionSubActivity : ListActivity
{
private List<VehicleConditionItemDTO> _items;
private VehicleSubListAdapter _vehicleAdapter;
//...
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetTheme(Resource.Style.MyAppTheme);
SetContentView(Resource.Layout.VehicleConditionItem);
// Set up action bar
ActionBar.SetDisplayHomeAsUpEnabled(true);
// Set up list view
ListView.ChoiceMode = ChoiceMode.Multiple;
_items = new List<VehicleConditionItemDTO>();
_vehicleAdapter = new VehicleSubListAdapter(this, _items);
ListAdapter = _vehicleAdapter;
ListView.ItemClick += ListView_ItemClick;
//...
// Fill list view
FillList();
}
private void FillList()
{
AddFluidItems();
_vehicleAdapter.NotifyDataSetChanged();
}
private void AddFluidItems()
{
// I've checked that this is being called correctly
if (Global.Conditions.FluidLevels.Count > 0)
{
foreach (var item in Global.Conditions.FluidLevels)
{
_items.Add(item);
}
}
else
{
_items.Add(new VehicleConditionItemDTO("1", "Engine oil"));
// ...
foreach (var item in _items)
{
Global.Conditions.FluidLevels.Add(item);
}
}
}
// ...
private void ListView_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
// Items already check/uncheck properly when tapped
// So I just update the global list items checked property
Global.Conditions.FluidLevels[e.Position].Checked = !Global.Conditions.FluidLevels[e.Position].Checked;
}
}
The layout for the activity is
<?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:minWidth="25px"
android:minHeight="25px"
android:background="#color/background">
<ListView
android:minWidth="25px"
android:minHeight="25px"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#android:id/list" />
</LinearLayout>
Selecting Items Programmatically
Manually setting which items are ‘selected’ is done with the
SetItemChecked method (it can be called multiple times for multiple
selection)
Customizing A List View's Appearance
Note that SetItemChecked is on the ListView.
You can remove the code in GetView that sets Checked.
Then, after (or during the call to FillList) for each item that should be initially checked, call:
ListView.SetItemChecked (position, true);

Mono For Android, FindViewById A CheckBoxPreference?

I have a PreferenceScreen, where the user can check/uncheck a checkbox.
To get access any Control in the Activity I used always:
var button = FindViewById<Button>(Resource.Id.myButton);
Well now, I want to access my CheckBoxPreference..
, but its not working and I get this Exception:
The type 'Android.Preferences.CheckBoxPreference' cannot be used as type parameter 'T' in the generic type or method 'Android.App.Activity.FindViewById(int)'. There is no implicit reference conversion from 'Android.Preferences.CheckBoxPreference' to 'Android.Views.View'.
How my PreferenceScreen.xml looks like:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="Basic"
android:id="#+id/preferenceCategory">
<CheckBoxPreference
android:id="#+id/preferenceCheckBox"
android:key="usetestdata"
android:title="Testdata ON/OFF"
android:defaultValue="true" />
</PreferenceCategory>
</PreferenceScreen>
and the not working code:
var aCheckBox = FindViewById<CheckBoxPreference>(Resource.Id.preferenceCheckBox);
aCheckBox.Enabled = false;
Maybe someone can help me and tell me on how to access controls within an activity from a PreferenceScreen?
Here is the code for using PreferenceActivity
public class SettingsActivity extends PreferenceActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//add the prefernces.xml layout
addPreferencesFromResource(R.xml.preferences);
final CheckBoxPreference cf = (CheckBoxPreference) findPreference("checkbox"));
cf.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
// do something here
return false;
}
});
}
your preferences.xml in xml folder
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<CheckBoxPreference android:key="checkbox"
android:title="Title"/>
</PreferenceScreen>

Categories