Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Icon search function #481

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 44 additions & 57 deletions app/src/main/java/com/dkanada/icecons/activities/IconActivity.java
Original file line number Diff line number Diff line change
@@ -1,80 +1,67 @@
package com.dkanada.icecons.activities;

import android.graphics.Rect;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import android.widget.GridView;

import com.dkanada.icecons.R;
import com.dkanada.icecons.utils.ImageUtils;
import com.dkanada.icecons.utils.ScreenUtils;
import com.dkanada.icecons.adapters.IconAdapter;

import java.util.ArrayList;
import java.util.Collections;

public class IconActivity extends BaseActivity {
private final ArrayList<LinearLayout> layoutList = new ArrayList<>();
private final ArrayList<ImageView> imageList = new ArrayList<>();
private final IconAdapter mAdapter = new IconAdapter(R.layout.grid_item);
private String[] mImages;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (ScreenUtils.isPortrait(getApplicationContext())) {
createLayout(7);
} else {
createLayout(12);
}
}

private void createLayout(int width) {
float scale = ScreenUtils.densityScale(getApplicationContext());
int margin = 16 * Math.round(scale);

LinearLayout.LayoutParams baseParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
LinearLayout.LayoutParams containerParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
LinearLayout.LayoutParams imageParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f);
setContentView(R.layout.icon_grid);

ScrollView baseScroller = new ScrollView(this);
baseScroller.setLayoutParams(baseParams);
baseScroller.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
setContentView(baseScroller);
baseScroller.setVisibility(View.VISIBLE);
mImages = getResources().getStringArray(R.array.icon_pack);

// display width hack
Rect windowRect = new Rect();
baseScroller.getWindowVisibleDisplayFrame(windowRect);
int windowWidth = windowRect.right - windowRect.left;

LinearLayout baseLayout = new LinearLayout(this);
baseLayout.setOrientation(LinearLayout.VERTICAL);
baseLayout.setLayoutParams(layoutParams);
baseLayout.setPadding(margin, margin, 0, 0);
baseScroller.addView(baseLayout);
EditText searchBar = findViewById(R.id.searchBar);
searchBar.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}

String[] images = getResources().getStringArray(R.array.icon_pack);
for (int i = 0; i < images.length; i++) {
if (i % width == 0) {
layoutList.add((i / width), new LinearLayout(this));
layoutList.get(i / width).setOrientation(LinearLayout.HORIZONTAL);
layoutList.get(i / width).setGravity(Gravity.START);
layoutList.get(i / width).setLayoutParams(containerParams);
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
mAdapter.clearList();
if (charSequence.length() == 0) {
mAdapter.newLoadAsyncList(() -> {
ArrayList<String> imageList = new ArrayList<>(mImages.length);
Collections.addAll(imageList, mImages);
return imageList;
}).execute();
} else {
String searchString = charSequence.toString().toLowerCase();
mAdapter.newLoadAsyncList(() -> {
ArrayList<String> imageList = new ArrayList<>(mImages.length);
for (String s : mImages) {
if (s.contains(searchString)) {
imageList.add(s);
}
}
return imageList;
}).execute();
}
}

baseLayout.addView(layoutList.get(i / width));
@Override
public void afterTextChanged(Editable editable) {
}

imageList.add(i, new ImageView(this));
imageList.get(i).setLayoutParams(imageParams);
imageList.get(i).setScaleType(ImageView.ScaleType.FIT_XY);
imageList.get(i).setPadding(0, 0, margin, margin);
imageList.get(i).setAdjustViewBounds(true);
});

final int resId = getResources().getIdentifier(images[i], "drawable", getPackageName());
ImageUtils.bitmapLoadAsync(imageList.get(i), getApplicationContext().getResources(), resId, (windowWidth / width) - (margin * width + margin) / width, (windowWidth / width) - (margin * width + margin) / width);
GridView gridView = findViewById(R.id.iconGrid);
gridView.setAdapter(mAdapter);

layoutList.get(i / width).addView(imageList.get(i));
}
// call onTextChanged
searchBar.setText(null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.dkanada.icecons.adapters;

import java.util.ArrayList;

public class IconAdapter extends ViewHolderListAdapter<String, IconViewHolder> {
public IconAdapter(int listItemLayout) {
super(IconViewHolder.class, listItemLayout, new ArrayList<>(0));
}
}
77 changes: 77 additions & 0 deletions app/src/main/java/com/dkanada/icecons/adapters/IconViewHolder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.dkanada.icecons.adapters;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;

import java.lang.ref.WeakReference;

public class IconViewHolder extends ViewHolderAdapter.ViewHolder<String> {
private final ImageView icon;
private AsyncTask<String, Void, Drawable> asyncLoad = null;
private final static View.OnLongClickListener longClickListener = v -> {
CharSequence content = null;
if (v instanceof ImageView)
content = v.getContentDescription();
if (content != null)
Toast.makeText(v.getContext(), content, Toast.LENGTH_SHORT).show();
return true;
};

public IconViewHolder(View view) {
super(view);
icon = (ImageView) view;
}

@Override
protected void setContent(String content, int position, @NonNull ViewHolderAdapter<String, ? extends ViewHolderAdapter.ViewHolder<String>> adapter) {
//IconAdapter iconAdapter = (IconAdapter) adapter;
if (asyncLoad != null)
asyncLoad.cancel(false);

icon.setContentDescription(content);
icon.setOnLongClickListener(longClickListener);
icon.animate().cancel();
icon.setAlpha(0f);

asyncLoad = new AsyncLoad(this).execute(content);
}

private static class AsyncLoad extends AsyncTask<String, Void, Drawable> {
private final WeakReference<IconViewHolder> weakHolder;

public AsyncLoad(IconViewHolder holder) {
super();
weakHolder = new WeakReference<>(holder);
}

@Override
protected Drawable doInBackground(String... strings) {
IconViewHolder holder = weakHolder.get();
if (holder == null || strings.length == 0)
return null;
String resIdName = strings[0];
Context ctx = holder.icon.getContext();
final int resId = ctx.getResources().getIdentifier(resIdName, "drawable", ctx.getPackageName());
return ResourcesCompat.getDrawable(ctx.getResources(), resId, null);
}

@Override
protected void onPostExecute(Drawable drawable) {
IconViewHolder holder = weakHolder.get();
if (holder != null && this.equals(holder.asyncLoad)) {
holder.asyncLoad = null;
holder.icon.setImageDrawable(drawable);
holder.icon.animate()
.alpha(1f)
.setDuration(1000);
}
}
}
}
130 changes: 130 additions & 0 deletions app/src/main/java/com/dkanada/icecons/adapters/ViewHolderAdapter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package com.dkanada.icecons.adapters;

import android.os.AsyncTask;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.dkanada.icecons.BuildConfig;

import java.util.Collection;

/**
* Adapter class that implements the View holder pattern.
* The ViewHolder is held as a tag in the list item view.
*
* @param <T> Type of data to send to the ViewHolder
* @param <VH> ViewHolder class
*/
public abstract class ViewHolderAdapter<T, VH extends ViewHolderAdapter.ViewHolder<T>> extends BaseAdapter {
@NonNull
final Class<VH> mViewHolderClass;
@LayoutRes
final int mListItemLayout;

protected ViewHolderAdapter(@NonNull Class<VH> viewHolderClass, @LayoutRes int listItemLayout) {
mViewHolderClass = viewHolderClass;
mListItemLayout = listItemLayout;
}

@LayoutRes
protected int getItemViewTypeLayout(int viewType) {
return mListItemLayout;
}

@Override
public abstract T getItem(int position);

@Override
public long getItemId(int position) {
return getItem(position).hashCode();
}

@Override
public boolean hasStableIds() {
return true;
}

@Nullable
protected VH getNewViewHolder(View view) {
VH holder = null;
try {
holder = mViewHolderClass.getDeclaredConstructor(View.class).newInstance(view);
} catch (Exception e) {
Log.e("VHA", "ViewHolder can't be instantiated (make sure class and constructor are public)", e);
}
return holder;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
final View view;
if (convertView == null) {
int viewType = getItemViewType(position);
if (BuildConfig.DEBUG) {
int viewTypeCount = getViewTypeCount();
if (viewType >= viewTypeCount)
throw new IllegalStateException("ViewType " + viewType + " >= ViewTypeCount " + viewTypeCount);
}
@LayoutRes
int itemLayout = getItemViewTypeLayout(viewType);
view = LayoutInflater.from(parent.getContext()).inflate(itemLayout, parent, false);
} else {
view = convertView;
}

Object tag = view.getTag();
VH holder = mViewHolderClass.isInstance(tag) ? mViewHolderClass.cast(tag) : getNewViewHolder(view);
if (holder != null) {
T content = getItem(position);
holder.setContent(content, position, this);
}
return view;

}

public static abstract class ViewHolder<T> {
protected ViewHolder(View view) {
view.setTag(this);
}

protected abstract void setContent(T content, int position, @NonNull ViewHolderAdapter<T, ? extends ViewHolder<T>> adapter);
}

public static abstract class LoadAsyncData<T> extends AsyncTask<Void, Void, Collection<T>> {
private final ViewHolderAdapter<T, ? extends ViewHolder<T>> adapter;
private final LoadInBackground<T> task;

public interface LoadInBackground<T> {
@Nullable
Collection<T> loadInBackground();
}

public LoadAsyncData(@NonNull ViewHolderAdapter<T, ? extends ViewHolder<T>> adapter, @NonNull LoadInBackground<T> loadInBackground) {
super();
this.adapter = adapter;
task = loadInBackground;
}

@Override
protected Collection<T> doInBackground(Void... voids) {
return task.loadInBackground();
}

@Override
protected void onPostExecute(Collection<T> data) {
if (data == null)
return;
//adapter.addAll(data);
onDataLoadFinished(adapter, data);
}

protected abstract void onDataLoadFinished(@NonNull ViewHolderAdapter<T, ? extends ViewHolder<T>> adapter, @NonNull Collection<T> data);
}
}
Loading