Issue with Xamarin Android AppcombatToolbar and MobileBarcodeScanner - xamarin

If I try to use the AppcombatToolbar (https://developer.xamarin.com/guides/android/user_interface/toolbar/part-3-toolbar-compatibility/) in a customoverlay the items in my toolbar are not displayed. I see the space of the toolbar but without buttons and text
This is my zxing usage:
var scanner = new ZXing.Mobile.MobileBarcodeScanner();
//Tell our scanner we want to use a custom overlay instead of the default
scanner.UseCustomOverlay = true;
//Inflate our custom overlay from a resource layout
View zxingOverlay = LayoutInflater.FromContext(this).Inflate(Resource.Layout.Master, null);
//Set our custom overlay
scanner.CustomOverlay = zxingOverlay;
//Start scanning!
var result = await scanner.Scan();
This my BaseActivity
[Activity(Label = "#string/app_name", MainLauncher = false, Icon = "#drawable/icon")]
public class MasterActivity : AppCompatActivity
{
LinearLayout content;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
base.SetContentView(Resource.Layout.Master);
// Create your application here
var toolbar = FindViewById<Toolbar>(Resource.Id.maintoolbar);
SetSupportActionBar(toolbar);
SupportActionBar.Title = GetString(Resource.String.app_name);
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
SupportActionBar.SetHomeButtonEnabled(true);
content = (LinearLayout)FindViewById(Resource.Id.content);
}
public override void SetContentView(int id)
{
LayoutInflater inflater = (LayoutInflater)BaseContext.GetSystemService(Context.LayoutInflaterService);
if (content != null)
{
inflater.Inflate(id, content);
}
}
public override bool OnCreateOptionsMenu(IMenu menu)
{
MenuInflater.Inflate(Resource.Menu.topmenus, menu);
return base.OnCreateOptionsMenu(menu);
}
public override bool OnOptionsItemSelected(IMenuItem item)
{
if(item.ItemId == Resource.Id.menu_logout)
{
Settings.UserName = null;
Settings.Password = null;
StartActivity(typeof(LoginActivity));
}
Toast.MakeText(this, "Action selected: " + item.TitleFormatted,
ToastLength.Short).Show();
return base.OnOptionsItemSelected(item);
}
}
And this my Base Layout:
<?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="25px"
android:minHeight="25px"
android:weightSum="1">
<include
android:id="#+id/maintoolbar"
layout="#layout/toolbar" />
<LinearLayout
android:id="#+id/content"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#android:color/transparent"/>
</LinearLayout>
Page with working Toolbar
Scanpage with no working toolbar

Related

RecyclerView not showing the image full height

I have a problem with the images inside recyclerview
They shown like this
My code to load the image is :
#BindingAdapter("imageUrl")
fun ImageView.bindImage(imgUrl: String?) {
imgUrl?.let {
val imgUri = imgUrl.toUri().buildUpon().scheme("https").build().toString()
val uiHandler = Handler(Looper.getMainLooper())
thread(start = true) {
val bitmap = downloadBitmap(imgUri)
uiHandler.post {
this.setImageBitmap(bitmap)
}
}
}
}
fun downloadBitmap(imageUrl: String): Bitmap? {
return try {
val conn = URL(imageUrl).openConnection()
conn.connect()
val inputStream = conn.getInputStream()
val bitmap = BitmapFactory.decodeStream(inputStream)
inputStream.close()
bitmap
} catch (e: Exception) {
Log.e(ContentValues.TAG, "Exception $e")
null
}
}
XML for item:
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/iv_song_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
app:imageUrl="#{songObject.songImage}"
android:src="#drawable/img_song_cover" />
And XML For Recycler:
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_home_albums_list"
android:layout_width="match_parent"
android:layout_height="#dimen/dp200w"
android:layout_marginStart="#dimen/dp16w"
android:layout_marginLeft="#dimen/dp16w"
android:layout_marginTop="#dimen/dp8w"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tv_home_albums_title"
tools:listitem="#layout/item_album" />
My task is to do all the work without using any third-party,
So any help ?
I have solved the problem just add a statement to check if the image loaded before to not render it more than once when I scroll with recycler view, and remove the place holder.
if(this.drawable == null) {
imgUrl?.let {
val imgUri = imgUrl.toUri().buildUpon().scheme("https").build().toString()
val uiHandler = Handler(Looper.getMainLooper())
thread(start = true) {
val bitmap = downloadBitmap(imgUri)
uiHandler.post {
this.setImageBitmap(bitmap)
}
}
}
}

Telerik UI for Xamarin: Property not found for RadListView Binding

I am working on an Android app with Xamarin, using Telerik UI.
The following error is raised when trying to bind a property to a Telerik ListViewTextCell in a RadListView:
[0:] Binding: 'Author' property not found on 'Book', target property: 'Telerik.XamarinForms.DataControls.ListView.ListViewTextCell.Detail'
This happens in even the most minimal cases. Below is an example, drawn largely from the ListView documentation itself.
PageTest.cs:
using System.Collections.Generic;
using System.ComponentModel;
using Xamarin.Forms;
using Telerik.XamarinForms.DataControls;
using Telerik.XamarinForms.DataControls.ListView;
namespace MyTelerikApp
{
[DesignTimeVisible(false)]
public partial class PageTest : ContentPage
{
public PageTest()
{
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
var listView = new RadListView
{
ItemsSource = new ViewModel().Source,
ItemTemplate = new DataTemplate(() =>
{
var cell = new ListViewTextCell
{
TextColor = Color.Black,
DetailColor = Color.Gray,
};
cell.SetBinding(ListViewTextCell.TextProperty, new Binding(nameof(Book.Title)));
cell.SetBinding(ListViewTextCell.DetailProperty, new Binding(nameof(Book.Author)));
return cell;
}),
LayoutDefinition = new ListViewLinearLayout { ItemLength = 70 }
};
MainPageContent.Children.Add(listView);
}
}
}
public class Book
{
public string Title { get; set; }
public string Author { get; set; }
}
public class ViewModel
{
public ViewModel()
{
this.Source = new List<Book>{
new Book{ Title = "The Fault in Our Stars ", Author = "John Green"},
new Book{ Title = "Divergent", Author = "Veronica Roth"},
new Book{ Title = "Gone Girl", Author = "Gillian Flynn"},
new Book{ Title = "Clockwork Angel", Author = "Cassandra Clare"},
new Book{ Title = "The Martian", Author = "Andy Weir"},
new Book{ Title = "Ready Player One", Author = "Ernest Cline"},
new Book{ Title = "The Lost Hero", Author = "Rick Riordan"},
new Book{ Title = "All the Light We Cannot See", Author = "Anthony Doerr"},
new Book{ Title = "Cinder", Author = "Marissa Meyer"},
new Book{ Title = "Me Before You", Author = "Jojo Moyes"},
new Book{ Title = "The Night Circus", Author = "Erin Morgenstern"},
};
}
public List<Book> Source { get; set; }
}
PageText.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="GeoGIS.views.PageTest">
<StackLayout x:Name="MainPageContent">
</StackLayout>
</ContentPage>
After some searching, it seems that a BindingContext is necessary, but I couldn't get that to work either.
I didn't found BindingContext from your code.And I guess you confused the two usages of ContentPage(XAML and C# ).
When we created a contentpage,we have two choices(XAML and C#) as follows:
1.When we choose the ContentPage(c#),in this case, there is no xaml.And we can do like this:
public class TestPage1 : ContentPage
{
public TestPage1 ()
{
var listView = new RadListView
{
BackgroundColor = Color.White,
ItemsSource = new ViewModel().Source,
ItemTemplate = new DataTemplate(() =>
{
var cell = new ListViewTextCell
{
TextColor = Color.Black,
DetailColor = Color.Gray,
};
cell.SetBinding(ListViewTextCell.TextProperty, new Binding(nameof(Book.Title)));
cell.SetBinding(ListViewTextCell.DetailProperty, new Binding(nameof(Book.Author)));
return cell;
}),
LayoutDefinition = new ListViewLinearLayout { ItemLength = 70 },
};
Content = new StackLayout {
Children = {
listView
}
};
}
}
2.When we choose the ContentPage,in this case, code has xaml.We can do like this.
Put the followinging code in your xaml
<StackLayout>
<telerikDataControls:RadListView ItemsSource="{Binding Source}" BackgroundColor="White" x:Name="listView">
<telerikDataControls:RadListView.BindingContext>
<local:ViewModel />
</telerikDataControls:RadListView.BindingContext>
<telerikDataControls:RadListView.ItemTemplate>
<DataTemplate>
<telerikListView:ListViewTextCell Text="{Binding Title}" Detail="{Binding Author}" TextColor="Black" DetailColor="Gray" />
</DataTemplate>
</telerikDataControls:RadListView.ItemTemplate>
<telerikDataControls:RadListView.LayoutDefinition>
<telerikListView:ListViewLinearLayout ItemLength="70" />
</telerikDataControls:RadListView.LayoutDefinition>
</telerikDataControls:RadListView>
</StackLayout>
And remove the method OnAppearing() from your code.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
//BindingContext = new ViewModel();
}
protected override void OnAppearing()
{
base.OnAppearing();
}
}
From above code,we can found the BindingContext,it is necessary.
<telerikDataControls:RadListView.BindingContext>
<local:ViewModel />
</telerikDataControls:RadListView.BindingContext>
And we can also BindingContext like this(Any one is ok.):
BindingContext = new ViewModel();
The result is the same:

Plugin.Media Not Working on Prism Xamarin Forms (TakePhotoAsync)

I know this question is not new, but I am really stuck on this for days, and I need your support.
My problem is:
I can't take pictures in my prism xamarin forms project using the plugin media for Android (it works for selecting images from gallery though).
The Error I get is:
unable to get file location xam plugin media site
I would love to hear from you guys, and thanks in advance for your support.
Here i my code:
Android Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.niternational.Hope" android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="27" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<application android:label="Hope.Android" android:icon="#mipmap/ic_launcher">
<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.niternational.Hope.fileprovider" android:exported="false" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="#xml/file_paths"></meta-data>
</provider>
</application>
</manifest>
file_paths file on xml folder on Resources
<?xml version="1.0" encoding="utf-8" ?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images" path="Pictures" />
<external-files-path name="my_movies" path="Movies" />
</paths>
Main Activity
[Activity(Label = "Hope", Icon = "#mipmap/ic_launcher", Theme = "#style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
CrossCurrentActivity.Current.Init(this, bundle);
LoadApplication(new App(new AndroidInitializer()));
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults)
{
Plugin.Permissions.PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
public class AndroidInitializer : IPlatformInitializer
{
public void RegisterTypes(IContainerRegistry container)
{
// Register any platform specific implementations
}
}
AssemblyInfo file
I have added:
[assembly: UsesFeature("android.hardware.camera", Required = false)]
[assembly: UsesFeature("android.hardware.camera.autofocus", Required = false)]
Code Behind
private async void TakeImage()
{
var actions = await Application.Current.MainPage.DisplayActionSheet("ActionSheet: Image?", "Cancel", null, "Take Picture", "From Gallery");
switch (actions)
{
case "Take Picture":
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsPickPhotoSupported)
{
var message = "No Camera available";
//DependencyService.Get<IMessage>().ShortAlert(message);
return;
}
var mediaOptions = new StoreCameraMediaOptions
{
Directory = "UploaDoc",
Name = $"{DateTime.UtcNow}.jpg",
SaveToAlbum = true,
CompressionQuality = 75,
CustomPhotoSize = 50,
PhotoSize = PhotoSize.MaxWidthHeight,
MaxWidthHeight = 2000,
DefaultCamera = CameraDevice.Front
};
// Take a photo of the business receipt.
var file = await CrossMedia.Current.TakePhotoAsync(mediaOptions);
if (file == null)
return;
image.Source = ImageSource.FromStream(() =>
{
var stream = file.GetStream();
return stream;
});
var memoryStream = new MemoryStream();
file.GetStream().CopyTo(memoryStream);
file.Dispose();
imgAsBytes = memoryStream.ToArray();
memoryStream.Dispose();
break;
case "From Gallery":
if (!CrossMedia.Current.IsPickPhotoSupported)
{
var message = "Picking image is not supported";
//DependencyService.Get<IMessage>().ShortAlert(message);
return;
}
var files = await CrossMedia.Current.PickPhotoAsync();
if (files == null)
return;
image.Source = ImageSource.FromStream(() =>
{
var stream = files.GetStream();
return stream;
});
var ms = new MemoryStream();
files.GetStream().CopyTo(ms);
files.Dispose();
imgAsBytes = ms.ToArray();
ms.Dispose();
break;
}

How to rotate images in GridView

A collection of images are showing in GridView using Xamarin Android with Mvvm Cross, but the problem is there are two button which rotates clock and anti clock direction with 90 degrees for each click all cells(or images) should be rotate within the GridView.
How can I achieve it?
Here is my viewModel collection which will be bind to GridView,
private ObservableCollection<Snapshot> _snapshotsItemSource;
public ObservableCollection<Snapshot> SnapshotsItemSource
{
get { return _snapshotsItemSource; }
set
{
_snapshotsItemSource = value;
RaisePropertyChanged(() => SnapshotsItemSource);
}
}
And my Model object is,
public class Snapshot : MvxViewModel
{
string _ID;
public string ID
{
get
{
return _ID;
}
set
{
_ID = value;
ImageUrl = string.Format("http://{0}:{1}/GetSnapshot?ID={2}", TIConstants.Device.IpAdd, TIConstants.PortNo, value);
}
}
string _ImageUrl;
public string ImageUrl
{
get
{
return _ImageUrl;
}
set
{
_ImageUrl = value;
RaisePropertyChanged("ImageUrl");
}
}
}
And My view is,
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:mvvm="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<MvvmCross.Binding.Droid.Views.MvxGridView
android:id="#+id/gvSnapshots"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:numColumns="3"
android:layout_alignParentTop="true"
mvvm:MvxItemTemplate="#layout/snapshotcellview"
mvvm:MvxBind="ItemsSource SnapshotsItemSource" />
<RelativeLayout
android:background="#color/white"
android:layout_width="match_parent"
android:layout_height="#dimen/section_height"
android:orientation="horizontal"
android:layout_alignParentBottom="true">
<ImageButton
android:id="#+id/btnRotateLeft"
android:layout_alignParentLeft="true"
android:src="#drawable/abc_text_select_handle_left_mtrl_dark"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageButton
android:id="#+id/btnRotateRight"
android:layout_alignParentRight="true"
android:src="#drawable/abc_text_select_handle_left_mtrl_dark"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
Try With Glide, is This helpful for you
Glide
.with( context )
.load( "image Url" )
.transform( new RotateTransformation( context, 90f ))
.into( imageView );
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Use this to return your custom view for this Fragment
// return inflater.Inflate(Resource.Layout.YourFragment, container, false);
base.OnCreateView(inflater, container, savedInstanceState);
var view = this.BindingInflate(Resource.Layout.SnapshotsView, null);
var toolbar = ((MainActivity)this.Activity).FindViewById(Resource.Id.toolbar);
var txtTitle = ((MainActivity)this.Activity).FindViewById<TextView>(Resource.Id.TitleText);
txtTitle.Text = ViewModel.ViewTitle;
RegisterEvents();
ViewModel.SetItemSource();
var btnLeft = view.FindViewById<ImageButton>(Resource.Id.btnRotateLeft);
btnLeft.Click += BtnLeft_Click;
var btnRight = view.FindViewById<ImageButton>(Resource.Id.btnRotateRight);
btnRight.Click += BtnRight_Click;
grid = view.FindViewById<MvxGridView>(Resource.Id.gvSnapshots);
mAdapter = new SnapshotsDataViewAdapter(this.Activity, (IMvxAndroidBindingContext)BindingContext);
grid.Adapter = mAdapter;
grid.OnItemClickListener = this;
return view;
}
void BtnLeft_Click(object sender, EventArgs e)
{
currentRotation = currentRotation + 1;
mAdapter.NotifyDataSetChanged();
}
void BtnRight_Click(object sender, EventArgs e)
{
currentRotation = currentRotation - 1;
mAdapter.NotifyDataSetChanged();
}
static int currentRotation = 0;
static float RotationTranslation = 0;
private class SnapshotsDataViewAdapter : MvxAdapter
{
SnapshotsViewModel mViewModel;
public SnapshotsDataViewAdapter(FragmentActivity context, IMvxAndroidBindingContext bindingContext) : base(context, bindingContext)
{
mViewModel = bindingContext.DataContext as SnapshotsViewModel;
}
protected override View GetBindableView(View convertView, object dataContext, ViewGroup parent, int templateId)
{
View row = convertView;
try
{
var item = (BSSnapshot)dataContext;
if (row == null)
{
row = BindingContext.BindingInflate(templateId, parent, false);
}
var imgView = row.FindViewById<ImageView>(Resource.Id.imgRotate1);
Picasso.With(Android.App.Application.Context).Load(item.ImageUrl).Into(imgView);
imgView.Rotation = currentRotation*90;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
finally
{}
return row;
}
}
Here I used Picasso as Glide was not able to getting add to the project and it is working fine.

android tab content does not show up

I'm currently learning to build app for Android, and I use Android Studio to do so.
I searched for similar posts but did not find what could help me.
My goal is to have an Activity with a tabHost and 4 Tabs (for the moment). I will put the code after giving some details.
To begin, I'm just focused on two tabs on which I would like to:
- put a button to start (on the first Tab) a dedicated activity to create an item (contact item),
- Display the Contact list on the second Tab.
My problem : The button is correctly visible and works fine (I can create a Contact). i also have a function checking wheter a contact already exists or not (correctly working).
What's not working is when I select the second Tab, my list won't show up and I can't see my contacts.
This my General Activity :
package avappmobile.fourwe;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TabHost;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class General extends Activity {
List<Contact> Contacts = new ArrayList<Contact>();
List<Stuff> Stuffs = new ArrayList<Stuff>();
List<Money> Moneys = new ArrayList<Money>();
ListView contactListView;
DatabaseContactHandler dbContactHandler;
DatabaseMoneyHandler dbMoneyHandler;
DatabaseStuffHandler dbStuffHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_general);
TabHost tabHost = (TabHost) findViewById(R.id.tabHost);
contactListView = (ListView) findViewById(R.id.listViewContact);
dbContactHandler = new DatabaseContactHandler(getApplicationContext());
dbMoneyHandler = new DatabaseMoneyHandler(getApplicationContext());
dbStuffHandler = new DatabaseStuffHandler(getApplicationContext());
tabHost.setup();
TabHost.TabSpec tabSpec = tabHost.newTabSpec("home");
tabSpec.setContent(R.id.tabHome);
tabSpec.setIndicator("Home");
tabHost.addTab(tabSpec);
tabHost.newTabSpec("contact");
tabSpec.setContent(R.id.tabContact);
tabSpec.setIndicator("Contact");
tabHost.addTab(tabSpec);
tabHost.newTabSpec("money");
tabSpec.setContent(R.id.tabMoney);
tabSpec.setIndicator("Money");
tabHost.addTab(tabSpec);
tabHost.newTabSpec("stuff");
tabSpec.setContent(R.id.tabStuff);
tabSpec.setIndicator("Stuff");
tabHost.addTab(tabSpec);
if (dbContactHandler.getContactsCount() != 0)
Contacts.addAll(dbContactHandler.getAllContacts());
populateList();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.general, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void goToContactCreation(View view) {
Intent intent = new Intent(this, ContactCreation.class);
startActivity(intent);
}
//Contact
private void populateList() {
ArrayAdapter<Contact> adapter = new ContactListAdapter();
contactListView.setAdapter(adapter);
}
private class ContactListAdapter extends ArrayAdapter<Contact> {
public ContactListAdapter() {
super (General.this, R.layout.contact_listview, Contacts);
}
#Override
public View getView(int position, View view, ViewGroup parent) {
if (view == null)
view = getLayoutInflater().inflate(R.layout.contact_listview, parent, false);
Contact currentContact = Contacts.get(position);
TextView firstName = (TextView) view.findViewById(R.id.txtFirstName);
firstName.setText(currentContact.getFirstName());
TextView lastName = (TextView) view.findViewById(R.id.txtLastName);
lastName.setText(currentContact.getLastName());
return view;
}
}
}
My DbContactHandler :
package avappmobile.fourwe;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.util.ArrayList;
import java.util.List;
/**
* Created by a.vescera on 13/11/2014.
*/
public class DatabaseContactHandler extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "fourWe",
TABLE_CONTACTS = "contacts",
KEY_ID = "id",
KEY_FIRSTNAME = "firstName",
KEY_LASTNAME = "lastName",
KEY_PHONE = "phone",
KEY_EMAIL = "email",
KEY_MONEYLEND = "moneyLend",
KEY_MONEYBORROWED = "moneyBorrowed",
KEY_STUFFLEND = "stuffLend",
KEY_STUFFBORROWED = "stuffBorrowed";
public DatabaseContactHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_CONTACTS + "(" + KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + KEY_FIRSTNAME + " TEXT," +
KEY_LASTNAME + " TEXT," + KEY_PHONE + " TEXT," + KEY_EMAIL + " TEXT," + KEY_MONEYLEND + " INTEGER," + KEY_MONEYBORROWED + " INTEGER," +
KEY_STUFFLEND + " INTEGER," + KEY_STUFFBORROWED + " INTEGER)");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_CONTACTS);
onCreate(db);
}
// Method to create a contact.
public void createContact(Contact contact) {
SQLiteDatabase db = getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_FIRSTNAME, contact.getFirstName());
values.put(KEY_LASTNAME, contact.getLastName());
values.put(KEY_PHONE, contact.getPhone());
values.put(KEY_EMAIL, contact.getEmail());
values.put(KEY_MONEYLEND, 0);
values.put(KEY_MONEYBORROWED, 0);
values.put(KEY_STUFFLEND, 0);
values.put(KEY_STUFFBORROWED, 0);
db.insert(TABLE_CONTACTS, null, values);
db.close();
}
// Method to get the details of a specific contact by an id.
public Contact getContactId(int id) {
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query(TABLE_CONTACTS, new String[] { KEY_ID, KEY_FIRSTNAME, KEY_LASTNAME, KEY_PHONE, KEY_EMAIL, KEY_MONEYLEND,
KEY_MONEYBORROWED, KEY_STUFFLEND, KEY_STUFFBORROWED }, KEY_ID + "=?", new String[] { String.valueOf(id) }, null, null, null, null );
if (cursor != null)
cursor.moveToFirst();
Contact contact = new Contact(Integer.parseInt(cursor.getString(0)), cursor.getString(1), cursor.getString(2), cursor.getString(3), cursor.getString(4),
Integer.parseInt(cursor.getString(5)),Integer.parseInt(cursor.getString(6)),Integer.parseInt(cursor.getString(7)),Integer.parseInt(cursor.getString(8)));
db.close();
cursor.close();
return contact;
}
// Method to get the details of a specific contact by firstName and lastName.
public Boolean getContact(String firstName, String lastName) {
SQLiteDatabase db = getReadableDatabase();
Contact contact;
Cursor cursor = db.query(TABLE_CONTACTS, new String[] { KEY_ID, KEY_FIRSTNAME, KEY_LASTNAME, KEY_PHONE, KEY_EMAIL, KEY_MONEYLEND,
KEY_MONEYBORROWED, KEY_STUFFLEND, KEY_STUFFBORROWED }, KEY_FIRSTNAME + "=?" + " AND " + KEY_LASTNAME + "=?", new String[] { firstName, lastName }, null, null, null, null );
if (cursor != null && cursor.moveToFirst()) {
db.close();
cursor.close();
return true;
} else {
db.close();
cursor.close();
return false;
}
}
// Method to delete a specific contact.
public void deleteContact(Contact contact) {
SQLiteDatabase db = getWritableDatabase();
db.delete(TABLE_CONTACTS, KEY_ID + "=?", new String[] { String.valueOf(contact.getId()) });
db.close();
}
// Method to get the total number of existing contacts into the DB.
public int getContactsCount() {
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_CONTACTS, null);
int count = cursor.getCount();
db.close();
cursor.close();
return count;
}
// Method to update the details of a specific contact.
public int updateContact(Contact contact) {
SQLiteDatabase db = getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_FIRSTNAME, contact.getFirstName());
values.put(KEY_LASTNAME, contact.getLastName());
values.put(KEY_PHONE, contact.getPhone());
values.put(KEY_EMAIL, contact.getEmail());
values.put(KEY_MONEYLEND, contact.getMoneyLend());
values.put(KEY_MONEYBORROWED, contact.getMoneylBorrowed());
values.put(KEY_STUFFLEND, contact.getStuffLend());
values.put(KEY_STUFFBORROWED, contact.getStuffBorrowed());
int rowsAffected = db.update(TABLE_CONTACTS, values, KEY_ID + "=?", new String[] { String.valueOf(contact.getId()) });
db.close();
return rowsAffected;
}
// Method to get the list of the details of all the contacts present into the DB.
public List<Contact> getAllContacts() {
List<Contact> contacts = new ArrayList<Contact>();
SQLiteDatabase db = getWritableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_CONTACTS, null);
if (cursor.moveToFirst()) {
do {
contacts.add(new Contact(Integer.parseInt(cursor.getString(0)), cursor.getString(1), cursor.getString(2), cursor.getString(3), cursor.getString(4),
Integer.parseInt(cursor.getString(5)),Integer.parseInt(cursor.getString(6)),Integer.parseInt(cursor.getString(7)),Integer.parseInt(cursor.getString(8))));
}
while (cursor.moveToNext());
}
cursor.close();
db.close();
return contacts;
}
}
I don't put the detail of the Contact class, but if you think you need it, please feel free to ask me.
I put then the Design part of my main activity:
<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"
tools:context="avappmobile.fourwe.General">
<TabHost
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/tabHost">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TabWidget
android:id="#android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"></TabWidget>
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:id="#+id/tabHome"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<Button
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/new_contact"
android:id="#+id/btnNewContact"
android:onClick="goToContactCreation"
android:enabled="true"
android:layout_gravity="right" />
</LinearLayout>
<LinearLayout
android:id="#+id/tabContact"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="#string/contacts_list"
android:id="#+id/txtMyContacts"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp" />
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/listViewContact"
android:layout_marginTop="20dp" />
</LinearLayout>
<LinearLayout
android:id="#+id/tabMoney"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"></LinearLayout>
<LinearLayout
android:id="#+id/tabStuff"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"></LinearLayout>
</FrameLayout>
</LinearLayout>
</TabHost>
</LinearLayout>
And the layout created to display my contacts on the secont Tab.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="#string/first_name_contact"
android:id="#+id/txtFirstName"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:id="#+id/txtLastName"
android:layout_gravity="center_horizontal"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:text="#string/first_name_contact"
android:singleLine="false" />
</RelativeLayout>
Thanks.
After further investigation on internet, I found that with the latest version of android, it might be more interesting to show a file with tab (and each tab having a different file, which is my goal) using the ViewPager.
A quick and correctly defined tutorial is available here : http://architects.dzone.com/articles/android-tutorial-using.
I then close my subject since I'm now focused on this way of doing my work.
Regards.

Resources