【选择图片Jar】全屏DialogFragment实现图片详情预览(十)

1.前言

上一篇文章我们在最后抛出了一个问题。到底我们要如何实现图片的详情页的预览。 如图:
这里写图片描述

相信大家看了标题已经知道了,我们是用DialogFragment实现我们这个功能的!

嘿嘿,可能这个时候会有点惊讶,原来DialogFragment还有这样的效果?

奥秘在哪里呢?等下我们就会来揭晓。

再说两句~~Dialog和Fragment一直是我们开发中又爱又恨的两个东西,Dialog的Api繁多复杂,难以使用! Fragment生命周期很难精准把握,而奇淫巧技非常多!

关于Dialog的问题,Google特意推出了DialogFragment来解决Dialog本身这个原生控件的弱点和不足,目前Google官方推荐使用DialogFragment,而且在实际开发中,发现的确是DialogFragment好用!

那关于Fragment的这个问题,我目前也在爬坑收集各种BUG和技巧中,之后学有所成,再回来分享吧!!因为这个不是三两句话可以完整概括的。 下面附上一条连接:,有兴趣的可以学习完本课程之后看看
关于 Android,用多个 activity,还是单 activity 配合 fragment?-稀土掘金

2.FullScreenFragment布局实现

还是那个问题,我们不能打包资源文件进入Jar所以,还是要手动写代码,虽然过程比较繁琐复杂,但是还是要克服一下,这一次的痛苦,是为日后的快速打下基础!

public class FullScreenFragmentLayout extends RelativeLayout {
    /**
     * Bar条
     */
    private RelativeLayout mBar;
    /**
     * 返回按钮的图片的id,删除的图片id,Bar条底色
     */
    private int mBackIconId, mDeleteIconId, mBarColorId;
    /**
     * Bar条中左边的返回ImageView,右边的返回ImageView
     */
    private ImageView mBackIv, mDeleteIv;
    /**
     * Bar条中的文字控件
     */
    private TextView mNumTv;
    /**
     * ViewPager空间
     */
    private ViewPager mViewPager;
    /**
     * Bar条高度
     */
    private int mBarHeight;
    /**
     * 图标的宽度
     */
    private int mIconWidth;
    /**
     * 图标距离边界的大小
     */
    private int mIconMarginSide;
    /**
     * 文字控件距离边界的大小
     */
    private int mTextMarginSide;
    /**
     * 文字大小
     */
    private int mTextSize;
    /**
     * 文字颜色
     */
    private int mTextColorId;

    private FullScreenFragmentLayout(Context context, int mBackIconId,
            int mDeleteIconId, int mBarColorId, int mBarHeight, int mIconWidth,
            int mIconMarginSide, int mTextMarginSide, int mTextSize,
            int mTextColorId) {
        super(context);
        this.mBackIconId = mBackIconId;
        this.mDeleteIconId = mDeleteIconId;
        this.mBarColorId = mBarColorId;
        this.mBarHeight = mBarHeight;
        this.mIconWidth = mIconWidth;
        this.mIconMarginSide = mIconMarginSide;
        this.mTextMarginSide = mTextMarginSide;
        this.mTextSize = mTextSize;
        this.mTextColorId = mTextColorId;
        initViewPager();
        initBar();
    }

    private void initBar() {
        mBar = new RelativeLayout(getContext());
        if (mBarColorId != -1) {
            mBar.setBackgroundColor(getContext().getResources().getColor(
                    mBarColorId));
        }

        ViewGroup.LayoutParams p = new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, mBarHeight);
        mBar.setLayoutParams(p);
        // bar.setBackgroundColor(getContext().getResources()
        // .getColor(mBarColorId));

        mBackIv = new ImageView(getContext());
        if (mBackIconId != -1) {
            mBackIv.setBackgroundResource(mBackIconId);
        }

        RelativeLayout.LayoutParams backParams = new RelativeLayout.LayoutParams(
                mIconWidth, mIconWidth);
        backParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
        backParams.addRule(RelativeLayout.CENTER_VERTICAL);

        backParams.leftMargin = mIconMarginSide;
        mBackIv.setLayoutParams(backParams);
        mBar.addView(mBackIv);
        mNumTv = new TextView(getContext());
        // 注意 这里直接 无效
        // mNumTv.setTextColor("0xffffff");
        if (mTextColorId == -1) {
            mNumTv.setTextColor(Color.parseColor("#ffffff"));
        } else {
            mNumTv.setTextColor(getContext().getResources().getColor(
                    mTextColorId));
        }
        mNumTv.setTextSize(mTextSize);
        RelativeLayout.LayoutParams numParams = new RelativeLayout.LayoutParams(
                RelativeLayout.LayoutParams.WRAP_CONTENT,
                RelativeLayout.LayoutParams.WRAP_CONTENT);
        numParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
        numParams.addRule(RelativeLayout.CENTER_VERTICAL);
        int tvMargin = mTextMarginSide;
        numParams.leftMargin = tvMargin;
        mNumTv.setLayoutParams(numParams);
        mBar.addView(mNumTv);
        mDeleteIv = new ImageView(getContext());
        if (mDeleteIconId != -1) {
            mDeleteIv.setBackgroundResource(mDeleteIconId);
        }
        RelativeLayout.LayoutParams deleteParams = new RelativeLayout.LayoutParams(
                mIconWidth, mIconWidth);
        deleteParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
        deleteParams.addRule(RelativeLayout.CENTER_VERTICAL);
        deleteParams.rightMargin = mIconMarginSide;
        mDeleteIv.setLayoutParams(deleteParams);
        mBar.addView(mDeleteIv);
        this.addView(mBar);
    }

    private void initViewPager() {
        mViewPager = new ViewPager(getContext());
        ViewGroup.LayoutParams p = new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        mViewPager.setLayoutParams(p);
        this.addView(mViewPager);
    }

    public ViewPager getViewPager() {
        return mViewPager;
    }

    public TextView getNumberTextView() {
        return mNumTv;
    }

    public RelativeLayout getBar() {
        return mBar;
    }

    public static class Builder {
        private Context mContext;
        /**
         * 返回按钮的图片的id,删除的图片id,Bar条底色
         */
        private int mBackIconId, mDeleteIconId, mBarColorId;
        /**
         * Bar条高度
         */
        private int mBarHeight;
        /**
         * 图标的宽度
         */
        private int mIconWidth;
        /**
         * 图标距离边界的大小
         */
        private int mIconMarginSide;
        /**
         * 文字控件距离边界的大小
         */
        private int mTextMarginSide;
        /**
         * 文字大小
         */
        private int mTextSize;
        /**
         * 文字颜色
         */
        private int mTextColorId;

        public Builder(Context context) {
            mContext = context;
            // 初始化默认的大小
            initDefaultConfig();
        }

        private void initDefaultConfig() {
            // 获取屏幕高度
            int screenHeight = ScreenUtil.getScreenHeight(mContext);
            // 获取屏幕宽度
            int screenWidth = ScreenUtil.getScreenWidth(mContext);
            // bar高度为1/13
            mBarHeight = screenHeight / 13;

            mIconWidth = screenWidth / 13;

            mIconMarginSide = mIconWidth / 7;

            mTextSize = (int) (mIconMarginSide * 1.5);

            mTextMarginSide = mTextSize;

            mBackIconId = mBarColorId = mDeleteIconId = mTextColorId = -1;
        }

        public FullScreenFragmentLayout build() {
            return new FullScreenFragmentLayout(mContext, mBackIconId,
                    mDeleteIconId, mBarColorId, mBarHeight, mIconWidth,
                    mIconMarginSide, mTextMarginSide, mTextSize, mTextColorId);
        }

        public Builder setBarHeight(int height) {
            mBarHeight = height;
            return this;
        }

        public Builder setBarColorId(int colorId) {
            mBarColorId = colorId;
            return this;
        }

        public Builder setTextSize(int size) {
            mTextSize = size;
            return this;
        }

        public Builder setTextMarginLeftSize(int marginSize) {
            mTextMarginSide = marginSize;
            return this;
        }

        public Builder setTextColorId(int id) {
            mTextColorId = id;
            return this;
        }

        public Builder setIconSize(int size) {
            mIconWidth = size;
            return this;
        }

        public Builder setIconMarginSize(int marginSize) {
            mIconMarginSide = marginSize;
            return this;
        }

        public Builder setBackIconDrawableId(int id) {
            mBackIconId = id;
            return this;
        }

        public Builder setDeleteIconDrawableId(int id) {
            mDeleteIconId = id;
            return this;
        }
    }
}

这里我们采用了Builder模式进行创建,原因是因为可设置参数太多,采用这种模式比较方便创建。

注意一下Builder构造方式里面对部分参数进行了默认大小处理,这是为了能够正常显示出来。

private void initDefaultConfig() {
            // 获取屏幕高度
            int screenHeight = ScreenUtil.getScreenHeight(mContext);
            // 获取屏幕宽度
            int screenWidth = ScreenUtil.getScreenWidth(mContext);
            // bar高度为1/13
            mBarHeight = screenHeight / 13;

            mIconWidth = screenWidth / 13;

            mIconMarginSide = mIconWidth / 7;

            mTextSize = (int) (mIconMarginSide * 1.5);

            mTextMarginSide = mTextSize;

            mBackIconId = mBarColorId = mDeleteIconId = mTextColorId = -1;
        }

即这段代码。 对id设置为-1表示标记该位没有设置值。

布局代码写起来很慢,也很繁琐。 所以要有耐心! 如果还不太熟悉的话,可以查阅相关资料,这里就不一个一个来讲了!

3.FullScreenFragment的实现

OK!这里也是一个大工程!上好厕所, 拿好板凳围观吧。

首先来揭晓DialogFragment的奥秘:

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 设置全屏
        setStyle(DialogFragment.STYLE_NO_TITLE,
                android.R.style.Theme_Black_NoTitleBar);
    }

就是这一行代码~ 具体的还有其他样式就不在这里讲述了。大家可以看看官方文档。
官方文档:DialogFragment -不用翻墙也可以看!
那么下面我们看看构造方法:

    public static FullScreenFragment newInstance(int barColorId,
            int backIconId, int deleteIconId) {
        FullScreenFragment f = new FullScreenFragment();
        Bundle b = new Bundle();
        b.putInt(KEY_BACK_ICON_ID, backIconId);
        b.putInt(KEY_DELETE_ICON_ID, deleteIconId);
        b.putInt(KEY_BAR_COLOR_ID, barColorId);
        f.setArguments(b);
        return f;
    }

    public static FullScreenFragment newInstance(int barColorId, int barHeight,
            int backIconId, int deleteIconId, int iconWidth,
            int iconMarginSide, int textColor, int textSize,
            int textMarginLeftSize) {
        FullScreenFragment f = new FullScreenFragment();
        Bundle b = new Bundle();
        b.putInt(KEY_BAR_COLOR_ID, barColorId);
        b.putInt(KEY_BAR_HEIGHT, barHeight);
        b.putInt(KEY_BACK_ICON_ID, backIconId);
        b.putInt(KEY_DELETE_ICON_ID, deleteIconId);
        b.putInt(KEY_ICON_SIZE, iconWidth);
        b.putInt(KEY_ICON_MARGIN, iconMarginSide);
        b.putInt(KEY_TEXT_COLOR, textColor);
        b.putInt(KEY_TEXT_SIZE, textSize);
        b.putInt(KEY_TEXT_MARGIN, textMarginLeftSize);
        f.setArguments(b);
        return f;
    }

    private FullScreenFragment() {

    }

这里提供了两个构造方法。有的同学可能有疑问了,为什么要这样写呢?

其实我们可以从Google官方的很多代码看到这样的写法,通过setArguments(..);来传递信息,这是为了防止旋转之后,Android默认调用Fragment无参构造而产生的信息丢失。 具体的可以了解其他相关资料。

回到正题,其实上面那一堆东西都是为了从外部获取资源文件,或者样式,来创建我们FullScreenFragmentLayout的布局,这可以更加适应不同项目的需要。

下面我们来看看onCreateView方法:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // 创建布局
        mRootView = initLayout();
        // 获取控件
        mViewPager = mRootView.getViewPager();
        mNumberTv = mRootView.getNumberTextView();
        mBack = mRootView.getBackImageView();
        mDelete = mRootView.getDeleteImageView();

        // 初始化ViewPager
        initViewPager();
        // 改变文字标题
        postionChange(mCurrentPostion);
        // 要在设置完Adapter之后调用 不然没效果
        mViewPager.setCurrentItem(mCurrentPostion);
        // 初始化监听
        initBarListener();
        return mRootView;
    }

相信都很好理解。

下面贴上其他代码:

    private void initViewPager() {
        // 如果为空或者为0则返回
        if (mPaths == null || mPaths.size() == 0)
            return;
        mImageViews = new ImageView[mPaths.size()];
        for (int i = 0; i < mPaths.size(); i++) {
            mImageViews[i] = new ImageView(getActivity());
        }
        // mViewPager.setOffscreenPageLimit(0);
        mPagerAdapter = new PagerAdapter() {

            @Override
            public boolean isViewFromObject(View paramView, Object paramObject) {
                return paramView == paramObject;
            }

            @Override
            public int getCount() {
                return mPaths.size();
            }

            @Override
            public void destroyItem(ViewGroup container, int position,
                    Object object) {
                ((ViewPager) container).removeView(mImageViews[position]);
            }

            @Override
            public Object instantiateItem(ViewGroup container, int position) {
                ImageView i = mImageViews[position];
                ImageLoaderWrapper.loadFromFile(i, mPaths.get(position));
                ((ViewPager) container).addView(i, 0);
                return i;
            }
        };

        mViewPager.setAdapter(mPagerAdapter);

        mViewPager.addOnPageChangeListener(new OnPageChangeListener() {

            @Override
            public void onPageSelected(int paramInt) {
                // 当前位置
                mCurrentPosition = paramInt;
                postionChange(mCurrentPosition);

            }

            @Override
            public void onPageScrolled(int paramInt1, float paramFloat,
                    int paramInt2) {
                // 上一个位置 偏移量 下一个位置
            }

            @Override
            public void onPageScrollStateChanged(int paramInt) {
                // 这里是滑动的状态
            }
        });
    }

    /**
     * 改变位置
     * 
     * @param position
     */
    protected void postionChange(int position) {
        mNumberTv.setText(position + 1 + "/" + mPaths.size());
    }

        @Override
    public void onClick(View v) {
        String tag = (String) v.getTag();
        switch (tag) {
        case "back":
            this.dismiss();
            break;
        case "delete":
            // 删除
            break;
        }
    }

相信这些代码也难不倒大家。

稍微解释一下是,如果没有设置值就返回-1。这样可以用来方便构造我们的FullScreenFragmentLayout

还有的就是tag的用法,之前的文章也讲过,这里也不再说了~

然后我们要对外暴露两个方法,以便我们改变ViewPager显示的位置以及,所展示的图片列表:

    public void setList(List<String> list) {
        mPaths = list;
    }

    public void setCurrentPosition(int position) {
        mCurrentPostion = position;
    }

OK那再加上一些必要的东西,基本的FullScreenFragment就出来了。

public class FullScreenFragment extends DialogFragment implements
        OnClickListener {
    private static final String KEY_BAR_COLOR_ID = "bar_color";
    private static final String KEY_BAR_HEIGHT = "bar_height";
    private static final String KEY_BACK_ICON_ID = "back_icon";
    private static final String KEY_DELETE_ICON_ID = "delete_icon";
    private static final String KEY_ICON_MARGIN = "icon_margin";
    private static final String KEY_ICON_SIZE = "icon_size";
    private static final String KEY_TEXT_COLOR = "text_color";
    private static final String KEY_TEXT_SIZE = "text_size";
    private static final String KEY_TEXT_MARGIN = "text_margin";
    private FullScreenFragmentLayout mRootView;

    private ImageView mBack, mDelete;
    private ViewPager mViewPager;
    /**
     * 数字的TextView
     */
    private TextView mNumberTv;
    /**
     * ImageView集合
     */
    private ImageView[] mImageViews;
    /**
     * 路径集合
     */
    private List<String> mPaths;
    /**
     * 当前位置
     */
    private int mCurrentPostion = -1;

    private PagerAdapter mPagerAdapter;

    public static FullScreenFragment newInstance(int barColorId,
            int backIconId, int deleteIconId) {
        FullScreenFragment f = new FullScreenFragment();
        Bundle b = new Bundle();
        b.putInt(KEY_BACK_ICON_ID, backIconId);
        b.putInt(KEY_DELETE_ICON_ID, deleteIconId);
        b.putInt(KEY_BAR_COLOR_ID, barColorId);
        f.setArguments(b);
        return f;
    }

    public static FullScreenFragment newInstance(int barColorId, int barHeight,
            int backIconId, int deleteIconId, int iconWidth,
            int iconMarginSide, int textColor, int textSize,
            int textMarginLeftSize) {
        FullScreenFragment f = new FullScreenFragment();
        Bundle b = new Bundle();
        b.putInt(KEY_BAR_COLOR_ID, barColorId);
        b.putInt(KEY_BAR_HEIGHT, barHeight);
        b.putInt(KEY_BACK_ICON_ID, backIconId);
        b.putInt(KEY_DELETE_ICON_ID, deleteIconId);
        b.putInt(KEY_ICON_SIZE, iconWidth);
        b.putInt(KEY_ICON_MARGIN, iconMarginSide);
        b.putInt(KEY_TEXT_COLOR, textColor);
        b.putInt(KEY_TEXT_SIZE, textSize);
        b.putInt(KEY_TEXT_MARGIN, textMarginLeftSize);
        f.setArguments(b);
        return f;
    }

    private FullScreenFragment() {

    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 设置全屏
        setStyle(DialogFragment.STYLE_NO_TITLE,
                android.R.style.Theme_Black_NoTitleBar);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // if (mRootView == null) {
        // 创建布局
        mRootView = initLayout();
        // }
        // mViewPager = (ViewPager) view.findViewById(R.id.vp);
        // 获取空间
        mViewPager = mRootView.getViewPager();
        mNumberTv = mRootView.getNumberTextView();
        mBack = mRootView.getBackImageView();
        mDelete = mRootView.getDeleteImageView();
        // mPaths = new ArrayList<String>();

        // 初始化ViewPager
        initViewPager();
        // 改变文字标题
        postionChange(mCurrentPostion);
        // 要在设置完Adapter之后调用 不然没效果
        mViewPager.setCurrentItem(mCurrentPostion);
        // 初始化监听
        initBarListener();
        return mRootView;
    }

    private void initBarListener() {
        mBack.setTag("back");
        mDelete.setTag("delete");
        mBack.setOnClickListener(this);
        mDelete.setOnClickListener(this);
    }

    private FullScreenFragmentLayout initLayout() {
        Bundle b = getArguments();
        int barHeight = b.getInt(KEY_BAR_HEIGHT, -1);
        int barColorId = b.getInt(KEY_BAR_COLOR_ID, -1);
        int backIconId = b.getInt(KEY_BACK_ICON_ID, -1);
        int deleteIconId = b.getInt(KEY_DELETE_ICON_ID, -1);
        int iconSize = b.getInt(KEY_ICON_SIZE, -1);
        int iconMargin = b.getInt(KEY_ICON_MARGIN, -1);
        int textColorId = b.getInt(KEY_TEXT_COLOR, -1);
        int textSize = b.getInt(KEY_TEXT_SIZE, -1);
        int textMargin = b.getInt(KEY_TEXT_MARGIN, -1);
        FullScreenFragmentLayout.Builder builder = new FullScreenFragmentLayout.Builder(
                getActivity());
        if (barHeight != -1) {
            builder.setBarHeight(barHeight);
        }
        if (barColorId != -1) {
            builder.setBarColorId(barColorId);
        }
        if (backIconId != -1) {
            builder.setBackIconDrawableId(backIconId);
        }
        if (deleteIconId != -1) {
            builder.setDeleteIconDrawableId(deleteIconId);
        }
        if (iconSize != -1) {
            builder.setIconSize(iconSize);
        }
        if (iconMargin != -1) {
            builder.setIconMarginSize(iconMargin);
        }
        if (textColorId != -1) {
            builder.setTextColorId(textColorId);
        }
        if (textSize != -1) {
            builder.setTextSize(textSize);
        }
        if (textMargin != -1) {
            builder.setTextMarginLeftSize(textMargin);
        }
        return builder.build();
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
    }

    private void initViewPager() {
        // 如果为空或者为0则返回
        if (mPaths == null || mPaths.size() == 0)
            return;
        System.out.println("initViewPager Context = " + getActivity());
        mImageViews = new ImageView[mPaths.size()];
        for (int i = 0; i < mPaths.size(); i++) {
            mImageViews[i] = new ImageView(getActivity());
        }
        mViewPager.setOffscreenPageLimit(2);
        mPagerAdapter = new PagerAdapter() {
            @Override
            public boolean isViewFromObject(View paramView, Object paramObject) {
                // 判断当前是否一致,一致则绘制View出来
                return paramView == paramObject;
            }

            @Override
            public int getCount() {
                return mPaths.size();
            }

            @Override
            public void destroyItem(ViewGroup container, int position,
                    Object object) {
                System.out.println("destroyItem: viewPager = "
                        + mViewPager.toString() + " container = " + container
                        + " obj = " + object);
                // ((ViewPager) container).removeView(mImageViews[position]);
                View v = (View) object;
                // String vTag = (String) v.getTag();
                // if (mMovedPath != null && vTag.equals(mMovedPath)) {
                ((ViewPager) container).removeView(v);
                v = null;
                // }
            }

            @Override
            public Object instantiateItem(ViewGroup container, int position) {
                System.out.println("destroyItem: viewPager = "
                        + mViewPager.toString() + " container = " + container);
                ImageView i = mImageViews[position];
                String path = mPaths.get(position);
                i.setTag(path);
                ImageLoaderWrapper.loadFromFile(i, path);
                ((ViewPager) container).addView(i);
                System.out.println("instantiateItem");
                return i;
            }

            @Override
            public int getItemPosition(Object object) {
                System.out.println("getItemPosition: object =" + object);
                return POSITION_NONE;
            }

            @Override
            public void notifyDataSetChanged() {
                System.out.println("notifyDataSetChanged");
                super.notifyDataSetChanged();
            }

            @Override
            public void startUpdate(ViewGroup container) {

            }

            @Override
            public void finishUpdate(ViewGroup container) {

            }
        };

        mViewPager.setAdapter(mPagerAdapter);

        mViewPager.addOnPageChangeListener(new OnPageChangeListener() {

            @Override
            public void onPageSelected(int paramInt) {
                // 当前位置
                mCurrentPostion = paramInt;
                postionChange(mCurrentPostion);
            }

            @Override
            public void onPageScrolled(int paramInt1, float paramFloat,
                    int paramInt2) {
                // 上一个位置 偏移量 下一个位置
            }

            @Override
            public void onPageScrollStateChanged(int paramInt) {
                // 这里是滑动的状态
            }
        });
    }

    /**
     * 改变位置
     * 
     * @param position
     */
    protected void postionChange(int position) {
        mNumberTv.setText(position + 1 + "/" + mPaths.size());
    }

    public void setList(List<String> list) {
        mPaths = list;
    }

    public void setCurrentPosition(int position) {
        mCurrentPostion = position;
    }

    @Override
    public void onClick(View v) {
        String tag = (String) v.getTag();
        switch (tag) {
        case "back":
            this.dismiss();
            break;
        case "delete":

            break;
        }
    }
}

OK我们继续完善一下逻辑,我们还有删除这个逻辑没有实现,具体的逻辑如下:

    @Override
    public void onClick(View v) {
        ....
        case "delete":
            mPaths.remove(mCurrentPostion);
            mPagerAdapter.notifyDataSetChanged();
            mCurrentPostion = mViewPager.getCurrentItem();
            postionChange(mCurrentPostion);
            break;
        }
        ...
    }

至此是不是以为已经完成了? 没有哦! 因为我们还要通知外面的那个展示列表更新哦!
所以我们需要在这个DialogFragment dismiss的时候判断一下是否需要对外部进行更新!

我们依旧采用接口回调的思想:

    @Override
    public void onClick(View v) {
        ....
        case "delete":
            if (!mNeedToUpdate) {
                mNeedToUpdate = true;
            }
            mPaths.remove(mCurrentPostion);
            if (mPaths.size() == 0) {
                dismiss();
                return;
            }
            mPagerAdapter.notifyDataSetChanged();
            mCurrentPostion = mViewPager.getCurrentItem();
            postionChange(mCurrentPostion);
            break;
        }
        ...
    }

    @Override
    public void dismiss() {
        super.dismiss();
        if (mNeedToUpdate) {
            mCallback.update(mPaths);
        }
    }

    public void setUpdateCallback(UpdateCallback callback) {
        mCallback = callback;
    }

    public interface UpdateCallback {
        void update(List<String> mPaths);
    }

在DialogFragment消失的时候,通知他去更新!

最后我们还要监听一下用户的back实体键:

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        this.getDialog().setOnKeyListener(new OnKeyListener() {
            public boolean onKey(DialogInterface dialog, int keyCode,
                    KeyEvent event) {
                if (keyCode == KeyEvent.KEYCODE_BACK) {
                    dismiss();
                    return true;
                } else {
                    return false;
                }
            }
        });
    }

当用户按下back键的时候,我们也让它dissmiss()

OK!至此FullScreenFragment就这样完成啦!!

那么我们现在看看Controller的代码!

4.完整的ChosenPhotoViewController

那么Controller中的click代码就可以变成:

    ....
    @Override
    public void click(int position) {
        if (position == mPaths.size()) {
            // 跳转逻辑
            ....
        } else {
            if (mFullFragment == null) {
                throw new IllegalArgumentException(
                        "FullScreenFragment is null. you should invoke setDetailsFragment first");
            }
            if (mManager == null) {
                throw new IllegalArgumentException(
                        "FragmentManager is null. you should invoke setDetailsFragment first");
            }
            mFullFragment.setList(mPaths);
            mFullFragment.setCurrentPosition(position);
            mFullFragment.show(mManager, "FullFragment");
        }
    }
    ....

这里需要注意一下 DialogFragment的show是异步的!异步的!异步的!

当我们调用show的时候,不是立即显示出来的。
Android DialogFragment getActivity() is null -StackOverFlow

所以,在DialogFragment中,我们对外暴露的方法里面,一定不能涉及上下文的操作,也不能涉及View相关的代码!

这个坑我在开发的时候花了好长的时候,一开始我是在

mFullFragment.setList(mPaths);

才开始创建PagerAdapter,然后当我调用

mViewPager.setAdapter(mAdapter)

死活报的都是空指针异常

所以要好好注意这里!

到这里还没有完哦,我们还要在Controller中加一个对外暴露的方法,传如FullScreenFragment实例,以及FragmentManager

public void setDetailsFragment(@NonNull FragmentManager manager,
    @NonNull FullScreenFragment fragment) {
        mFullFragment = fragment;
        mManager = manager;
        //设置回调监听!
        mFullFragment.setUpdateCallback(new UpdateCallback() {

            @Override
            public void update(List<String> paths) {
                mAdapter.update(paths);
            }
        });
}

OK!那现在完整的ChosenPhotoController的完整代码也呼之欲出啦!

public class ChosenPhotoViewController extends BaseController {
    /**
     * 一行图片的数量
     */
    private int mNumColumuns;
    /**
     * +号图片的资源Id
     */
    private int mAddIconId;
    /**
     * 图片路径
     */
    private List<String> mPaths;
    /**
     * +号图片,接口回调
     */
    private AddIconAction mAction;
    private IPhotoGridView mView;
    private ChosenPhotoAdapter mAdapter;

    private FragmentManager mManager;
    private FullScreenFragment mFullFragment;

    public ChosenPhotoViewController(int numColumns, int addIconId) {
        mAddIconId = addIconId;
        mNumColumuns = numColumns;
        mPaths = new ArrayList<String>();
    }

    /**
     * 设置监听,主要是Controller和View联动使用 不需要手动调用
     * 
     * @param listener
     */
    @Override
    public void setPhotoViewListener(IPhotoGridView view) {
        mView = view;
        mAdapter = new ChosenPhotoAdapter(mView.getGridView().getContext(),
                mPaths, mNumColumuns, mAddIconId);
        mView.bindAdapter(mAdapter);
    }

    @Override
    public List<String> getPaths() {
        return mPaths;
    }

    @Override
    public void setAdapter(List<String> paths) {
        if (mView == null)
            throw new IllegalArgumentException(
                    "mListener is null. you should invoke ChosenPhotoGridView's bindController() first");
        mPaths = paths;
        mAdapter.update(mPaths);
    }

    @Override
    public void click(int position) {
        if (position == mPaths.size()) {
            if (mAction == null) {
                throw new IllegalArgumentException(
                        "AddIconAction is null. you should invoke setAddIconAction first");
            }
            mAction.onAddClick();
        } else {
            if (mFullFragment == null) {
                throw new IllegalArgumentException(
                        "FullScreenFragment is null. you should invoke setDetailsFragment first");
            }
            if (mManager == null) {
                throw new IllegalArgumentException(
                        "FragmentManager is null. you should invoke setDetailsFragment first");
            }
            mFullFragment.setList(mPaths);
            mFullFragment.setCurrentPosition(position);
            mFullFragment.show(mManager, "FullFragment");
        }
    }

    public void setDetailsFragment(@NonNull FragmentManager manager,
            @NonNull FullScreenFragment fragment) {
        mFullFragment = fragment;
        mManager = manager;
        mFullFragment.setUpdateCallback(new UpdateCallback() {

            @Override
            public void update(List<String> paths) {
                mAdapter.update(paths);
            }
        });
    }

    public void setAddIconAction(AddIconAction action) {
        mAction = action;
    }

    public interface AddIconAction {
        void onAddClick();
    }
}

到时候我们使用起来就是这样:

mGv = (GalleryGridView) findViewById(R.id.gv);

mController = new ChosenPhotoViewController(4, R.drawable.add);

FullScreenFragment f =FullScreenFragment.newInstance
(R.color.bar,R.drawable.btn_return, R.drawable.btn_delete);
        mController.setDetailsFragment(getSupportFragmentManager(), f);

mController.setAddIconAction(new AddIconAction() {
    @Override
    public void onAddClick() {
        Intent i = new Intent(ShowActivity.this, MainActivity.class);
        startActivityForResult(i, 1);
    }
});

mGv.bindController(mController);

嗯,代码还算优雅,也还算比较少!

5.结束语

OK! 现在这个Jar要已经达到了我们日常项目开发所需要的样子了!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值