получить путь к изображению из sqlite в адаптере изображения (GridView на Xamarin Android C#) - PullRequest
0 голосов
/ 05 мая 2020

Я хочу отображать свое изображение в виде сетки. Изображение исходит из пути, а путь хранится в базе данных SQLite. Я пробую руководство из MSDN здесь https://docs.microsoft.com/en-us/xamarin/android/user-interface/layouts/grid-view, и я изменил и изменил свой resource.drawable.image на путь к изображению (путь к изображению из базы данных), но я не знаю, как это сделать который. Я пытаюсь использовать метод растрового изображения, но все еще не понимаю, как сделать массив с помощью этого метода. Я хочу получить данные изображения, такие как название фотографии, описание фотографии и путь к фотографии из базы данных, и сохранить их в моем List <> или массиве.

Я уже создаю базу данных и пытаюсь вызвать ее, но, Я все еще запутался. Пожалуйста, помогите мне.

Итак, это класс объекта для таблицы. Он называется Photo.cs

[Table("tblPhoto")]
    public class Photo
    {
        [PrimaryKey, AutoIncrement, Column("pkPhotoID")]
        public int PhotoID { get; set; }
    [Column("fkUserID")]
    public int UserID { get; set; }
    public string PhotoPath { get; set; }
    public string PhotoName { get; set; }
    public string PhotoDescription { get; set; }
    private DateTime _creationDate;

    public string CreationDate
    {
        get { return _creationDate.ToString(); }
        set { _creationDate = DateTime.ParseExact(value, "yyyy:MM:dd HH:mm:ss", null); }
    }

    private DateTime _uploadDate;
    public string UploadDate
    {
        get { return _uploadDate.ToString(); }
        set { _uploadDate = DateTime.Parse(value); }
    }
    //show User Photo
    public static Photo ShowUserPhoto()
    {
        return DBManager.Instance.Query<Photo>($"SELECT * FROM tblPhoto a JOIN tblUser b WHERE a.UserID== b.UserID").FirstOrDefault();
    }

    //show photo path and its photo
    public static Photo ShowPhotoPath(string aPhotoPath)
    {
        return DBManager.Instance.Query<Photo>($"SELECT * FROM tblPhoto WHERE PhotoPath=='{aPhotoPath}'").FirstOrDefault();
    }

    //show all
    public static Photo ShowAllPhoto()
    {
        return DBManager.Instance.Query<Photo>($"SELECT * FROM tblPhoto").FirstOrDefault();
    }

, а второй предназначен для ImageAdapter, потому что я хочу отображать изображение в gridview. Он называется ImageAdapter.cs

public class ImageAdapter : BaseAdapter
    {
        private Context context;
        private List<string> gridViewString;
        private List<string> gridViewImage;
        public ImageAdapter(Context context, List<string> gridViewstr, List<string> gridViewImage)
        {
            this.context = context;
            gridViewString = gridViewstr;
            this.gridViewImage = gridViewImage;
        }
        public override int Count
        {
            get
            {
                return gridViewString.Count;
            }
        }
    public override Java.Lang.Object GetItem(int position)
    {
        return null;
    }

    public override long GetItemId(int position)
    {
        return 0;
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        View view;
        LayoutInflater inflater = (LayoutInflater)context.GetSystemService(Context.LayoutInflaterService);
        if (convertView == null)
        {
            view = new View(context);
            view = inflater.Inflate(Resource.Layout.gridview_layout, null);
            TextView txtview = view.FindViewById<TextView>(Resource.Id.textPhotoTitleViewGrid);
            ImageView imgview = view.FindViewById<ImageView>(Resource.Id.imageViewGrid);

            txtview.Text = gridViewString[position];
            imgview.SetImageBitmap(GetImageBitmapFromDB(gridViewImage[position]));
        }
        else
        {
            view = (View)convertView;
        }
        return view;
    }

    private Android.Graphics.Bitmap GetImageBitmapFromDB(string aPath)
    {
        Android.Graphics.Bitmap imageBitmap = null;

        var _getPath = Model.Photo.ShowPhotoPath(aPath);
        {
            var imgPath = _getPath.ShowPhotoPath(aPath);
            if (imgPath != null && imgPath.Length > 0)
            {
                imageBitmap = Android.Graphics.BitmapFactory.DecodeFile(imgPath);
            }
        }
        return imageBitmap;
    }
}

, и последний - это класс фрагментов с именем Fragment_home.cs. Изображение должно отображаться здесь

public class Fragment_Home : Android.Support.V4.App.Fragment
    {
        List<string> m_gridviewstring = new List<string>();
        List<string> m_imgview = new List<string>();
        GridView m_gridview;
        public override void OnCreate(Bundle aSavedInstanceState)
        {
            base.OnCreate(aSavedInstanceState);
        }

        public static Fragment_Home NewInstance()
        {
            var _frag1 = new Fragment_Home { Arguments = new Bundle() };
            return _frag1;
        }

        public override View OnCreateView(LayoutInflater aInflater, ViewGroup aContainer, Bundle aSavedInstanceState)
        {
            var _ignored = base.OnCreateView(aInflater, aContainer, aSavedInstanceState);
            //String stringData = Arguments.GetString("email");
            View _view =  aInflater.Inflate(Resource.Layout.FragmentHome, null);

            //var gridview = _view.FindViewById<GridView>(Resource.Id.gridview);
            //gridview.Adapter = new ImageAdapter(Context);

            //gridview.ItemClick += Gridview_ItemClick;

            //return _view;

            var _retrievePic = Model.Photo.ShowAllPhoto();
            //_retrievePic.PhotoPath;

            ImageAdapter adapter = new ImageAdapter(Activity, m_gridviewstring, m_imgview);
            m_gridview = _view.FindViewById<GridView>(Resource.Id.grid_view_image_text);
            m_gridview.Adapter = adapter;
            return _view;
        }
    }

Пожалуйста, помогите мне, любая помощь?

1 Ответ

0 голосов
/ 05 мая 2020

Я размещаю два изображения по пути /storage/emulated/0/DCIM/Camera/ и пути "/storage/emulated/0/Pictures". Для тестирования я переименовываю имена фотографий.

Здесь работает gif (пожалуйста, не обращайте внимания на фрагменты вложений, я не хочу создавать новую демонстрацию от начала до конца, я использовал свою предыдущую демонстрацию).

enter image description here

Во-первых, я создаю PhotoDAO.cs, он вставляет данные в БД и считывает все данные из БД. Я указал PhotoPath и PhotoName при вставке данных в БД.

  public class PhotoDAO
    {
      static  SQLiteConnection db;

        public List<Photo> GetAllPhotos()
        {
            Console.WriteLine("Reading data");
            var table = db.Table<Photo>();
            List<Photo> photos = table.ToList<Photo>();


            return photos;
        }
        public static void DoSomeDataAccess()
        {
            Console.WriteLine("Creating database, if it doesn't already exist");
            string dbPath = Path.Combine(
                 System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal),
                 "Photo1.db3");
            db = new SQLiteConnection(dbPath);
            db.CreateTable<Photo>();
            if (db.Table<Photo>().Count() == 0)
            {
                // only insert the data if it doesn't already exist
                var newPhoto1 = new Photo();
                newPhoto1.UserID = 1;
                newPhoto1.PhotoPath = "/storage/emulated/0/Pictures/";
                newPhoto1.PhotoName = "icon.png";
                newPhoto1.PhotoDescription = "This is a hamburger";
                db.Insert(newPhoto1);

                var newPhoto2 = new Photo();
                newPhoto2.UserID = 2;
                newPhoto2.PhotoPath = "/storage/emulated/0/Pictures/";
                newPhoto2.PhotoName = "person.jpg";
                newPhoto2.PhotoDescription = "This is a person";
                db.Insert(newPhoto2);

                var newPhoto3 = new Photo();
                newPhoto3.UserID = 3;
                newPhoto3.PhotoPath = "/storage/emulated/0/DCIM/Camera/";
                newPhoto3.PhotoName = "IMG1.jpg";
                newPhoto3.PhotoDescription = "This is a IMG1";
                db.Insert(newPhoto3);

                var newPhoto4 = new Photo();
                newPhoto4.UserID = 4;
                newPhoto4.PhotoPath = "/storage/emulated/0/DCIM/Camera/";
                newPhoto4.PhotoName = "IMG2.jpg";
                newPhoto4.PhotoDescription = "This is a IMG2";
                db.Insert(newPhoto4);

            }  
        }
    }

Затем в Fragment_Gallery.cs мы устанавливаем Adapter для GridView. Вот код.

    public class Fragment_Gallery : Android.Support.V4.App.Fragment
    {
        public override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Create your fragment here
        }
        public static Fragment_Gallery NewInstance()
        {
            var frag1 = new Fragment_Gallery { Arguments = new Bundle() };
            return frag1;
        }
        public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {

            var ignored = base.OnCreateView(inflater, container, savedInstanceState);
            View view = inflater.Inflate(Resource.Layout.galleryfragment, null);

            var gridview = view.FindViewById<GridView>(Resource.Id.gridview);

            PhotoDAO.DoSomeDataAccess();
            var photoDAO=new PhotoDAO();
            List<Photo> photos=photoDAO.GetAllPhotos();
            gridview.Adapter = new MyAdapter(this, photos);
            return view;
        }
    }

Вот код моего адаптера gridview. Я создаю CustomView для тестирования, если вам понадобится настроить элемент в gridview в будущем. Я установил источник Imageview по локальному пути, см. Метод GetView.

    internal class MyAdapter :BaseAdapter<Photo>
    {
        private Fragment_Gallery fragment_Gallery;
        private List<Photo> photos;

        public MyAdapter(Fragment_Gallery fragment_Gallery, List<Photo> photos)
        {
            this.fragment_Gallery = fragment_Gallery;
            this.photos = photos;
        }

        public override Photo this[int position] => photos[position];

        public override int Count => photos.Count;



        public override long GetItemId(int position)
        {
           return position;
        }

        public override View GetView(int position, View convertView, ViewGroup parent)
        {

            View view = convertView;
            if (view == null) // no view to re-use, create new
                view = fragment_Gallery.LayoutInflater.Inflate(Resource.Layout.CustomView, null);
            view.FindViewById<TextView>(Resource.Id.custUserID).Text = photos[position].UserID.ToString();
            view.FindViewById<TextView>(Resource.Id.custPhotoPath).Text = photos[position].PhotoPath;
            view.FindViewById<TextView>(Resource.Id.custPhotoName).Text = photos[position].PhotoName;
            view.FindViewById<TextView>(Resource.Id.custPhotoDescription).Text = photos[position].PhotoDescription;
            string imgFile = photos[position].PhotoPath + photos[position].PhotoName;
            Bitmap myBitmap = BitmapFactory.DecodeFile(imgFile);

            view.FindViewById<ImageView>(Resource.Id.custImage).SetImageBitmap(myBitmap);
            return view;
        }


    }

Вот макет примерно CustomView

<?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">
    <ImageView  
    android:layout_width="200dp"
    android:layout_height="200dp" 
    android:id="@+id/custImage" />
    <TextView
    android:layout_width="match_parent"
    android:layout_height="20dp"
    android:id="@+id/custUserID" 
    android:text="@string/abc_action_bar_home_description"
    />
    <TextView
    android:layout_width="match_parent"
    android:layout_height="20dp"
    android:id="@+id/custPhotoPath" 
    android:text="@string/abc_action_bar_home_description"
    />
    <TextView
    android:layout_width="match_parent"
    android:layout_height="20dp"
    android:id="@+id/custPhotoName" 
    android:text="@string/abc_action_bar_home_description"
    />
        <TextView
    android:layout_width="match_parent"
    android:layout_height="20dp"
    android:id="@+id/custPhotoDescription" 
    android:text="@string/abc_action_bar_home_description"
    />



</LinearLayout>

В конце, пожалуйста, не забудьте добавить android.permission.WRITE_EXTERNAL_STORAGE в вашем AndroidManifest.xml

Вот моя демонстрация, вы можете скачать ее и провести тест (пожалуйста, добавьте изображения, такие как мой класс PersonDAO, или вы можете изменить имя изображения в классе PersonDAO).

https://drive.google.com/file/d/1ipw534Q0C4UxHva3Jiv5SoI0KycifpmI/view?usp=sharing

===== update =======

Если вы хотите достичь click событие, вы можете использовать gridview.ItemClick += Gridview_ItemClick; для его достижения. Если позиция изображения от адаптера не найдена, добавьте точку останова Photo photo = photos[e.Position]; в Gridview_ItemClick, если вы правильно получили e.Position.

   public class Fragment_Gallery : Android.Support.V4.App.Fragment
    {
        public override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Create your fragment here
        }
        public static Fragment_Gallery NewInstance()
        {
            var frag1 = new Fragment_Gallery { Arguments = new Bundle() };
            return frag1;
        }
        List<Photo> photos;
        public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {

            var ignored = base.OnCreateView(inflater, container, savedInstanceState);
            View view = inflater.Inflate(Resource.Layout.galleryfragment, null);

            GridView gridview = view.FindViewById<GridView>(Resource.Id.gridview);
            gridview.ItemClick += Gridview_ItemClick;

            PhotoDAO.DoSomeDataAccess();
            var photoDAO=new PhotoDAO();
            photos=photoDAO.GetAllPhotos();

            gridview.Adapter = new MyAdapter(this, photos);
            return view;
        }

        private void Gridview_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
        {
            // throw new NotImplementedException();

            Photo photo = photos[e.Position];
            Intent intent= new Intent(Context, typeof(DetailActivity));
            intent.PutExtra("PicName", photo.PhotoName);
            intent.PutExtra("PicDes", photo.PhotoDescription);
            StartActivity(intent);
        }
    }

В DetailActivity вы можете получил информацию об изображении по следующему коду.

   public class DetailActivity : Activity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layout.Detaillayout);
            TextView detailPhotoName = FindViewById<TextView>(Resource.Id.detailPhotoName);
            TextView detailPhotoDescription = FindViewById<TextView>(Resource.Id.detailPhotoDescription);

            Bundle extras =Intent.Extras;
            detailPhotoName.Text = extras.GetString("PicName");
            detailPhotoDescription.Text = extras.GetString("PicDes");
            // Create your application here
        }
    }

Вы хотите увеличить изображение в макете фрагмента или DetailActivity? В макете фрагмента просто установите большее значение для columnWidth=200dp в GridView и откройте CustomView.xml, установите большее значение для android:layout_width="200dp" android:layout_height="200dp" в ImageView

Вот нажмите на запущенный gif.

enter image description here

...