Last active
December 13, 2016 01:50
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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