package net.yslibrary.licenseadapter; import android.app.Activity; import android.app.Application; import android.content.Context; import android.view.LayoutInflater; import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.FragmentActivity; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.RecyclerView; import net.yslibrary.licenseadapter.internal.ExpandableLibrary; import net.yslibrary.licenseadapter.internal.LibrariesHolder; import net.yslibrary.licenseadapter.internal.LibraryViewHolder; import net.yslibrary.licenseadapter.internal.LicenseViewHolder; import net.yslibrary.licenseadapter.internal.ViewHolderBase; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * A {@link RecyclerView.Adapter} which displays expandable items with a library and its license. * <p> * For optimal performance, the {@link RecyclerView} using this adapter should be attached a support * library context such as the {@link AppCompatActivity}. * * @see Library * @see Licenses */ public final class LicenseAdapter extends RecyclerView.Adapter<ViewHolderBase> implements ExpandableLibrary.ExpandListener { private static final int TYPE_LIBRARY = 0; private static final int TYPE_LICENSE = 1; private final List<ExpandableLibrary> libraries; private LibrariesHolder holder; /** * Construct a new adapter to display a list of libraries and their licenses. * * @param libraries the libraries to display */ public LicenseAdapter(@NonNull List<Library> libraries) { List<ExpandableLibrary> wrappedLibraries = new ArrayList<>(); for (Library library : libraries) { wrappedLibraries.add(new ExpandableLibrary(library, this)); } this.libraries = Collections.unmodifiableList(wrappedLibraries); } @Override public int getItemViewType(int position) { return position % 2 == 0 ? TYPE_LIBRARY : TYPE_LICENSE; } @Override public int getItemCount() { return libraries.size() * 2; } @Override public ViewHolderBase onCreateViewHolder(ViewGroup parent, int viewType) { Context context = parent.getContext(); if (holder == null) { if (context instanceof FragmentActivity) { ViewModelProvider.AndroidViewModelFactory factory = ViewModelProvider.AndroidViewModelFactory.getInstance(((FragmentActivity) context).getApplication()); holder = new ViewModelProvider((FragmentActivity) context, factory).get(LibrariesHolder.class); } else if (context instanceof Activity) { holder = new LibrariesHolder(((Activity) context).getApplication()); } else { holder = new LibrariesHolder((Application) context.getApplicationContext()); } } if (viewType == TYPE_LIBRARY) { return new LibraryViewHolder(LayoutInflater.from(context) .inflate(R.layout.library, parent, false)); } else if (viewType == TYPE_LICENSE) { return new LicenseViewHolder(LayoutInflater.from(context) .inflate(R.layout.license, parent, false), holder); } else { throw new IllegalStateException("Unknown view type: " + viewType); } } @Override public void onBindViewHolder(@NonNull ViewHolderBase holder, int position) { int type = getItemViewType(position); if (type == TYPE_LIBRARY) { holder.bind(libraries.get(position / 2)); } else if (type == TYPE_LICENSE) { holder.bind(libraries.get((position - 1) / 2)); } else { throw new IllegalStateException("Unknown view type: " + type); } } @Override public void onExpand(@NonNull ExpandableLibrary library, boolean expanded) { int index = libraries.indexOf(library); if (index == -1) { throw new IllegalStateException("Could not find library: " + library); } notifyItemRangeChanged(index * 2, 2); } }