图像适配器 Xamarin Android
Image Adapter Xamarin Android
先了解一下背景:我正在制作一个图库作为我应用程序的一部分,因为我发现无法在 android 中导入多张图片。为此,下面的代码访问相机目录,然后通过适配器将图像放在 GridView 中,但适配器在列表而不是网格中显示图片,还有一个更大的问题是应用程序不会在加载后大约一秒钟崩溃,但它确实显示了 Xamarin 水印(此版本仅适用于 24 小时消息)。
我需要你帮助的问题是,为什么我的应用程序不会 运行 在 phone 中,为什么它会在模拟器中 运行,其次为什么它显示在列表中而不是网格?
我选择了写外部存储和读外部存储权限。
如果有人能帮助我,我将不胜感激。
我的主文件
public class MainActivity : Activity
{
List<string> URIs=new List<string> ();// un parsed URIs
List<ImageView> IMGs;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
SetContentView(Resource.Layout.Main);
IMGs = new List<ImageView> ();
GetImageFileNames ();
MakeImageViews ();
Toast.MakeText (this,"this is sparta",ToastLength.Short).Show ();
GridView gridView = FindViewById<GridView> (Resource.Id.gridView1);
PicAdapter PA= new PicAdapter (this,IMGs);
gridView.Adapter = PA;
}
void MakeImageViews ()
{
foreach (string uri in URIs)
{
Android.Net.Uri _uri = Android.Net.Uri.Parse(uri);
ImageView imageView = new ImageView(this);
imageView.LayoutParameters = new GridView.LayoutParams (85, 85);
imageView.SetScaleType (ImageView.ScaleType.CenterCrop);
imageView.SetPadding (8, 8, 8, 8);
imageView.SetImageURI (_uri);
IMGs.Add (imageView);
}
}
#region GetFileNames
void GetImageFileNames ()
{
//ImageView imageView = FindViewById<ImageView> (Resource.Id.imageView1);
DirectoryInfo dir = new DirectoryInfo (Android.OS.Environment.GetExternalStoragePublicDirectory (Android.OS.Environment.DirectoryDcim).AbsolutePath + "/Camera");
if (dir.Exists == true) {
FileInfo[] file = dir.GetFiles ();
foreach (FileInfo file2 in file) {
if (file2.Extension == ".jpg" || file2.Extension == ".jpeg" || file2.Extension == ".gif" ||
file2.Extension == ".png") {
URIs.Add (file2.ToString ());
}
}
// ImageView ImageView = FindViewById<ImageView> (Resource.Id.imageView1);
// ImageView.SetImageURI (URIs [1]);
//
} else {
Toast.MakeText (this, "Can not read files from camera folder or no files in camera folder", ToastLength.Short).Show ();
}
}
#endregion
}
适配器
public class PicAdapter: BaseAdapter<ImageView>
{ Context context;
List<ImageView> IMGs;
public PicAdapter (Context c,List<ImageView> imgs)
{
this.context = c;
this.IMGs = imgs;
}
#region implemented abstract members of BaseAdapter
public override long GetItemId (int position)
{
return position;
}
public override Android.Views.View GetView (int position, Android.Views.View convertView, Android.Views.ViewGroup parent)
{
View tile = convertView;
if (tile == null)
{
tile = LayoutInflater.From(context).Inflate(Resource.Layout.SinglePicTile,null,false);
}
ImageView picture = tile.FindViewById<ImageView>(Resource.Id.PicTile); // here you are making each grid view tiles
picture = IMGs [position];
return picture;
}
public override int Count {
get {return IMGs.Count;}
}
#endregion
#region implemented abstract members of BaseAdapter
public override ImageView this [int index] {
get {
return IMGs [index];
}
}
#endregion
}
Xaml、Main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/gridView">
<GridView
android:minWidth="25px"
android:minHeight="25px"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/gridView1" />
</LinearLayout>
适配器模板:
<?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">
<ImageView
android:src="@android:drawable/ic_menu_gallery"
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/PicTile"
android:padding="10dp"
android:maxWidth="100dp"
android:maxHeight="100dp"
android:cropToPadding="true" />
</LinearLayout>
而不是创建 ImageView
个实例并将它们交给您的 Adapter
。相反,您应该只将字符串列表交给它并让它处理初始化。否则你很快就会 运行 内存不足。
所以将您的 Adapter
更改为:
public class PicAdapter : BaseAdapter<string>
{
private List<string> _imageUrls = new List<string>();
public void AddImage(string uri)
{
_imageUrls.Add(uri);
}
...
}
然后在 GetView
中,您将实例化视图,或重复使用前一个单元格中的视图并设置 URI,该 URI 包含在您传递给 Adapter
的字符串之一中。
你的问题基本上出在这一行:
picture = IMGs [position];
这段代码并没有神奇地将ImageView
添加到布局中,您需要操作从FindViewById
获得的ImageView
:
public override View GetView (int position, View convertView, ViewGroup parent)
{
var view = convertView;
if (view == null)
view = LayoutInflater.From(context).Inflate(Resource.Layout.SinglePicTile, parent, false);
var picture = tile.FindViewById<ImageView>(Resource.Id.PicTile);
picture.SetImageURI(Android.Net.Uri.Parse(_imageUrls[position]));
return picture;
}
所以基本上放弃 MakeImageViews()
方法,因为这是 Adapter
应该处理的事情。
先了解一下背景:我正在制作一个图库作为我应用程序的一部分,因为我发现无法在 android 中导入多张图片。为此,下面的代码访问相机目录,然后通过适配器将图像放在 GridView 中,但适配器在列表而不是网格中显示图片,还有一个更大的问题是应用程序不会在加载后大约一秒钟崩溃,但它确实显示了 Xamarin 水印(此版本仅适用于 24 小时消息)。
我需要你帮助的问题是,为什么我的应用程序不会 运行 在 phone 中,为什么它会在模拟器中 运行,其次为什么它显示在列表中而不是网格?
我选择了写外部存储和读外部存储权限。
如果有人能帮助我,我将不胜感激。
我的主文件
public class MainActivity : Activity
{
List<string> URIs=new List<string> ();// un parsed URIs
List<ImageView> IMGs;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
SetContentView(Resource.Layout.Main);
IMGs = new List<ImageView> ();
GetImageFileNames ();
MakeImageViews ();
Toast.MakeText (this,"this is sparta",ToastLength.Short).Show ();
GridView gridView = FindViewById<GridView> (Resource.Id.gridView1);
PicAdapter PA= new PicAdapter (this,IMGs);
gridView.Adapter = PA;
}
void MakeImageViews ()
{
foreach (string uri in URIs)
{
Android.Net.Uri _uri = Android.Net.Uri.Parse(uri);
ImageView imageView = new ImageView(this);
imageView.LayoutParameters = new GridView.LayoutParams (85, 85);
imageView.SetScaleType (ImageView.ScaleType.CenterCrop);
imageView.SetPadding (8, 8, 8, 8);
imageView.SetImageURI (_uri);
IMGs.Add (imageView);
}
}
#region GetFileNames
void GetImageFileNames ()
{
//ImageView imageView = FindViewById<ImageView> (Resource.Id.imageView1);
DirectoryInfo dir = new DirectoryInfo (Android.OS.Environment.GetExternalStoragePublicDirectory (Android.OS.Environment.DirectoryDcim).AbsolutePath + "/Camera");
if (dir.Exists == true) {
FileInfo[] file = dir.GetFiles ();
foreach (FileInfo file2 in file) {
if (file2.Extension == ".jpg" || file2.Extension == ".jpeg" || file2.Extension == ".gif" ||
file2.Extension == ".png") {
URIs.Add (file2.ToString ());
}
}
// ImageView ImageView = FindViewById<ImageView> (Resource.Id.imageView1);
// ImageView.SetImageURI (URIs [1]);
//
} else {
Toast.MakeText (this, "Can not read files from camera folder or no files in camera folder", ToastLength.Short).Show ();
}
}
#endregion
}
适配器
public class PicAdapter: BaseAdapter<ImageView>
{ Context context;
List<ImageView> IMGs;
public PicAdapter (Context c,List<ImageView> imgs)
{
this.context = c;
this.IMGs = imgs;
}
#region implemented abstract members of BaseAdapter
public override long GetItemId (int position)
{
return position;
}
public override Android.Views.View GetView (int position, Android.Views.View convertView, Android.Views.ViewGroup parent)
{
View tile = convertView;
if (tile == null)
{
tile = LayoutInflater.From(context).Inflate(Resource.Layout.SinglePicTile,null,false);
}
ImageView picture = tile.FindViewById<ImageView>(Resource.Id.PicTile); // here you are making each grid view tiles
picture = IMGs [position];
return picture;
}
public override int Count {
get {return IMGs.Count;}
}
#endregion
#region implemented abstract members of BaseAdapter
public override ImageView this [int index] {
get {
return IMGs [index];
}
}
#endregion
}
Xaml、Main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/gridView">
<GridView
android:minWidth="25px"
android:minHeight="25px"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/gridView1" />
</LinearLayout>
适配器模板:
<?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">
<ImageView
android:src="@android:drawable/ic_menu_gallery"
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/PicTile"
android:padding="10dp"
android:maxWidth="100dp"
android:maxHeight="100dp"
android:cropToPadding="true" />
</LinearLayout>
而不是创建 ImageView
个实例并将它们交给您的 Adapter
。相反,您应该只将字符串列表交给它并让它处理初始化。否则你很快就会 运行 内存不足。
所以将您的 Adapter
更改为:
public class PicAdapter : BaseAdapter<string>
{
private List<string> _imageUrls = new List<string>();
public void AddImage(string uri)
{
_imageUrls.Add(uri);
}
...
}
然后在 GetView
中,您将实例化视图,或重复使用前一个单元格中的视图并设置 URI,该 URI 包含在您传递给 Adapter
的字符串之一中。
你的问题基本上出在这一行:
picture = IMGs [position];
这段代码并没有神奇地将ImageView
添加到布局中,您需要操作从FindViewById
获得的ImageView
:
public override View GetView (int position, View convertView, ViewGroup parent)
{
var view = convertView;
if (view == null)
view = LayoutInflater.From(context).Inflate(Resource.Layout.SinglePicTile, parent, false);
var picture = tile.FindViewById<ImageView>(Resource.Id.PicTile);
picture.SetImageURI(Android.Net.Uri.Parse(_imageUrls[position]));
return picture;
}
所以基本上放弃 MakeImageViews()
方法,因为这是 Adapter
应该处理的事情。