Skip to content
FlyJingFish edited this page Jan 9, 2024 · 33 revisions

自定义页面样式

使用示例

OpenImage.with(activity).setOpenImageStyle(R.style.MyAppPhotosTheme);
    <style name="MyAppPhotosTheme" >
        <item name="openImage.indicator.type">image</item>
        <item name="openImage.indicator.textFormat">@string/pos_text</item>
        <item name="openImage.viewPager.orientation">horizontal</item>
        <item name="openImage.indicator.textColor">@color/purple_500</item>
        <item name="openImage.indicator.textSize">16sp</item>
        <item name="openImage.indicator.gravity">center_horizontal|bottom</item>
        <item name="openImage.indicator.marginBottom">14dp</item>
        <item name="openImage.indicator.image.interval">4dp</item>
        <item name="openImage.viewPager.pageMargin">10dp</item>
        <item name="openImage.statusBar.fontStyle">dark</item>
        <item name="openImage.indicator.imageRes">@drawable/indicator_image</item>
    </style>

属性一览

    <!--页面背景可以是图片或颜色-->
    <attr name="openImage.background" format="reference|color" />
    <!--页面切换方向-->
    <attr name="openImage.viewPager.orientation" format="enum">
        <enum name="horizontal" value="0" />
        <enum name="vertical" value="1" />
    </attr>
    <!--以下指示器相关距离设置-->
    <attr name="openImage.indicator.marginStart" format="dimension" />
    <attr name="openImage.indicator.marginEnd" format="dimension" />
    <attr name="openImage.indicator.marginTop" format="dimension" />
    <attr name="openImage.indicator.marginBottom" format="dimension" />
    <attr name="openImage.indicator.marginLeft" format="dimension" />
    <attr name="openImage.indicator.marginRight" format="dimension" />
    <!--指示器在页面的位置-->
    <attr name="openImage.indicator.gravity" format="flags">
        <flag name="top" value="0x30" />
        <flag name="bottom" value="0x50" />
        <flag name="left" value="0x03" />
        <flag name="right" value="0x05" />
        <flag name="center_vertical" value="0x10" />
        <flag name="center_horizontal" value="0x01" />
        <flag name="center" value="0x11" />
        <flag name="start" value="0x00800003" />
        <flag name="end" value="0x00800005" />
    </attr>
    <!--指示器文字或图片-->
    <attr name="openImage.indicator.type" format="enum">
        <enum name="text" value="0" />
        <enum name="image" value="1" />
        <enum name="none" value="2" />
    </attr>
    <!--如果指示器是文本可以设置例如(%1$d/%2$d) --> (1/10)-->
    <attr name="openImage.indicator.textFormat" format="reference|string" />
    <!--文本指示器颜色-->
    <attr name="openImage.indicator.textColor" format="reference|color" />
    <!--文本大小-->
    <attr name="openImage.indicator.textSize" format="dimension" />
    <!--图片指示器资源-->
    <attr name="openImage.indicator.imageRes" format="reference" />
    <!--图片指示器每个之间的间隔-->
    <attr name="openImage.indicator.image.interval" format="dimension" />
    <!--图片指示器排列方向-->
    <attr name="openImage.indicator.image.orientation" format="enum">
        <enum name="horizontal" value="0" />
        <enum name="vertical" value="1" />
    </attr>
    <!--页面状态栏字体颜色-->
    <attr name="openImage.statusBar.fontStyle" format="enum">
        <enum name="light" value="1" />
        <enum name="dark" value="2" />
        <enum name="full_screen" value="3" />
    </attr>
    <!--卡片之间的距离-->
    <attr name="openImage.viewPager.pageMargin" format="dimension" />
    <!--触摸关闭方向,如果不设置默认和ViewPager2的方向相反-->
    <attr name="openImage.touchClose.orientation" format="enum">
        <enum name="horizontal" value="0" />
        <enum name="vertical" value="1" />
    </attr>
    <!--触摸时指示器是否隐藏-->
    <attr name="openImage.indicator.touchingHide" format="boolean" />
    <!--下载时是否显示 Toast 的总开关-->
    <attr name="openImage.download.toast" format="boolean" />
    <!--下载开始时 Toast 的文案,文案为空时不显示-->
    <attr name="openImage.download.startToast" format="reference|string" />
    <!--下载结束时 Toast 的文案,文案为空时不显示-->
    <attr name="openImage.download.successToast" format="reference|string" />
    <!--下载失败时 Toast 的文案,文案为空时不显示-->
    <attr name="openImage.download.errorToast" format="reference|string" />
    <!--请求读取外部存储权限失败时的文案,文案为空时不显示-->
    <attr name="openImage.requestWriteExternalStoragePermissionsFail" format="reference|string" />

更多定制使用说明:

一、自定义加载大图核心类(OpenImageGlideLib、OpenImageCoilLib 或 OpenImageFullLib不需要这步)

1,您需要实现BigImageHelper接口并设置它,它是加载大图的关键(建议放在Application中设置)

注意:这个地方只是示例,如果你的项目存在超大图,请注意需要自行处理(否则可能内存溢出或崩溃)。不想自己搞的,可直接用 OpenImageGlideLib(OpenImageCoilLib) 或 OpenImageFullLib

 public class BigImageHelperImpl implements BigImageHelper {
    @Override
    public void loadImage(Context context, String imageUrl, OnLoadBigImageListener onLoadBigImageListener) {
        //加载图片

    }

 }

2、在Application中设置setBigImageHelper

public class MyApplication extends Application {
     @Override
     public void onCreate() {
         super.onCreate();
         //初始化大图加载器
         OpenImageConfig.getInstance().setBigImageHelper(new BigImageHelperImpl());
     }
 }

二,如果有需要自定义视频Fragment页面请实现VideoFragmentCreate 并继承BaseImageFragment或VideoPlayerFragment(在OpenImageFullLib包下)否则动画效果可能不够完善

1、第一步做好相关页面

例1:

(链接 VideoFragmentCreateImpl)

(链接 VideoPlayerFragment)

例2:

(链接 FriendsVideoFragmentCreateImpl)

(链接 FriendsPlayerFragment)

2、通过OpenImageConfig设置可实现全局使用

OpenImageConfig.getInstance().setVideoFragmentCreate(new VideoFragmentCreateImpl());

3、如果需要单独设置区别于全局公共页面的话,可以在OpenImage调用显示时设置

OpenImage.with(this).setVideoFragmentCreate(new VideoFragmentCreateImpl())

三、如果有需要定制图片Fragment页面请实现ImageFragmentCreate 并继承BaseImageFragment否则动画效果可能不够完善

1、做好相关页面,例如:

(链接 ImageFragment)

2,通过OpenImageConfig设置可实现全局使用

OpenImageConfig.getInstance().setImageFragmentCreate(new ImageFragmentImpl());

3、如果需要单独设置区别于全局公共页面的话,可以在OpenImage调用显示时设置

OpenImage.with(this).setImageFragmentCreate(new ImageFragmentCreateImpl());

四、如需在页面上定制更多页面元素可以通过两种方式

1、调用 OpenImage 的 addMoreView ,此方法可多次调用,添加很多个View(但不要将同一个View添加多次……)

2、调用 OpenImage 的 setUpperLayerFragmentCreate 设置一个fragment,fragment 需要继承 BaseInnerFragment。例如:

(链接 FriendLayerFragmentCreateImpl)

(链接 FriendsFragment)

然后打开大图时设置它即可

OpenImage.with(this).setUpperLayerFragmentCreate(new FriendLayerFragmentCreateImpl(),bundle, false, false);

使用方式2的好处在于可以传入你想要的数据,在Fragment中写你的逻辑代码,相当于大图页面是你定制的,可以看apk的朋友圈功能,就是用的这个功能

在这介绍下BaseInnerFragment,它里边内置了一些方法,您很可能用到,目前有(以下方法请在 onViewCreated 中调用,不要在onCreateView中使用)

 addOnItemLongClickListener removeOnItemLongClickListener 添加移除 长按Item监听
 addOnItemClickListener removeOnItemClickListener 添加移除 点击Item监听
 addOnSelectMediaListener removeOnSelectMediaListener 添加移除 切换图片监听 
 上边的监听都会返给你正在显示的数据和position

五、如果以上方式setUpperLayerFragmentCreate还不能满足您的定制需求,可以继承 OpenImageActivity 页面,你可以这样做

例如:

布局:

<?xml version="1.0" encoding="utf-8"?>
<com.flyjingfish.openimagelib.widget.TouchCloseLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent">
   <!--这个是就是拖动时改变透明度的背景你可以换成其他View,例如ImageView-->
   <View
       android:id="@+id/v_bg"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:background="@android:color/black"
       />
   <FrameLayout
       android:id="@+id/fl_touch_view"
       android:layout_width="match_parent"
       android:layout_height="match_parent">

       <!--这块就是你可以创作的地方,你可以写一些其他布局例如RelativeLayout来包裹ViewPager2-->

       <androidx.viewpager2.widget.ViewPager2
           android:id="@+id/viewPager"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:layout_gravity="center"/>

   </FrameLayout>

</com.flyjingfish.openimagelib.widget.TouchCloseLayout>
其实布局有很多种组合方式,可以看下以下3个例子:

my_activity_viewpager

my_activity_viewpager2

my_activity_kuaishou

你的Activity:

public class MyBigImageActivity extends OpenImageActivity {

  private MyActivityViewpagerBinding rootBinding;

  @Override
  public View getContentView() {
      rootBinding = MyActivityViewpagerBinding.inflate(getLayoutInflater());
      return rootBinding.getRoot();
  }

  @Override
  public View getBgView() {
      return rootBinding.vBg;
  }


  @Override
  public FrameLayout getViewPager2Container() {
      return rootBinding.flTouchView;
  }

  @Override
  public ViewPager2 getViewPager2() {
      return rootBinding.viewPager;
  }

  @Override
  public TouchCloseLayout getTouchCloseLayout() {
      return rootBinding.getRoot();
  }
}

在这介绍下OpenImageActivity,它里边内置了一些方法,您很可能用到,目前有

 addOnItemLongClickListener removeOnItemLongClickListener 添加移除 长按Item监听
 addOnItemClickListener removeOnItemClickListener 添加移除 点击Item监听
 addOnSelectMediaListener removeOnSelectMediaListener 添加移除 切换图片监听 
 上边的监听都会返给你正在显示的数据和position

 openImageAdapter 是相册 ViewPager2 的的适配器(如果你需要加载更多数据会用到这个)

更多在OpenImageActivity中使用示例:

KuaiShouActivity

<activity
    android:name=".xxx.XXXActivity"
    android:configChanges="orientation|keyboardHidden|screenSize"
    android:exported="true"
    android:windowSoftInputMode="stateAlwaysHidden|adjustResize"
    android:theme="@style/Theme.OpenImageTheme">
    <meta-data
        android:name="notch.config"
        android:value="portrait|landscape" />
    <meta-data
        android:name="android.notch_support"
        android:value="true" />
    <meta-data
        android:name="android.max_aspect"
        android:value="2.2" />
</activity>

AndroidManifest.xml 中配置它,如需定制主题,可继承 Theme.OpenImageTheme 再配置

然后在你调用显示的地方,设置它

OpenImage.with(context).setOpenImageActivityCls(MyBigImageActivity.class)

另外还可以传入数据

OpenImage.with(context).setOpenImageActivityCls(MyBigImageActivity.class, bundleKey, bundle) 

注意 setOpenImageActivityCls 还支持设置更新数据更多详细内容请看这两个 Demo KuaiShouDemoActivityMsgRvAdapter

OpenImage.with(context).setOpenImageActivityCls(MessageVpActivity.class, new OnUpdateViewListener() {
    @Override
    public void onAdd(Collection<? extends OpenImageUrl> data, UpdateViewType updateViewType) {
        if (updateViewType == UpdateViewType.FORWARD){
            messageBeans.addAll(0, (Collection<? extends MessageBean>) data);
            notifyDataSetChanged();
        }else if (updateViewType == UpdateViewType.BACKWARD){
            messageBeans.addAll((Collection<? extends MessageBean>) data);
            notifyDataSetChanged();
        }
    }

    @Override
    public void onRemove(OpenImageUrl openImageUrl) {
        messageBeans.remove(openImageUrl);
        notifyDataSetChanged();
    }

    @Override
    public void onReplace(int position,OpenImageUrl oldData, OpenImageUrl newData) {
        int index=0;
        for (MessageBean bean : messageBeans) {
            if (bean == oldData){
                messageBeans.set(index, (MessageBean) newData);
                notifyDataSetChanged();
                return;
            }
            index++;
        }
    }
})

上边回调对应的方法触发条件是需要你在继承自 OpenImageActivity 的 Activity 中,使用 openImageAdapter 具体对应关系如下:

//向数据末尾增加新数据
openImageAdapter.addData(datas);  ----------------------------->  onAdd(data,UpdateViewType.BACKWARD)
//向数据末尾增加新数据(如果你不想更新前边页面,可以使用此方法,方便在回调中返回 UpdateViewType.NONE 以此作为标记)
openImageAdapter.addData(datas,UpdateViewType.NONE);  --------->  onAdd(data,UpdateViewType.NONE)
//向数据前边增加新数据
openImageAdapter.addFrontData(datas);  ------------------------>  onAdd(data,UpdateViewType.FORWARD)
//向数据前边增加新数据(如果你不想更新前边页面,可以使用此方法,方便在回调中返回 UpdateViewType.NONE 以此作为标记)
openImageAdapter.addFrontData(datas,UpdateViewType.NONE);  ---->  onAdd(data,UpdateViewType.NONE)
//删除数据
openImageAdapter.removeData(position);  ----------------------->  onRemove(openImageUrl)
//替换或更新数据
openImageAdapter.replaceData(position,openImageUrl);  --------->  onReplace(position,oldBean,newBean)
//获取所有数据
openImageAdapter.getData()

六,你的数据实体类需要实现OpenImageUrl接口

public interface OpenImageUrl extends Serializable {
   /**
    * @return 返回应该浏览的大图或者视频的大图封面
    */
   String getImageUrl();

   /**
    * @return 返回要播放的视频链接
    */
   String getVideoUrl();

   /**
    * @return 返回点击的列表展示的图片链接或者视频的小图封面(没有小图和getImageUrl传一个值)
    */
   String getCoverImageUrl();

   /**
    * @return 返回是视频还是图片
    */
   MediaType getType();
}

七,打开图片时(详细说明点击右侧导航栏看更多)

在点击时调用,按需使用即可(以下以RecyclerView为例介绍)

 OpenImage.with(activity)
        //点击ImageView所在的RecyclerView(也支持设置setClickViewPager2,setClickViewPager,setClickGridView,setClickListView,setClickImageView)
        .setClickRecyclerView(recyclerView,new SourceImageViewIdGet() {
          @Override
          public int getImageViewId(OpenImageUrl data, int position) {
              return R.id.iv_image;//点击的ImageView的Id
          }
       })
       //点击的ImageView的ScaleType类型(如果设置不对,打开的动画效果将是错误的)
       .setSrcImageViewScaleType(ImageView.ScaleType.CENTER_CROP,true)
       //RecyclerView的数据
       .setImageUrlList(datas)
       //点击的ImageView所在数据的位置
       .setClickPosition(position)
       //clickDataPosition 点击的数据所在位置 clickViewPosition 点击的视图所在位置(和上边方法二选一,详细使用方法可看wiki文档)
       //这个方法主要是针对的是像聊天页面那种图文混合的数据,可以看 "聊天页面" Demo
       .setClickPosition(clickDataPosition, clickViewPosition)
       //设置显示下载按钮(可不设置,默认不显示)
       .setShowDownload()
       //可不设置(定制页面样式,详细可看Wiki文档)
       .setOpenImageStyle(R.style.DefaultPhotosTheme)
       //设置显示在页面上层的fragment(可不设置)
       .setUpperLayerFragmentCreate(new FriendLayerFragmentCreateImpl(),bundle,false,false)
       //设置自定义的视频播放fragment页面(可不设置)
       .setVideoFragmentCreate(new VideoFragmentCreateImpl())
       //设置加载失败时显示的图片(可不设置)
       .setErrorResId(R.mipmap.ic_launcher)
       //设置退出页面时,如果页面无对应的ImageView则回到点击位置(类似微信聊天页面的效果)(可不设置)
       .setWechatExitFillInEffect(true)
       //设置true后关闭时,将看不到前一页面正在查看的图片(可不设置)
       .setShowSrcImageView(true)
       //设置自定义的大图外壳页面(可不设置)
       .setOpenImageActivityCls(MyBigImageActivity.class)
       //设置切换图片时前一页面跟随滚动(可不设置)
       .setAutoScrollScanPosition(true)
       //设置画廊效果,参数为左右两侧漏出的宽度(可不设置)
       .setGalleryEffect(10)
       //设置切换图片监听(可不设置)
       .setOnSelectMediaListener(new OnSelectMediaListener() {
           @Override
           public void onSelect(OpenImageUrl openImageUrl, int position) {

           }
       })
       //设置点击监听(可不设置)
       .setOnItemClickListener(new OnItemClickListener() {
           @Override
           public void onItemClick(BaseInnerFragment fragment, OpenImageUrl openImageUrl, int position) {
   
           }
       })
       //设置长按图片监听(可不设置)
       .setOnItemLongClickListener(new OnItemLongClickListener() {
           @Override
           public void onItemLongClick(BaseInnerFragment fragment, OpenImageUrl openImageUrl, int position) {
           
           }
       })
       //设置退出大图页面时的监听(可不设置)
       .setOnExitListener(new OnExitListener() {
           @Override
           public void onExit() {
           
           }
       })
       //设置切换大图时的效果(可不设置,本库中目前只有这一个,如需其他效果可参照ScaleInTransformer自行定义效果)
       .addPageTransformer(new ScaleInTransformer())
       //开始展示大图
       .show();
Clone this wiki locally