/*
* Copyright (C) 2014 Freddie (Musenkishi) Lust-Hed
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.musenkishi.wally.adapters;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PorterDuff;
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.LayerDrawable;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.GlideBitmapDrawable;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import com.musenkishi.paletteloader.PaletteLoader;
import com.musenkishi.paletteloader.PaletteRequest;
import com.musenkishi.wally.R;
import com.musenkishi.wally.base.WallyApplication;
import com.musenkishi.wally.models.Image;
import java.util.ArrayList;
import java.util.HashMap;
/**
* Adapter that handles images coming from backend.
*
* Created by Musenkishi on 2014-02-28.
*/
public class RecyclerImagesAdapter extends RecyclerView.Adapter<RecyclerImagesAdapter.ViewHolder> {
protected int itemSize;
public void setItemSize(int itemSize) {
this.itemSize = itemSize;
}
private OnSaveButtonClickedListener onSaveButtonClickedListener;
private OnItemClickListener onItemClickListener;
private OnGetViewListener onGetViewListener;
private ArrayList<Image> images;
private int barHeight;
private HashMap<String, Boolean> existingFiles = new HashMap<String, Boolean>();
private SparseArray<ValueAnimator> valueAnimators = new SparseArray<ValueAnimator>();
/**
* Don't use this constructor.
*/
public RecyclerImagesAdapter() {
throw new NoDataException("No data set. Did you use the correct constructor?");
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
LayoutInflater inflater = (LayoutInflater) viewGroup.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View view = inflater.inflate(R.layout.view_cell_thumb_tile, viewGroup, false);
if (barHeight == 0){
barHeight = view.getResources().getDimensionPixelSize(R.dimen.default_height);
}
view.getLayoutParams().height = itemSize + barHeight;
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
if (onGetViewListener != null) {
onGetViewListener.onBindView(position);
}
final Image image = getItem(position);
if (image != null){
viewHolder.bottomBar.setBackgroundColor(viewHolder.bottomBar.getContext().getResources().getColor(R.color.Transparent));
viewHolder.textViewResolution.setTextColor(viewHolder.bottomBar.getContext().getResources().getColor(R.color.Thumb_Text));
RequestListener<String, GlideDrawable> glideDrawableRequestListener = new RequestListener<String, GlideDrawable>() {
@Override
public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
Bitmap bitmap = ((GlideBitmapDrawable) resource).getBitmap();
if (bitmap != null) {
Context context = viewHolder.bottomBar.getContext();
PaletteLoader.with(context, model)
.load(bitmap)
.setPaletteRequest(new PaletteRequest(PaletteRequest.SwatchType.REGULAR_VIBRANT, PaletteRequest.SwatchColor.BACKGROUND))
.into(viewHolder.bottomBar);
PaletteLoader.with(context, model)
.load(bitmap)
.setPaletteRequest(new PaletteRequest(PaletteRequest.SwatchType.REGULAR_VIBRANT, PaletteRequest.SwatchColor.TEXT_TITLE))
.into(viewHolder.textViewResolution);
PaletteLoader.with(context, model)
.load(bitmap)
.fallbackColor(viewHolder.textViewResolution.getCurrentTextColor())
.setPaletteRequest(new PaletteRequest(PaletteRequest.SwatchType.REGULAR_VIBRANT, PaletteRequest.SwatchColor.TEXT_TITLE))
.mask()
.into(viewHolder.imageButton);
}
return false;
}
};
Glide.with(viewHolder.bottomBar.getContext())
.load(image.thumbURL())
.fitCenter()
.placeholder(R.color.Transparent)
.listener(glideDrawableRequestListener)
.into(viewHolder.imageView);
viewHolder.textViewResolution.setText(image.resolution());
if (existingFiles != null && existingFiles.containsKey(image.imageId())) {
if (valueAnimators.get(position) != null) {
valueAnimators.get(position).cancel();
}
viewHolder.imageButton.setImageResource(R.drawable.ic_action_heart_full);
viewHolder.imageButton.getDrawable().mutate().setColorFilter(viewHolder.textViewResolution.getCurrentTextColor(), PorterDuff.Mode.MULTIPLY);
viewHolder.imageButton.getDrawable().mutate().setAlpha(255);
viewHolder.imageButton.setOnClickListener(null);
} else if (WallyApplication.getDownloadIDs().containsValue(image.imageId())) {
viewHolder.imageButton.setOnClickListener(null);
animateDownload(viewHolder, position);
} else {
viewHolder.imageButton.setImageResource(R.drawable.ic_action_heart_empty);
viewHolder.imageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onSaveButtonClickedListener != null) {
v.setOnClickListener(null);
onSaveButtonClickedListener.onSaveButtonClicked(image);
animateDownload(viewHolder, position);
}
}
});
viewHolder.imageButton.getDrawable().mutate().setColorFilter(viewHolder.textViewResolution.getCurrentTextColor(), PorterDuff.Mode.MULTIPLY);
}
}
viewHolder.itemView.getLayoutParams().height = itemSize + barHeight;
viewHolder.itemView.getLayoutParams().width = itemSize;
}
private void animateDownload(final ViewHolder viewHolder, int position) {
viewHolder.imageButton.setImageResource(R.drawable.ic_heart_download_animation);
if (valueAnimators.get(position) != null) {
valueAnimators.get(position).cancel();
}
ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 10000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
if (viewHolder.imageButton.getDrawable() instanceof LayerDrawable) {
LayerDrawable layerDrawable = (LayerDrawable) viewHolder.imageButton.getDrawable();
layerDrawable.getDrawable(0).mutate().setColorFilter(viewHolder.textViewResolution.getCurrentTextColor(), PorterDuff.Mode.MULTIPLY);
if (layerDrawable.getDrawable(layerDrawable.getNumberOfLayers()-1) instanceof ClipDrawable) {
ClipDrawable clipDrawable = (ClipDrawable) layerDrawable.getDrawable(layerDrawable.getNumberOfLayers()-1);
clipDrawable.mutate().setColorFilter(viewHolder.textViewResolution.getCurrentTextColor(), PorterDuff.Mode.MULTIPLY);
clipDrawable.mutate().setLevel((Integer) animation.getAnimatedValue());
float reversedValue = 10000f - ((Integer) animation.getAnimatedValue());
float alphaValue = reversedValue / 10000f;
if (alphaValue > 0.5f) {
clipDrawable.mutate().setAlpha(255);
} else {
float f = alphaValue * 2;
clipDrawable.mutate().setAlpha(f == 1.0f ? 255 : (int) (f * 256.0f));
}
}
}
}
});
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
valueAnimator.setDuration(500);
valueAnimator.start();
valueAnimators.append(position, valueAnimator);
}
public RecyclerImagesAdapter(ArrayList<Image> images, int itemSize) {
this.images = images;
this.itemSize = itemSize;
}
public Image getItem(int position) {
return images.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemCount() {
return images.size();
}
public void setImages(ArrayList<Image> images) {
this.images = images;
}
public ArrayList<Image> getImages() {
return images;
}
public void setOnSaveButtonClickedListener(OnSaveButtonClickedListener onSaveButtonClickedListener) {
this.onSaveButtonClickedListener = onSaveButtonClickedListener;
}
public void updateSavedFilesList(HashMap<String, Boolean> savedFilesList) {
existingFiles = savedFilesList;
}
/**
* Will loop through all items in the adapter and check if any are included in the existing files map.
* For each match, a {@code notifyItemChanged()} will be called.
*/
public void notifySavedItemsChanged() {
for (int i = 0; i < getItemCount(); i++) {
Image image = getItem(i);
if (existingFiles.containsKey(image.imageId())){
notifyItemChanged(i);
}
}
}
public interface OnSaveButtonClickedListener {
abstract void onSaveButtonClicked(Image image);
}
private class NoDataException extends NullPointerException {
private NoDataException(String detailMessage) {
super(detailMessage);
}
}
public class ViewHolder extends RecyclerView.ViewHolder {
View itemView;
ImageView imageView;
ViewGroup bottomBar;
ImageButton imageButton;
TextView textViewResolution;
public ViewHolder(View itemView) {
super(itemView);
this.itemView = itemView;
imageView = (ImageView) itemView.findViewById(R.id.thumb_image_view);
imageButton = (ImageButton) itemView.findViewById(R.id.thumb_button_heart);
textViewResolution = (TextView) itemView.findViewById(R.id.thumb_text_resolution);
bottomBar = (ViewGroup) itemView.findViewById(R.id.thumb_bottom_view);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onItemClickListener != null) {
onItemClickListener.onItemClick(v, getPosition());
}
}
});
}
}
public interface OnItemClickListener {
abstract void onItemClick(View view, int position);
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public interface OnGetViewListener {
abstract void onBindView(int position);
}
public void setOnGetViewListener(OnGetViewListener onGetViewListener) {
this.onGetViewListener = onGetViewListener;
}
}