Files
briar/briar-android/src/org/briarproject/android/view/BriarRecyclerView.java
Torsten Grote d5beca5351 Port Signal's emoji implementation to Briar
Add functionality to save and restore recently used Emojis

Update emoji and add new categories based on AOSP's XML file
2016-09-23 17:18:18 +01:00

210 lines
5.7 KiB
Java

package org.briarproject.android.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.Adapter;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.briarproject.R;
import java.util.logging.Logger;
import static org.briarproject.android.util.AndroidUtils.MIN_RESOLUTION;
public class BriarRecyclerView extends FrameLayout {
private static final long DEFAULT_REFRESH_INTERVAL = MIN_RESOLUTION;
private static final Logger LOG =
Logger.getLogger(BriarRecyclerView.class.getName());
private RecyclerView recyclerView;
private TextView emptyView;
private ProgressBar progressBar;
private RecyclerView.AdapterDataObserver emptyObserver;
private Runnable refresher = null;
private boolean isScrollingToEnd = false;
public BriarRecyclerView(Context context) {
this(context, null, 0);
}
public BriarRecyclerView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public BriarRecyclerView(Context context, @Nullable AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
TypedArray attributes = context.obtainStyledAttributes(attrs,
R.styleable.BriarRecyclerView);
isScrollingToEnd = attributes
.getBoolean(R.styleable.BriarRecyclerView_scrollToEnd, true);
String emtpyText =
attributes.getString(R.styleable.BriarRecyclerView_emptyText);
if (emtpyText != null) setEmptyText(emtpyText);
attributes.recycle();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
stopPeriodicUpdate();
}
private void initViews() {
View v = LayoutInflater.from(getContext()).inflate(
R.layout.briar_recycler_view, this, true);
recyclerView = (RecyclerView) v.findViewById(R.id.recyclerView);
emptyView = (TextView) v.findViewById(R.id.emptyView);
progressBar = (ProgressBar) v.findViewById(R.id.progressBar);
showProgressBar();
// scroll down when opening keyboard
if (isScrollingToEnd) {
addLayoutChangeListener();
}
emptyObserver = new RecyclerView.AdapterDataObserver() {
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
super.onItemRangeInserted(positionStart, itemCount);
if (itemCount > 0) showData();
}
@Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
super.onItemRangeRemoved(positionStart, itemCount);
if (itemCount > 0) showData();
}
};
}
private void addLayoutChangeListener() {
recyclerView.addOnLayoutChangeListener(
new OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top,
int right, int bottom, int oldLeft, int oldTop,
int oldRight, int oldBottom) {
if (bottom < oldBottom) {
recyclerView.postDelayed(new Runnable() {
@Override
public void run() {
scrollToPosition(
recyclerView.getAdapter()
.getItemCount() - 1);
}
}, 100);
}
}
});
}
public void setLayoutManager(RecyclerView.LayoutManager layout) {
if (recyclerView == null) initViews();
recyclerView.setLayoutManager(layout);
}
public void setAdapter(Adapter adapter) {
if (recyclerView == null) initViews();
Adapter oldAdapter = recyclerView.getAdapter();
if (oldAdapter != null) {
oldAdapter.unregisterAdapterDataObserver(emptyObserver);
}
recyclerView.setAdapter(adapter);
if (adapter != null) {
adapter.registerAdapterDataObserver(emptyObserver);
if (adapter.getItemCount() > 0) {
// only show data if adapter has data already
// otherwise progress bar is shown
emptyObserver.onChanged();
}
}
}
public void setEmptyText(String text) {
if (recyclerView == null) initViews();
emptyView.setText(text);
}
public void setEmptyText(int res) {
if (recyclerView == null) initViews();
emptyView.setText(res);
}
public void showProgressBar() {
if (recyclerView == null) initViews();
recyclerView.setVisibility(INVISIBLE);
emptyView.setVisibility(INVISIBLE);
progressBar.setVisibility(VISIBLE);
}
public void showData() {
if (recyclerView == null) initViews();
Adapter adapter = recyclerView.getAdapter();
if (adapter != null) {
if (adapter.getItemCount() == 0) {
emptyView.setVisibility(VISIBLE);
recyclerView.setVisibility(INVISIBLE);
} else {
// use GONE here so empty view doesn't use space on small lists
emptyView.setVisibility(GONE);
recyclerView.setVisibility(VISIBLE);
}
progressBar.setVisibility(GONE);
}
}
public void scrollToPosition(int position) {
if (recyclerView == null) initViews();
recyclerView.scrollToPosition(position);
}
public void smoothScrollToPosition(int position) {
if (recyclerView == null) initViews();
recyclerView.smoothScrollToPosition(position);
}
public RecyclerView getRecyclerView() {
return this.recyclerView;
}
public void startPeriodicUpdate() {
if (recyclerView == null || recyclerView.getAdapter() == null) {
throw new IllegalStateException("Need to call setAdapter() first!");
}
refresher = new Runnable() {
@Override
public void run() {
LOG.info("Updating Content...");
recyclerView.getAdapter().notifyDataSetChanged();
postDelayed(refresher, DEFAULT_REFRESH_INTERVAL);
}
};
LOG.info("Adding Handler Callback");
postDelayed(refresher, DEFAULT_REFRESH_INTERVAL);
}
public void stopPeriodicUpdate() {
if (refresher != null) {
LOG.info("Removing Handler Callback");
removeCallbacks(refresher);
}
}
}