Merge branch 'develop'

This commit is contained in:
houxg
2017-02-14 19:33:35 +08:00
7 changed files with 249 additions and 67 deletions

View File

@@ -12,16 +12,23 @@ import android.text.style.BackgroundColorSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import org.houxg.leamonax.R;
import org.houxg.leamonax.database.AppDataBase;
import org.houxg.leamonax.model.Note;
import org.houxg.leamonax.model.NoteFile;
import org.houxg.leamonax.model.Notebook;
import org.houxg.leamonax.service.AccountService;
import org.houxg.leamonax.service.NoteFileService;
import org.houxg.leamonax.utils.FileUtils;
import org.houxg.leamonax.utils.TimeUtils;
import org.houxg.leamonax.widget.NoteList;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -34,6 +41,7 @@ import butterknife.ButterKnife;
public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.NoteHolder> {
public static final int TYPE_DETAIL_PLACEHOLDER = 233;
private List<Note> mData;
private Map<String, String> mNotebookId2TitleMaps;
@@ -41,6 +49,7 @@ public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.NoteHolder> {
private Pattern mTitleHighlight;
private int mCurrentType = NoteList.TYPE_SIMPLE;
private List<Long> mSelectedNotes = new ArrayList<>();
private boolean isScrolling = false;
public NoteAdapter(NoteAdapterListener listener) {
mListener = listener;
@@ -60,6 +69,10 @@ public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.NoteHolder> {
}
}
public void setScrolling(boolean scrolling) {
isScrolling = scrolling;
}
public void setType(int type) {
mCurrentType = type;
}
@@ -81,12 +94,15 @@ public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.NoteHolder> {
@Override
public NoteAdapter.NoteHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = null;
int layoutId = -1;
if (viewType == NoteList.TYPE_SIMPLE) {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_note_simple, parent, false);
layoutId = R.layout.item_note_simple;
} else if (viewType == NoteList.TYPE_DETAIL) {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_note, parent, false);
layoutId = R.layout.item_note;
} else if (viewType == TYPE_DETAIL_PLACEHOLDER) {
layoutId = R.layout.item_note_detail_placeholder;
}
View view = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
return new NoteHolder(view);
}
@@ -100,50 +116,29 @@ public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.NoteHolder> {
@Override
public int getItemViewType(int position) {
return mCurrentType;
if (isScrolling && mCurrentType == NoteList.TYPE_DETAIL) {
return TYPE_DETAIL_PLACEHOLDER;
} else {
return mCurrentType;
}
}
@Override
public void onBindViewHolder(NoteAdapter.NoteHolder holder, int position) {
final Note note = mData.get(position);
if (getItemViewType(position) == NoteList.TYPE_DETAIL) {
renderDetail(holder, note);
} else {
renderSimple(holder, note);
int type = getItemViewType(position);
switch (type) {
case NoteList.TYPE_DETAIL:
case TYPE_DETAIL_PLACEHOLDER:
renderDetailMeta(holder, note);
if (type == NoteList.TYPE_DETAIL) {
renderDetailContent(holder, note);
}
break;
case NoteList.TYPE_SIMPLE:
renderSimple(holder, note);
break;
}
holder.container.setSelected(mSelectedNotes.contains(note.getId()));
}
private void renderDetail(NoteHolder holder, final Note note) {
if (TextUtils.isEmpty(note.getTitle())) {
holder.titleTv.setText(R.string.untitled);
} else {
holder.titleTv.setText(getHighlightedText(note.getTitle()));
}
if (note.isMarkDown()) {
holder.contentTv.setText(note.getContent());
} else {
Spanned spannedContent = Html.fromHtml(note.getContent());
String contentStr = spannedContent.toString();
contentStr = contentStr.replaceAll("\\n\\n+", "\n");
holder.contentTv.setText(contentStr);
}
holder.notebookTv.setText(mNotebookId2TitleMaps.get(note.getNoteBookId()));
long updateTime = note.getUpdatedTimeVal();
Context context = holder.updateTimeTv.getContext();
String time;
if (updateTime >= TimeUtils.getToday().getTimeInMillis()) {
time = TimeUtils.toTimeFormat(updateTime);
} else if (updateTime >= TimeUtils.getYesterday().getTimeInMillis()) {
time = context.getString(R.string.time_yesterday, TimeUtils.toTimeFormat(updateTime));
} else if (updateTime >= TimeUtils.getThisYear().getTimeInMillis()) {
time = TimeUtils.toDateFormat(updateTime);
} else {
time = TimeUtils.toYearFormat(updateTime);
}
holder.updateTimeTv.setText(time);
holder.dirtyTv.setVisibility(note.isDirty() ? View.VISIBLE : View.GONE);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -161,6 +156,59 @@ public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.NoteHolder> {
return true;
}
});
holder.container.setSelected(mSelectedNotes.contains(note.getId()));
}
private void renderDetailMeta(NoteHolder holder, final Note note) {
if (holder.imageView != null) {
holder.imageView.setImageDrawable(null);
}
if (TextUtils.isEmpty(note.getTitle())) {
holder.titleTv.setText(R.string.untitled);
} else {
holder.titleTv.setText(getHighlightedText(note.getTitle()));
}
holder.notebookTv.setText(mNotebookId2TitleMaps.get(note.getNoteBookId()));
long updateTime = note.getUpdatedTimeVal();
String time;
if (updateTime >= TimeUtils.getToday().getTimeInMillis()) {
time = TimeUtils.toTimeFormat(updateTime);
} else if (updateTime >= TimeUtils.getYesterday().getTimeInMillis()) {
time = holder.updateTimeTv.getContext().getString(R.string.time_yesterday, TimeUtils.toTimeFormat(updateTime));
} else if (updateTime >= TimeUtils.getThisYear().getTimeInMillis()) {
time = TimeUtils.toDateFormat(updateTime);
} else {
time = TimeUtils.toYearFormat(updateTime);
}
holder.updateTimeTv.setText(time);
holder.dirtyTv.setVisibility(note.isDirty() ? View.VISIBLE : View.GONE);
}
private void renderDetailContent(NoteHolder holder, final Note note) {
List<NoteFile> noteFiles = NoteFileService.getRelatedNoteFiles(note.getId());
holder.imageView.setImageDrawable(null);
for (NoteFile noteFile : noteFiles) {
if (TextUtils.isEmpty(noteFile.getLocalPath())) {
continue;
}
File file = new File(noteFile.getLocalPath());
if (FileUtils.isImageFile(file)) {
Glide.with(holder.container.getContext())
.load(file)
.fitCenter()
.into(holder.imageView);
break;
}
}
if (note.isMarkDown()) {
holder.contentTv.setText(note.getContent());
} else {
Spanned spannedContent = Html.fromHtml(note.getContent());
String contentStr = spannedContent.toString();
contentStr = contentStr.replaceAll("\\n\\n+", "\n");
holder.contentTv.setText(contentStr);
}
}
private void renderSimple(final NoteHolder holder, final Note note) {
@@ -185,23 +233,6 @@ public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.NoteHolder> {
}
holder.updateTimeTv.setText(time);
holder.dirtyTv.setVisibility(note.isDirty() ? View.VISIBLE : View.GONE);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mListener != null) {
mListener.onClickNote(note);
}
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (mListener != null) {
mListener.onLongClickNote(note);
}
return true;
}
});
}
private CharSequence getHighlightedText(String text) {
@@ -247,6 +278,9 @@ public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.NoteHolder> {
TextView dirtyTv;
@BindView(R.id.container)
View container;
@Nullable
@BindView(R.id.iv_image)
ImageView imageView;
public NoteHolder(View itemView) {
super(itemView);

View File

@@ -16,6 +16,7 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.List;
import java.util.Locale;
import okio.BufferedSource;
@@ -72,6 +73,10 @@ public class NoteFileService {
}
}
public static List<NoteFile> getRelatedNoteFiles(long noteLocalId) {
return AppDataBase.getAllRelatedFile(noteLocalId);
}
public static InputStream getImage(String localId) {
NoteFile noteFile = AppDataBase.getNoteFileByLocalId(localId);
if (noteFile == null) {

View File

@@ -0,0 +1,10 @@
package org.houxg.leamonax.utils;
import java.io.File;
public class FileUtils {
public static boolean isImageFile(File file) {
return file != null && file.isFile() && file.getName().matches("([^\\s]+(\\.(?i)(jpg|png|gif|bmp))$)");
}
}

View File

@@ -39,6 +39,10 @@ public class NoteList {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
mAdapter.setScrolling(newState != RecyclerView.SCROLL_STATE_IDLE);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
mAdapter.notifyDataSetChanged();
}
}
@Override

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="6dp" />
<solid android:color="#E0E0E0" />
</shape>

View File

@@ -28,20 +28,35 @@
android:fontFamily="sans-serif-medium"
android:textColor="@color/primary_text_light"
android:textSize="20sp"
android:layout_marginBottom="4dp"
tools:text="Leanote API" />
<TextView
android:id="@+id/tv_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:fontFamily="sans-serif"
android:maxHeight="120dp"
android:maxLines="4"
android:textColor="#9E9E9E"
android:textSize="14sp"
tools:text="Enim consequat enim pariatur id anim Ut Excepteur dolor in laborum incididunt veniam quis proident. in consequat aliquip in minim adipisicing exercitation sunt sed qui pariatur consequat commodo ea do." />
android:orientation="horizontal">
<TextView
android:id="@+id/tv_content"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:fontFamily="sans-serif"
android:maxHeight="120dp"
android:maxLines="6"
android:textColor="@color/hint_text_light"
android:textSize="14sp"
tools:text="Enim consequat enim pariatur id anim Ut Excepteur dolor in laborum incididunt veniam quis proident. in consequat aliquip in minim adipisicing exercitation sunt sed qui pariatur consequat commodo ea do." />
<ImageView
android:id="@+id/iv_image"
android:layout_width="wrap_content"
android:maxWidth="100dp"
android:maxHeight="100dp"
android:adjustViewBounds="true"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?android:attr/selectableItemBackground"
android:background="@drawable/note_selector"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="8dp"
android:paddingEnd="16dp"
android:paddingStart="16dp"
android:paddingTop="16dp">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:textColor="@color/primary_text_light"
android:textSize="20sp"
android:layout_marginBottom="4dp"
tools:text="Leanote API" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_content"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:fontFamily="sans-serif"
android:maxHeight="120dp"
android:textColor="@color/transparent"
android:background="@drawable/shape_placeholder"
android:maxLines="6"
android:textSize="14sp"
android:text="Enim consequat enim pariatur id anim Ut Excepteur dolor in laborum incididunt veniam quis proident. in consequat aliquip in minim adipisicing exercitation sunt sed qui pariatur consequat commodo ea do." />
</LinearLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#BDBDBD" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingBottom="8dp"
android:paddingEnd="16dp"
android:paddingStart="16dp"
android:paddingTop="8dp">
<TextView
android:id="@+id/tv_dirty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:background="@drawable/shape_changed"
android:fontFamily="sans-serif"
android:paddingBottom="2dp"
android:paddingEnd="4dp"
android:paddingStart="4dp"
android:paddingTop="2dp"
android:text="@string/changed"
android:textColor="#fff"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_update_time"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:fontFamily="sans-serif-light"
android:textColor="@color/hint_text_light"
android:textSize="12sp"
tools:text="9-18 23:23" />
<TextView
android:id="@+id/tv_notebook"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:textColor="@color/hint_text_light"
android:textSize="12sp"
tools:text="Gradle" />
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>