Skip to content

Instantly share code, notes, and snippets.

@brunodles
Last active December 13, 2016 01:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brunodles/3d866e816f3e52dd6406530ed4ba5368 to your computer and use it in GitHub Desktop.
Save brunodles/3d866e816f3e52dd6406530ed4ba5368 to your computer and use it in GitHub Desktop.
Add new views on a LinearLayout like you do on a ListView or RecycleView
import android.database.DataSetObserver;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.UiThread;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.LinearLayout;
import java.util.ArrayList;
import java.util.List;
/**
* Created by bruno on 27/06/16.
*/
public final class LinearLayoutWrapper {
private static final String TAG = "LinearLayoutAdapter";
private final LinearLayout layout;
private final AdapterInterator interator;
private Runnable register, unregister;
private final Handler mainHandler = new Handler(Looper.getMainLooper());
public LinearLayoutWrapper(LinearLayout layout, Adapter adapter) {
this.layout = layout;
removeBuiltViews();
interator = new ListViewAdapterInterator(adapter);
setupAdapter(adapter);
register.run();
}
public LinearLayoutWrapper(LinearLayout layout, RecyclerView.Adapter adapter) {
this.layout = layout;
removeBuiltViews();
interator = new RecyclerViewAdapterInterator(adapter);
setupAdapter(adapter);
register.run();
}
private void setupAdapter(Adapter adapter) {
DataSetObserver observer = new ListViewAdapterObserver(this::cleanAndBuildViews);
buildViews();
register = () -> {
try {
adapter.registerDataSetObserver(observer);
} catch (IllegalStateException e) {
}
};
unregister = () -> {
try {
adapter.unregisterDataSetObserver(observer);
} catch (IllegalStateException e) {
}
};
}
private void setupAdapter(RecyclerView.Adapter adapter) {
RecyclerViewAdapterObserver observer = new RecyclerViewAdapterObserver(this::cleanAndBuildViews);
buildViews();
register = () -> {
try {
adapter.registerAdapterDataObserver(observer);
} catch (IllegalStateException e) {
}
};
unregister = () -> {
try {
adapter.unregisterAdapterDataObserver(observer);
} catch (IllegalStateException e) {
}
};
}
private void cleanAndBuildViews() {
mainHandler.post(() -> {
removeBuiltViews();
tryBuildViews();
});
}
@UiThread
private void tryBuildViews() {
try {
buildViews();
} catch (Exception e) {
Log.e(TAG, "tryBuildViews: Hey guys, looks like we got one exception when build a new view", e);
}
}
@UiThread
private void buildViews() {
for (int i = 0; i < interator.getCount(); i++)
addView(interator.getView(i, layout));
}
@UiThread
private void addView(View view) {
layout.addView(view);
}
@UiThread
private synchronized void removeBuiltViews() {
layout.removeAllViews();
}
public void register() {
if (register != null) register.run();
}
public void unregister() {
if (unregister != null) unregister.run();
}
private static interface AdapterInterator {
int getCount();
View getView(int index, ViewGroup container);
}
private static final class ListViewAdapterInterator implements AdapterInterator {
private final Adapter adapter;
public ListViewAdapterInterator(Adapter adapter) {
this.adapter = adapter;
}
@Override
public int getCount() {
return adapter.getCount();
}
@Override
public View getView(int index, ViewGroup container) {
return adapter.getView(index, null, container);
}
}
private static final class RecyclerViewAdapterInterator implements AdapterInterator {
private final RecyclerView.Adapter adapter;
public RecyclerViewAdapterInterator(RecyclerView.Adapter adapter) {
this.adapter = adapter;
}
@Override
public int getCount() {
return adapter.getItemCount();
}
@Override
public View getView(int index, ViewGroup container) {
RecyclerView.ViewHolder viewHolder = adapter.onCreateViewHolder(container, adapter.getItemViewType(index));
adapter.onBindViewHolder(viewHolder, index);
return viewHolder.itemView;
}
}
private static interface OnDataSetChanged {
void onChanged();
}
private static final class ListViewAdapterObserver extends DataSetObserver {
private final OnDataSetChanged listener;
ListViewAdapterObserver(OnDataSetChanged listener) {
this.listener = listener;
}
@Override
public void onChanged() {
listener.onChanged();
}
}
private static final class RecyclerViewAdapterObserver extends RecyclerView.AdapterDataObserver {
private final OnDataSetChanged listner;
RecyclerViewAdapterObserver(OnDataSetChanged listner) {
this.listner = listner;
}
@Override
public void onChanged() {
listner.onChanged();
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount) {
onChanged();
}
@Override
public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
onChanged();
}
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
onChanged();
}
@Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
onChanged();
}
}
}
public class SampleActivity extends Activity {
private LinearLayout linearLayout;
private LinearLayoutWrapper wrapper;
private RecyclerView.Adapter myAdapter;
private List<Dto> data;
public void onCreate(Bundler savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sample);
linearLayout = (LinearLayout)findViewById(R.id.myLinearLayout);
// Here the wrapper will try to find the data from the adapter and build the views.
// The wrapper will be registered as an observer of the myAdapter
wrapper = new LinearLayoutWrapper(linearLayout, myAdapter);
}
public void onStart() {
super.onStart();
// data = getDataFromSomewhere();
}
public void onResume() {
super.onResume();
// you can instatiate the wrapper here.
// If you choose to instantiate it on the `onCreate`, call `wrapper.register()`, just for sure.
wrapper.register();
// Beware: when you change the adapter the whole LinearLayout will be recreated.
myAdapter.setList(data);
myAdapter.notifyDataSetChanged();
}
public void onPause() {
super.onPause();
// unregister the wrapper
if (wrapper != null) wrapper.unregister();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment