神马笔记 版本1.7.0——辅助编辑·代码篇

一、目标

定义实现辅助编辑的整体代码框架。

二、体验地址

神马笔记最新版本下载:【神马笔记 版本1.7.0——辅助编辑功能.apk

三、代码结构

与辅助编辑有关的代码均位于app.haiyunshan.whatsnote.outline包之下。

1. 包结构

  • app.haiyunshan.whatsnote.outline
    • OutlineFragment
    • IndentDialogFragment
    • IndentFragment
  • app.haiyunshan.whatsnote.outline.entity
    • Outline
    • BaseOutlineEntity
    • ParagraphOutlineEntity
    • PictureOutlineEntity
  • app.haiyunshan.whatsnote.outline.viewholder
    • BaseOutlineViewHolder
    • ParagraphOutlineViewHolder
    • PictureOutlineViewHolder
  • app.haiyunshan.whatsnote.outline.helper
    • OutlineHelper
    • OutlineFactory
PackageSummary
app.haiyunshan.whatsnote.outlineFragment级别的用户交互类
app.haiyunshan.whatsnote.outline.entity交互数据类
app.haiyunshan.whatsnote.outline.viewholderRecyclerView的ViewHolder类
app.haiyunshan.whatsnote.outline.helper助手类

2. 界面类

app.haiyunshan.whatsnote.outlineSummary
OutlineFragment大纲结构界面
IndentDialogFragment段落缩进对话框
IndentFragment段落缩进界面

3. 交互数据类

app.haiyunshan.whatsnote.outline.entitySummary
Outline文章大纲数据集合类
BaseOutlineEntity段落和图片基类
ParagraphOutlineEntity段落类
PictureOutlineEntity图片类

4. ViewHolder类

app.haiyunshan.whatsnote.outline.viewholderSummary
BaseOutlineViewHolder段落和图片基类,与BaseOutlineEntity对应。
ParagraphOutlineViewHolder段落类,与ParagraphOutlineEntity对应。
PictureOutlineViewHolder图片类,与PictureOutlineEntity对应。

5. 助手类

app.haiyunshan.whatsnote.outline.helperSummary
OutlineHelper大纲结构管理助手类。
OutlineFactory大纲结构工厂类,负责Document与Outline的相互转换。

四、布局资源

1. 列表项布局

段落和图片的布局唯一的差别只是显示内容控件的不同,前者为TextView,后者为ImageView。其他所有布局都是相同的,因此定义通用的布局资源,预留ViewStub用于段落和图片加载自身的布局资源。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="@dimen/settingItemHeight"
        android:background="@color/colorWindowBackground">

    <FrameLayout
            android:id="@+id/btn_delete"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/holo_red_light"
            android:foreground="?selectableItemBackground">

        <TextView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:gravity="center"
                android:layout_gravity="left"
                android:paddingLeft="24dp"
                android:paddingRight="24dp"
                android:text="删除"
                android:textStyle="bold"
                android:textColor="@android:color/white"
                android:textAppearance="@style/TextAppearance.AppCompat.Button"/>

    </FrameLayout>

    <LinearLayout
            android:id="@+id/swipe_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:minHeight="@dimen/settingItemHeight"
            android:paddingLeft="?listPreferredItemPaddingLeft"
            android:paddingRight="?listPreferredItemPaddingRight"
            android:background="@color/colorWindowBackground"
            android:foreground="?selectableItemBackground"
            android:clipToPadding="false"
            android:orientation="horizontal"
            android:gravity="center_vertical"
            android:layout_gravity="center">

        <ImageView
                android:id="@+id/iv_checkbox"
                android:layout_width="24dp"
                android:layout_height="24dp"
                android:src="@null"
                android:background="@drawable/anc_ic_circle_color_stroke"
                android:tint="@color/colorPrimary"
                android:backgroundTint="@color/colorChevron"
                android:scaleType="fitCenter"
                android:layout_gravity="left|center_vertical"
                android:visibility="visible"
                android:duplicateParentState="false"
                android:layout_marginRight="?listPreferredItemPaddingRight"/>

        <ImageView
                android:id="@+id/iv_icon"
                android:layout_marginRight="?listPreferredItemPaddingRight"
                android:layout_width="24dp"
                android:layout_height="24dp"
                android:scaleType="fitCenter"
                android:src="@drawable/ic_paragraph_outline"
                android:tint="@color/colorOutlineIcon"
                android:visibility="gone"
                />

        <ViewStub
                android:id="@+id/stub"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:gravity="left|center_vertical"/>

        <ImageView
                android:id="@+id/btn_drag"
                android:layout_width="28dp"
                android:layout_height="28dp"
                android:src="@drawable/ic_drag_handle_white_24dp"
                android:tint="@color/colorDrag"
                android:scaleType="centerInside"
                android:visibility="visible"
                android:layout_gravity="right|center_vertical"
                android:layout_marginLeft="?listPreferredItemPaddingLeft"/>

    </LinearLayout>

</FrameLayout>

2. 段落布局

替换列表项布局中的ViewStub

<?xml version="1.0" encoding="utf-8"?>
<TextView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/tv_name"
        android:textAppearance="@style/TextAppearance.AppCompat.Menu"
        android:layout_width="0dp"
        android:gravity="left|center_vertical"
        android:layout_height="match_parent"
        android:singleLine="true"
        android:lines="1"
        android:layout_weight="1"/>

3. 图片布局

替换列表项布局中的ViewStub

设置scaleType为fitXY,伸缩图片适应控件大小。

设置background为圆角矩形,并配合outlineProvider实现裁剪,实现圆角图片效果。

设置foreground,为控件添加Stroke。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="0dp"
             android:layout_weight="1"
             android:layout_height="match_parent">

    <ImageView
            android:id="@+id/iv_picture"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="8dp"
            android:layout_marginBottom="8dp"
            android:scaleType="fitXY"
            android:background="@drawable/shape_picture_outline_bg"
            android:foreground="@drawable/shape_picture_outline_fg"
            android:outlineProvider="background"/>

</FrameLayout>

五、实现要点

1. OutlineFactory

OutlineFactory实现了DocumentOutline的相互转换。需要注意的是Outline转换为Document时。

  1. 内容不能为空
  2. 最后一个必须是段落,以保证用户可以继续编辑
  3. 第一个必须是段落,以保证用户可以编写标题

2. BaseOutlineEntity

public class BaseOutlineEntity<T extends DocumentEntity> {

    String id;

    T parent;

    BaseOutlineEntity(T parent) {
        this.parent = parent;

        this.id = UUIDUtils.next();
    }

    public String getId() {
        return this.id;
    }

    public String getParentId() {
        return parent.getId();
    }

    public T getParent() {
        return parent;
    }

    public void indent(CharSequence prefix) {
		// 由子类实现缩进
    }

    public void delete() {
		// 由子类实现删除
    }
}

3. BaseOutlineViewHolder

由于通过反射方式创建BaseOutlineViewHolder的子类们,必须保证构造函数不被混淆。因此必须使用@Keep注解标注构造函数。

public class BaseOutlineViewHolder<T extends BaseOutlineEntity> extends SwipeViewHolder<T> {

    public static final int LAYOUT_RES_ID = R.layout.layout_outline_list_item;

    ImageView checkBox;
    ImageView iconView;
    ViewStub viewStub;
    ImageView dragView;

    OutlineHelper helper;

    @Keep
    public BaseOutlineViewHolder(OutlineHelper helper, View itemView) {
        super(itemView);

        this.helper = helper;
    }

    @Override
    public int getLayoutResourceId() {
        return LAYOUT_RES_ID;
    }

    // ……
}

六、实现过程

欲知后事如何,且听下回分解。

七、Finally

~还似旧时游上苑~车如流水马如龙~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值