Java tutorial
/** * This file is part of FileSpace for Android, an app for managing your server (files, talks...). * <p/> * Copyright (c) 2014-2015 FileSpace for Android contributors (http://mercandalli.com) * <p/> * LICENSE: * <p/> * FileSpace for Android is free software: you can redistribute it and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any * later version. * <p/> * FileSpace for Android is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * @author Jonathan Mercandalli * @license http://www.gnu.org/licenses/gpl.html * @copyright 2014-2015 FileSpace for Android contributors (http://mercandalli.com) */ package com.mercandalli.android.apps.files.file; import android.content.Context; import android.graphics.Color; import android.support.annotation.ColorInt; import android.support.annotation.Nullable; import android.support.v4.content.ContextCompat; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import com.mercandalli.android.apps.files.R; import com.mercandalli.android.apps.files.file.filespace.FileSpaceModel; import com.mercandalli.android.library.base.java.StringUtils; import com.mercandalli.android.library.base.precondition.Preconditions; import java.util.ArrayList; import java.util.List; /** * The {@link FileModel} card {@link android.support.v7.widget.RecyclerView.Adapter}. */ public class FileModelCardAdapter extends RecyclerView.Adapter<FileModelCardAdapter.ViewHolder> { /** * The view type of the header. */ public static final int TYPE_HEADER_AUDIO = 0; /** * The view type of the header. */ public static final int TYPE_HEADER_IMAGE = 1; /** * The view type of the card. */ private static final int TYPE_CARD_ITEM = 2; /** * The application {@link Context}. */ private final Context mContextApp; private final List<FileModel> mFiles; private final OnFileClickListener mOnFileClickListener; private final OnFileLongClickListener mOnFileLongClickListener; private FileModelListener mMoreListener; private OnFileSubtitleAdapter mOnFileSubtitleAdapter; private final String mStringDirectory; private final String mStringFile; private final String mStringFiles; /* Header */ private List<FileModelCardHeaderItem> mHeaderIds; private OnHeaderClickListener mOnHeaderClickListener; private int mHeaderType = TYPE_HEADER_AUDIO; /** * Adapter without header. */ public FileModelCardAdapter(final Context context, final List<FileModel> files, final FileModelListener moreListener, final OnFileClickListener onFileClickListener, final OnFileLongClickListener onFileLongClickListener) { mContextApp = context.getApplicationContext(); mFiles = new ArrayList<>(); mFiles.addAll(files); mMoreListener = moreListener; mOnFileClickListener = onFileClickListener; mOnFileLongClickListener = onFileLongClickListener; mStringDirectory = context.getString(R.string.file_model_adapter_directory); mStringFile = context.getString(R.string.file_model_adapter_file); mStringFiles = context.getString(R.string.file_model_adapter_files); setHasStableIds(true); } /** * Adapter with header. */ public FileModelCardAdapter(final Context context, final List<FileModelCardHeaderItem> headerIds, final OnHeaderClickListener onHeaderClickListener, final List<FileModel> files, final FileModelListener moreListener, final OnFileClickListener onFileClickListener, final OnFileLongClickListener onFileLongClickListener) { this(context, files, moreListener, onFileClickListener, onFileLongClickListener); mHeaderIds = new ArrayList<>(); mHeaderIds.addAll(headerIds); mOnHeaderClickListener = onHeaderClickListener; } @Override public FileModelCardAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == TYPE_HEADER_AUDIO) { return new HeaderViewHolder(LayoutInflater.from(parent.getContext()) .inflate(R.layout.view_file_header_audio, parent, false), mHeaderIds, mOnHeaderClickListener); } else if (viewType == TYPE_HEADER_IMAGE) { return new HeaderViewHolder(LayoutInflater.from(parent.getContext()) .inflate(R.layout.view_file_header_image, parent, false), mHeaderIds, mOnHeaderClickListener); } else if (viewType == TYPE_CARD_ITEM) { return new CardViewHolder( LayoutInflater.from(parent.getContext()).inflate(R.layout.card_file, parent, false), hasHeader(), mOnFileClickListener, mOnFileLongClickListener); } throw new RuntimeException( "There is no type that matches the type " + viewType + " + make sure your using types correctly."); } @Override public void onBindViewHolder(final ViewHolder viewHolder, final int position) { if (viewHolder instanceof HeaderViewHolder) { final HeaderViewHolder headerViewHolder = (HeaderViewHolder) viewHolder; headerViewHolder.setFileModelCardHeaderItems(mHeaderIds); return; } final FileModel fileModel = getFileModel(position); if (fileModel == null || !(viewHolder instanceof CardViewHolder)) { return; } final CardViewHolder cardViewHolder = (CardViewHolder) viewHolder; cardViewHolder.mTitle.setText(getAdapterTitle(fileModel)); cardViewHolder.subtitle.setText(getAdapterSubtitle(fileModel)); final FileTypeModel type = fileModel.getType(); if (fileModel.isDirectory()) { cardViewHolder.icon.setImageResource(R.drawable.directory); } else if (FileTypeModelENUM.AUDIO.type.equals(type)) { cardViewHolder.icon.setImageResource(R.drawable.file_audio); } else if (FileTypeModelENUM.PDF.type.equals(type)) { cardViewHolder.icon.setImageResource(R.drawable.file_pdf); } else if (FileTypeModelENUM.APK.type.equals(type)) { cardViewHolder.icon.setImageResource(R.drawable.file_apk); } else if (FileTypeModelENUM.ARCHIVE.type.equals(type)) { cardViewHolder.icon.setImageResource(R.drawable.file_archive); } else if (FileTypeModelENUM.FILESPACE.type.equals(type)) { cardViewHolder.icon.setImageResource(R.drawable.file_space); } else { cardViewHolder.icon.setImageResource(R.drawable.file_default); } if (mMoreListener == null) { cardViewHolder.more.setVisibility(View.GONE); } cardViewHolder.more.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mMoreListener != null) { mMoreListener.executeFileModel(fileModel, v); } } }); } @Override public long getItemId(int position) { return position; } @Override public int getItemViewType(int position) { return isHeader(position) ? mHeaderType : TYPE_CARD_ITEM; } @Override public int getItemCount() { return mFiles.size() + (hasHeader() ? 1 : 0); } public void setList(final List<FileModel> list) { Preconditions.checkNotNull(list); mFiles.clear(); mFiles.addAll(list); notifyDataSetChanged(); } public void setOnFileSubtitleAdapter(final OnFileSubtitleAdapter onFileSubtitleAdapter) { mOnFileSubtitleAdapter = onFileSubtitleAdapter; } public void setHeaderType(int headerType) { mHeaderType = headerType; } public boolean isHeader(final int position) { return hasHeader() && position == 0; } public boolean hasHeader() { return mOnHeaderClickListener != null; } private String getAdapterTitle(FileModel fileModel) { String adapterTitleStart = ""; if (fileModel.getType() == null) { if (fileModel.getName() != null) { return adapterTitleStart + fileModel.getFullName(); } else { return adapterTitleStart + fileModel.getUrl(); } } else if (FileTypeModelENUM.FILESPACE.type.equals(fileModel.getType()) && fileModel.getContent() != null) { return adapterTitleStart + fileModel.getContent().getAdapterTitle(); } else if (fileModel.getName() != null) { return adapterTitleStart + fileModel.getFullName(); } else { return adapterTitleStart + fileModel.getUrl(); } } private String getAdapterSubtitle(final FileModel fileModel) { String result; if (mOnFileSubtitleAdapter != null && (result = mOnFileSubtitleAdapter.onFileSubtitleModify(fileModel)) != null) { return result; } if (fileModel.isDirectory() && fileModel.getCount() != 0) { return mStringDirectory + ": " + StringUtils.longToShortString(fileModel.getCount()) + " " + (fileModel.getCount() > 1 ? mStringFiles : mStringFile); } if (fileModel.isDirectory()) { return mStringDirectory; } final FileSpaceModel content; if (FileTypeModelENUM.FILESPACE.type.equals(fileModel.getType()) && (content = fileModel.getContent()) != null) { return fileModel.getType().getTitle(mContextApp) + " " + StringUtils.capitalize(content.getType().toString()); } if (fileModel.getType() != null) { return fileModel.getType().getTitle(mContextApp); } return ""; } @Nullable private FileModel getFileModel(final int adapterPosition) { if (isHeader(adapterPosition)) { return null; } final int filesPosition = adapterPosition - (hasHeader() ? 1 : 0); if (filesPosition >= mFiles.size()) { return null; } return mFiles.get(filesPosition); } public interface OnFileClickListener { void onFileCardClick(View v, int position); } public interface OnFileLongClickListener { boolean onFileCardLongClick(View v, int position); } public interface OnHeaderClickListener { /** * The header is clicked. */ boolean onHeaderClick(View v, List<FileModelCardHeaderItem> fileModelCardHeaderItems); } public interface OnFileSubtitleAdapter { @Nullable String onFileSubtitleModify(final FileModel fileModel); } public static class ViewHolder extends RecyclerView.ViewHolder { public ViewHolder(View itemView) { super(itemView); } } private static class HeaderViewHolder extends ViewHolder implements OnClickListener { @ColorInt private final int mPrimaryColor; private final OnHeaderClickListener mOnHeaderClickListener; private final List<FileModelCardHeaderItem> mFileModelCardHeaderItems; public HeaderViewHolder(final View itemView, final List<FileModelCardHeaderItem> headerIds, final OnHeaderClickListener onHeaderClickListener) { super(itemView); Preconditions.checkNotNull(onHeaderClickListener); mPrimaryColor = ContextCompat.getColor(itemView.getContext(), R.color.primary); mOnHeaderClickListener = onHeaderClickListener; mFileModelCardHeaderItems = new ArrayList<>(); mFileModelCardHeaderItems.addAll(headerIds); updateView(); } @Override public void onClick(View v) { final int viewId = v.getId(); boolean isElementAlreadySelected = false; for (FileModelCardHeaderItem f : mFileModelCardHeaderItems) { if (f.getId() == viewId && f.isSelected()) { isElementAlreadySelected = true; break; } } if (isElementAlreadySelected) { return; } for (FileModelCardHeaderItem f : mFileModelCardHeaderItems) { f.setSelected(f.getId() == viewId); } mOnHeaderClickListener.onHeaderClick(v, mFileModelCardHeaderItems); updateView(); } public void setFileModelCardHeaderItems(List<FileModelCardHeaderItem> fileModelCardHeaderItems) { mFileModelCardHeaderItems.clear(); mFileModelCardHeaderItems.addAll(fileModelCardHeaderItems); updateView(); } private void updateView() { for (FileModelCardHeaderItem f : mFileModelCardHeaderItems) { final TextView tv = (TextView) itemView.findViewById(f.getId()); tv.setOnClickListener(this); if (f.isSelected()) { tv.setTextColor(mPrimaryColor); tv.setBackgroundResource(R.drawable.file_local_audio_rounded_bg_selected); } else { tv.setTextColor(Color.WHITE); tv.setBackgroundResource(R.drawable.file_local_audio_rounded_bg); } } } } private static class CardViewHolder extends ViewHolder implements OnClickListener, View.OnLongClickListener { public final TextView mTitle; public final TextView subtitle; public final ImageView icon; public final View mItem; public final View more; private final OnFileClickListener mOnFileClickListener; private final OnFileLongClickListener mOnFileLongClickListener; private final boolean mHasHeader; public CardViewHolder(final View itemLayoutView, final boolean hasHeader, final OnFileClickListener onFileClickListener, final OnFileLongClickListener onFileLongClickListener) { super(itemLayoutView); mHasHeader = hasHeader; mItem = itemLayoutView.findViewById(R.id.card_file_item); mTitle = (TextView) itemLayoutView.findViewById(R.id.card_file_title); subtitle = (TextView) itemLayoutView.findViewById(R.id.card_file_subtitle); icon = (ImageView) itemLayoutView.findViewById(R.id.card_file_icon); more = itemLayoutView.findViewById(R.id.card_file_more); mOnFileClickListener = onFileClickListener; mOnFileLongClickListener = onFileLongClickListener; mItem.setOnClickListener(this); mItem.setOnLongClickListener(this); } @Override public void onClick(View v) { if (mOnFileClickListener != null) { mOnFileClickListener.onFileCardClick(icon, getAdapterPosition() - (mHasHeader ? 1 : 0)); } } @Override public boolean onLongClick(View v) { return mOnFileLongClickListener != null && mOnFileLongClickListener.onFileCardLongClick(v, getAdapterPosition() - (mHasHeader ? 1 : 0)); } } }