android - 如何使用 PreferenceFragmentCompat 添加可以在 PreferenceScreen 内编辑的 ImageView ?

标签 android android-imageview android-preferences

似乎 PreferenceScreen 中不支持 ImageView 开箱即用,我该如何实现它,所以它类似于 whatsapp 的。
enter image description here

最佳答案

好的,经过一番研究,我确信以下是最新且稳定的解决方案,假设您正在使用 androidx.preference而不是 android.preference在 API 29 中已弃用。

解决步骤

  • 创建自定义布局
  • 通过扩展 Preference 创建新的自定义首选项类类(class)
  • 在您的 preference.xml 中添加这个新类的条目文件
  • 在你的 SettingsFragment 中使用这个类

  • 1 - 自定义布局

    这是一个简单的自定义布局,其中包含我们的 ImageView
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:paddingLeft="16dp">
    
        <ImageView
            android:id="@+id/image"
            android:layout_width="70dp"
            android:layout_height="70dp"
            android:layout_marginEnd="16dp"
            android:src="@drawable/profile" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Syed Ahmed Jamil"
            android:textAppearance="?android:attr/textAppearanceLarge"/>
    
    </LinearLayout>
    

    2 - 通过扩展 Preference 创建一个新的自定义首选项类类(class)

    我们正在覆盖 onBindViewHolder()方法,因为这是我们获得自定义布局 View 的引用,我们从中提取 ImageView .

    虽然您可以为 ImageView 提供点击监听器。直接在onBindViewHolder()此刻,但在您的 SettingsFragment 中提供此点击监听器更有意义。这就是我们创建 setImageClickListener() 的原因。方法。

    我们将使用 setImageClickListener()在第 4 步。
    public class ImageViewPreference extends Preference {
    
        private ImageView imageView;
        View.OnClickListener imageClickListener;
    
        public ImageViewPreference(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        //onBindViewHolder() will be called after we call setImageClickListener() from SettingsFragment
        @Override
        public void onBindViewHolder(PreferenceViewHolder holder) {
            super.onBindViewHolder(holder);
            imageView = (ImageView)holder.findViewById(R.id.image);
            imageView.setOnClickListener(imageClickListener);
        }
    
        public void setImageClickListener(View.OnClickListener onClickListener)
        {
            imageClickListener = onClickListener;
        }
    }
    

    3 - 在您的 preference.xml 中添加这个新类的条目文件

    现在将这个新类添加到您的 preference.xml并使用 app:layout 设置其布局属性。
    <PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
    
        <com.example.preferencefragmentsample.ImageViewPreference
            app:key="image_preference"
            app:layout="@layout/custom_layout" />
    
        <Preference
            app:key="notifications"
            app:title="Notifications"
            app:summary="Enable or disable notifications"
            app:icon="@drawable/ic_notifications_24dp"
            app:iconSpaceReserved="false"
            />
    
        <Preference
            app:key="feedback"
            app:summary="Get to know the developer"
            app:title="About"
            app:icon="@drawable/ic_info_outline_24dp"/>
    
    </PreferenceScreen>
    

    4 - 在你的 SettingsFragment 中使用这个类

    现在只需引用 ImageViewPreference使用 findPreference()通过将您在 preference.xml 中定义的键字符串值传递给它.

    之后只需调用setImageClickListener()并在点击时为其提供您想要的任何功能。举个例子,我只是在烤一条显示“图像已点击”的消息
    public class SettingsFragment extends PreferenceFragmentCompat {
    
        ImageViewPreference imageViewPreference;
    
        @Override
        public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
            setPreferencesFromResource(R.xml.prefs,rootKey);
    
            imageViewPreference = (ImageViewPreference) findPreference("image_preference");
    
            if (imageViewPreference != null)
                imageViewPreference.setImageClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
    
                        //do whatever you want on image click here
                        Toast.makeText(getContext(), "Image Clicked", Toast.LENGTH_SHORT).show();
                    }
                });
    
    
        }
    }
    

    最终输出

    enter image description here

    更新:从 Firebase 云存储加载图像

    NOTE: I haven't had the time to actually test and run this. This is just to give you a flow of how to do it. But I have carefully checked and everything seems fine and it should run as expected. I'll leave some minor changes to you if there are some errors regarding firebase or converting from File to Bitmap.



    先修改ImageViewPreference类,以便它可以接收位图并将其应用到 ImageView .它类似于我们收到并申请 onClickListenerImageView .
    public class ImageViewPreference extends Preference {
    
        private ImageView imageView;
        private Bitmap imageBitmap;
        View.OnClickListener imageClickListener;
    
        public ImageViewPreference(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        //onBindViewHolder() will be called after we call setImageClickListener() and setBitmap() from SettingsFragment
        @Override
        public void onBindViewHolder(PreferenceViewHolder holder) {
            super.onBindViewHolder(holder);
            imageView = (ImageView)holder.findViewById(R.id.image);
            imageView.setOnClickListener(imageClickListener);
            imageView.setImageBitmap(imageBitmap);
        }
    
        public void setImageClickListener(View.OnClickListener onClickListener)
        {
            imageClickListener = onClickListener;
        }
    
        public void setBitmap(Bitmap bitmap)
        {
            imageBitmap = bitmap;
        }
    }
    

    现在假设您已经按照文档配置了 Firebase 云存储。在本地检索图像 File使用 getFile() 来自 firebase 云存储的对象方法并将该文件对象转换为位图。之后只需将该位图发送到 ImageViewPreference使用 setBitmap()我们之前创建的方法。
    public class SettingsFragment extends PreferenceFragmentCompat {
    
        private Bitmap imageBitmap;
        ImageViewPreference imageViewPreference;
    
        @Override
        public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
            setPreferencesFromResource(R.xml.prefs,rootKey);
    
            //Get your image in a local file and convert it into bitmap
            StorageReference storageRef = FirebaseStorage.getInstance().getReference().child("images/yourImage.jpg");
            File localFile = File.createTempFile("myImage", "bmp");
    
            storageRef.getFile(localFile).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
                @Override
                public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
                    //Convert File to Bitmap
                    imageBitmap = BitmapFactory.decodeFile(localFile.getAbsolutePath());
                }
            }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception exception) {
                    // Handle any errors
                }
            });
    
            imageViewPreference = (ImageViewPreference) findPreference("image_preference");
    
            if (imageViewPreference != null)
            {
                imageViewPreference.setImageClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
    
                        //do whatever you want on image click here
                        Toast.makeText(getContext(), "Image Clicked", Toast.LENGTH_SHORT).show();
                    }
                });
    
                //Send the downloaded bitmap to ImageViewPreference
                imageViewPreference.setBitmap(imageBitmap);
            }
    
    
        }
    }
    

    关于android - 如何使用 PreferenceFragmentCompat 添加可以在 PreferenceScreen 内编辑的 ImageView ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59507248/

    相关文章:

    c# - Android 如何以编程方式使线性布局可滚动?

    android - 当 Android 应用程序的客户端请求创建文档时如何创建 pdf

    android - 使用 ion 将图像加载到 android imageView 中会返回模糊的结果

    java - 在 Sony D2203 上运行 PreferenceManager.setDefaultValues 时出现错误,但在 Sony D2403 上运行时它可以正常工作

    java - 警报对话框中的首选项 Activity

    android - 铃声偏好主题

    android - 哪个 com.google.android.gms :play-services-ads version is compatible with com. android.support :appcompat-v7:27. 1.1?

    java - 保存少量数据的最佳方法

    android - 我无法使用计时器播放动画

    java - 具有百分比高度和宽度的相对布局