Native Android BottomSheet is not appearing in React Native - java

I am building a custom component in Java and trying to display that in React Native but the component is not appearing. I've been looking through forums and documentation for solutions but can't find a solution. I am not sure if it's an issue on the native side or the React Native side. Any help or advice on improvement is highly appreciated.
Bottom Sheet View
public class BottomSheetView extends NestedScrollView {
private BottomSheetBehavior bSheetBehavior;
public BottomSheetView(Context context) {
super(context);
init();
}
private void init() {
inflate(getContext(), R.layout.bottom_sheet, this);
CoordinatorLayout coordinaterLayout = findViewById(R.id.coordinate_layout);
View bottomSheet = coordinaterLayout.findViewById(R.id.bottom_sheet_component);
bSheetBehavior = BottomSheetBehavior.from(bottomSheet);
bSheetBehavior.setHideable(false);
bSheetBehavior.setPeekHeight((int) PixelUtil.toPixelFromDIP(200));
}
#Override
protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
}
}
Bottom Sheet Manager
public class BottomSheetManager extends ViewGroupManager<BottomSheetView> {
public static final String REACT_CLASS = "BottomSheet";
private BottomSheetView bottomSheet;
#Override
public String getName() {
return REACT_CLASS;
}
#Override
protected BottomSheetView createViewInstance(ThemedReactContext reactContext) {
return new BottomSheetView(reactContext);
}
}
Bottom Sheet Package
public class BottomSheetPackage implements ReactPackage {
private Activity mActivity = null;
BottomSheetPackage(Activity activity) {
mActivity = activity;
}
public BottomSheetPackage() {
}
#Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = Collections.emptyList();
return modules;
}
#Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Arrays.<ViewManager>asList(new BottomSheetManager());
}
}
React Native
class BottomSheet extends Component {
render() {
return (<BottomSheet style={{height: 200}}/>);
}
}

Related

Access view created by ui component in native module in React Native

I have created a custom UI component TextInputPro that renders an EditText. I also have a native module that I can send events like focus() to.
My files are
|-- TextInputProPackage.java <--- packages all together
|-- TextInputProManager.java <--- creates a view (EditText)
|-- TextInputProModule.java <--- gets events from JS
How can TextInputProModule.java communicate with the View created by TextInputProManager.java?
TextInputProPackage.java:
public class TextInputProPackage implements ReactPackage {
#Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
// MODULE CREATED HERE
return Arrays.<NativeModule>asList(
new TextInputProModule(reactContext)
);
}
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
//VIEW CREATED HERE
return Arrays.<ViewManager>asList(
new TextInputProManager()
);
}
}
TextInputProManager.java:
public class TextInputProManager extends SimpleViewManager<EditText> {
public static final String REACT_CLASS = "TextInputPro";
public EditText editText;
#Override
public String getName() {
return REACT_CLASS;
}
#Override
public EditText createViewInstance(ThemedReactContext context){
editText = new EditText(context);
editText.setText("hello world");
return editText;
}
}
TextInputProModule.java:
public class TextInputProModule extends ReactContextBaseJavaModule {
public static final String REACT_CLASS = "TextInputPro";
private static ReactApplicationContext reactContext = null;
public TextInputProModule(ReactApplicationContext context) {
super(context);
reactContext = context;
}
#Override
public String getName() {
return REACT_CLASS;
}
#ReactMethod
public void focus () {
// WHERE ARE YOU EDITTEXT?
}
}
In my head, I have to make a global variable in Package.java and pass it down to both constructors, but I couldn't make that work

How pass data from RecyclerView to activity

I need to pass data from recyclerView adapter to main activity on click on image of recyclerview. Can someone help?
public class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.VideoHolder> {
private ArrayList<Video> mData;
private ArrayList<Video> mData2;
private Activity mACtivity;
public VideoAdapter(ArrayList<Video> data, ArrayList<Video> data2, Activity activity) {
this.mData = data;
this.mData2 = data2;
this.mACtivity = activity;
}
#Override
public VideoHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.anteprima_list_item, parent, false);
//view.setOnClickListener(mOnClickListener);
return new VideoHolder(view);
}
#Override
public void onBindViewHolder(VideoHolder holder, int position) {
Video video = mData.get(position);
final Video video2 = mData2.get(position);
holder.setTitolo(video.getTitolo());
holder.setSottoTitolo(video.getSottotitolo());
holder.setData(video.getData());
holder.setData(video.getData());
/* holder.setAddress(restaurant.getAddress());
holder.setCost("Average cost for 2: " + restaurant.getCurrency() + restaurant.getCost());
holder.setRating(restaurant.getRating());*/
Glide.with(mACtivity)
.load(video2.getPic())
.into(holder.restaurantImageView);
holder.restaurantImageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// handle click event here
System.out.println("PIC"+video2.getPic());
}
});
}
#Override
public int getItemCount() {
if (mData == null)
return 0;
return mData.size();
}
public class VideoHolder extends RecyclerView.ViewHolder {
ImageView restaurantImageView;
TextView restaurantNameTextView;
TextView restaurantAddressTextView;
TextView restaurantRatingTextView;
TextView costTextView;
TextView distanceTextView;
LinearLayout linearlayout;
public VideoHolder(View itemView) {
super(itemView);
linearlayout=(LinearLayout) itemView.findViewById((R.id.linearlayout));
restaurantImageView = (ImageView) itemView.findViewById(R.id.imageview_restaurant);
restaurantNameTextView = (TextView) itemView.findViewById(R.id.textview_restaurant_name);
restaurantAddressTextView = (TextView) itemView.findViewById(R.id.restaurant_address_textview);
distanceTextView = (TextView) itemView.findViewById(R.id.restaurant_distance_textview);
/* costTextView = (TextView) itemView.findViewById(R.id.cost_for_two_textview);
restaurantRatingTextView = (TextView) itemView.findViewById(R.id.rating);*/
}
public void setTitolo(String titolo) {
restaurantNameTextView.setText(titolo);
}
public void setSottoTitolo(String sottotitolo) {
restaurantAddressTextView.setText(sottotitolo);
}
public void setData(String data) {
distanceTextView.setText(data);
}
/* public void setPic(String pic) {
distanceTextView.setText(pic);
}
public void setCost(String cost) {
costTextView.setText(cost);
}
public void setDistance(String distance) {
distanceTextView.setText(distance);
}*/
}
}
Create a listener Interface and let your MainActivity implement it. That way you can call your callback method in your onClick method.
Interface:
public interface OnImageClickListener {
void onImageClick(String imageData);
}
MainActivity:
public class MainActivity implements OnImageClickListener {
#Override
public void onImageClick(String imageData) {
// handle image data
}
//...
}
Your VideoAdapter:
//...
private OnImageClickListener onImageClickListener;
public VideoAdapter(ArrayList<Video> data, ArrayList<Video> data2, Activity activity, OnImageClickListener onImageClickListener) {
this.mData = data;
this.mData2 = data2;
this.mACtivity = activity;
this.onImageClickListener = onImageClickListener;
}
//...
#Override
public void onBindViewHolder(VideoHolder holder, int position) {
//...
holder.restaurantImageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onImageClickListener.onImageClick(video2.getPic());
}
});
//...
}
//...
If you want to pass value from onclick to your Parent activity, use onMethodCallback in your MainActivity:
public class MainActivity extends Activity implements AdapterCallback {
private MyAdapter mMyAdapter;
#Override
public void onMethodCallback(String yourValue) {
// get your value here
}
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.mMyAdapter = new MyAdapter(this);
}
}
In your Adapter:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private AdapterCallback mAdapterCallback;
public MyAdapter(Context context) {
try {
this.mAdapterCallback = ((AdapterCallback) context);
} catch (ClassCastException e) {
throw new ClassCastException("Activity must implement AdapterCallback.");
}
}
#Override
public void onBindViewHolder(final MyAdapter.ViewHolder viewHolder, final int i) {
// simple example, call interface here
// not complete
viewHolder.itemView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mAdapterCallback.onMethodCallback();
}
});
}
public static interface AdapterCallback {
void onMethodCallback(String yourValue);
}
}
If you are working with kotlin, the solution is much simpler.
Original Answer here
pass the lamda val itemClick: (Int) -> Unit to your adapter.
class MyRecyclerViewAdapter(params , val itemClick: (Int) -> Unit): RecyclerView.Adapter<RecyclerView.ViewHolder>() {
internal inner class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
...
itemView.setOnClickListener( {itemClick(layoutPosition)} )
}
}
In your Activity use the returned value position
val myAdapter = MyRecyclerViewAdapter(params) { position ->
// do something
}
Write interface in your adapter like bellow :
interface clickItemListener {
void onItemClick(String order);
}
And your constructor should be :
privat clickItemListener clickItemListeners;
public VideoAdapter(ArrayList<Video> data, ArrayList<Video> data2, Activity activity, clickItemListener clickItemListeners) {
this.mData = data;
this.mData2 = data2;
this.mACtivity = activity;
this.clickItemListeners = clickItemListeners;
}
Then you can pass to Activity :
yourLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
clickItemListeners.onItemClick(yourValue);
}
});
And implement your interface in your activity like bellow :
public class yourActivity extends AppCompatActivity implements
YourAdapter.clickItemListener{
#Override
public void onItemClick(String order) {
//You can get your value here
}
}
Remember that you should pass activity to adapter like bellow :
YourAdapter adapter = new YourAdapter (... , ... , ... , activity.this);

how to use Architecture Components ViewModel inside RecyclerView Adapter?

I have multiple ViewHolders that work as separated views inside a vertical RecyclerView. I'm practicing with the new Architecture Components ViewModel.
Inside my ViewModel I have a couple of MutableLiveData lists that i want to observe, but how can I call
ViewModelProviders.of((AppCompatActivity)getActivity()).get(FilterViewModel.class)
and
mFilterViewModel.getCountries().observe(this, new Observer<ArrayList<TagModel>>() {
#Override
public void onChanged(#Nullable ArrayList<TagModel> tagModels) {
}
});
without leaking the activity or save the activity inside the adapter?
my ViewModel
public class FilterViewModel extends ViewModel {
private final MutableLiveData<ArrayList<TagModel>> mCountries;
private final MutableLiveData<ArrayList<TagModel>> mSelectedCountryProvinceList;
private final MutableLiveData<ArrayList<TagModel>> mDistanceList;
public FilterViewModel(){
mCountries = new MutableLiveData<>();
mSelectedCountryProvinceList = new MutableLiveData<>();
mDistanceList = new MutableLiveData<>();
TagStore.getInstance().subscribe(new StoreObserver<TagSearchList>() {
#Override
public void update(TagSearchList object) {
mCountries.setValue(object.getCountries());
}
#Override
public void update(int id, TagSearchList object) {
if (id == 5){
TagStore.getInstance().unSubcribe(this);
update(object);
}
}
#Override
public void error(String error) {
}
}).get(5,"parent");
TagStore.getInstance().subscribe(new StoreObserver<TagSearchList>() {
#Override
public void update(TagSearchList object) {
mSelectedCountryProvinceList.setValue(object.toList());
}
#Override
public void update(int id, TagSearchList object) {
if (id == 6){
TagStore.getInstance().unSubcribe(this);
update(object);
}
}
#Override
public void error(String error) {
}
}).get(6,"parent");
TagStore.getInstance().subscribe(new StoreObserver<TagSearchList>() {
#Override
public void update(TagSearchList object) {
mDistanceList.setValue(object.toList());
}
#Override
public void update(int id, TagSearchList object) {
if (id == 51){
TagStore.getInstance().unSubcribe(this);
update(object);
}
}
#Override
public void error(String error) {
}
}).get(51,"parent");
}
public void selectCountry(final TagModel country){
TagStore.getInstance().subscribe(new StoreObserver<TagSearchList>() {
#Override
public void update(TagSearchList object) {
mSelectedCountryProvinceList.setValue(object.toList());
}
#Override
public void update(int id, TagSearchList object) {
if (id == country.getId()){
TagStore.getInstance().unSubcribe(this);
update(object);
}
}
#Override
public void error(String error) {
}
}).get(country.getId(),"parent");
}
public LiveData<ArrayList<TagModel>> getCountries(){
return mCountries;
}
public LiveData<ArrayList<TagModel>> getDistances(){
return mDistanceList;
}
public LiveData<ArrayList<TagModel>> getProvinces(){
return mSelectedCountryProvinceList;
}
I am using Room Persistence library. Below is my code for recyclerview adapter using MVVM.
You can see CartViewModel and I have initialized it into the constructor. The constructor gets the context from the activity, and I have cast it into FragmentActivity.
private CartViewModel cartViewModel;
public CartListAdapter(Context context, List<CartModel> cartModels) {
this.context = context;
this.cartModels = cartModels;
cartViewModel = ViewModelProviders.of((FragmentActivity) context).get(CartViewModel.class);
}
Here is my full adapter class. I hope it will help.
public class CartListAdapter extends RecyclerView.Adapter<CartListAdapter.CartListViewHolder> {
private static final String TAG = "CartListAdapter";
private Context context;
private List<CartModel> cartModels;
private Double totalQuantity = 0.0;
private CartViewModel cartViewModel;
public CartListAdapter(Context context, List<CartModel> cartModels) {
this.context = context;
this.cartModels = cartModels;
cartViewModel = ViewModelProviders.of((FragmentActivity) context).get(CartViewModel.class);
}
#NonNull
#Override
public CartListViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new CartListViewHolder(LayoutInflater.from(context).inflate(R.layout.list_all_cart_item,parent,false));
}
#Override
public void onBindViewHolder(#NonNull CartListViewHolder holder, int position) {
CartModel cartModel = cartModels.get(position);
Glide.with(context)
.load(cartModel.getPPICLocate())
.into(holder.cartItemImage);
holder.tvCartProductName.setText(cartModel.getProductName());
holder.tvCartProductCategory.setText(cartModel.getPCategorySubID());
holder.tvCartProductPrice.setText(cartModel.getPPriceSales());
holder.etCartProductQuantity.setText(cartModel.getPQuantity());
holder.btnCartPQtIncrease.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
totalQuantity = Double.valueOf(holder.etCartProductQuantity.getText().toString());
totalQuantity = totalQuantity+1;
cartModel.setPQuantity(totalQuantity.toString());
updateCart(cartModel);
}
});
holder.btnCartPQtDecrease.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
totalQuantity = Double.valueOf(holder.etCartProductQuantity.getText().toString());
totalQuantity = totalQuantity-1;
cartModel.setPQuantity(totalQuantity.toString());
updateCart(cartModel);
}
});
}
#Override
public int getItemCount() {
return cartModels.size();
}
public class CartListViewHolder extends RecyclerView.ViewHolder{
private ImageView cartItemImage;
private TextView tvCartProductName,tvCartProductCategory,tvCartProductPrice,
etCartProductQuantity,tvCartProductPrevPrice;
private ImageButton btnCartPQtIncrease,btnCartPQtDecrease;
public CartListViewHolder(#NonNull View itemView) {
super(itemView);
cartItemImage= itemView.findViewById(R.id.cartItemImage);
tvCartProductName= itemView.findViewById(R.id.tvCartProductName);
tvCartProductCategory= itemView.findViewById(R.id.tvCartProductCategory);
tvCartProductPrice= itemView.findViewById(R.id.tvCartProductPrice);
etCartProductQuantity= itemView.findViewById(R.id.etCartProductQuantity);
tvCartProductPrevPrice= itemView.findViewById(R.id.tvCartProductPrevPrice);
btnCartPQtIncrease= itemView.findViewById(R.id.btnCartPQtIncrease);
btnCartPQtDecrease= itemView.findViewById(R.id.btnCartPQtDecrease);
}
}
public void addItems(List<CartModel> cartModels) {
this.cartModels = cartModels;
notifyDataSetChanged();
}
private void updateCart(CartModel cartModel){
String tqt = String.valueOf(cartModel.getPQuantity());
Log.d(TAG, "updateQuantity: "+tqt);
/*cartRepository.updateCartRepo(cartModel);*/
cartViewModel.updateCartItemVM(cartModel);
}
}
You could create an OnClickListener interface instead, then implement the onClick method (defined in your interface) in your fragment or activity where you have access to your view model.
My solution to this issue is;
create a new variable(ViewModel) for the layout (fragment or activity layout)
in your activity or fragment get the instance of your viewModel with ViewModelProviders
hold the data which fills your recyclerView in MutableLiveData and observe it and fill the adapter of recyclerView with the value you observed
here you mut be careful not to create adapter instance in observe method.
if you create it in observe method, it will make leaks

How to use one RecyclerView adapter for objects of different types using generics?

I have a RecyclerView which I want to be populated with String objects sometimes & with Product objects some other time. So I started creating its manager adapter this way:
// BaseSearchAdapter is the class that contains the 'List<T> mItems' member variable
public class SearchAdapter<T> extends BaseSearchAdapter<SearchAdapter.ViewHolder, T> {
private Context mContext;
public SearchAdapter(Context context, List<T> items) {
mContext = context;
mItems = new ArrayList<>(items);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
T item = mItems.get(position);
holder.bind(item);
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView textLabel;
public ViewHolder(View v) {
}
public void bind(T item) {
textLabel.setText(...); // How to handle T ?
}
}
}
where T could be String or Product according to the plan.
My question is how can I appropriately bind the data (whether it's a String or a Product) object to its corresponding view in this situation? Or is there a better way to handle this ?
// BaseSearchAdapter is the class that contains the 'List<T> mItems' member variable
public class SearchAdapter<T> extends BaseSearchAdapter<SearchAdapter.ViewHolder<T>, T> {
private Context mContext;
private ViewHolderBinder<T> mBinder;
public SearchAdapter(Context context, List<T> items, ViewHolderBinder<T> binder) {
mContext = context;
mItems = new ArrayList<>(items);
mBinder = binder;
}
#Override
public void onBindViewHolder(ViewHolder<T> holder, int position) {
T item = mItems.get(position);
holder.bind(item);
}
public static class ViewHolder<T> extends RecyclerView.ViewHolder {
ViewHolderBinder<T> mBinder;
TextView textLabel;
public ViewHolder(View v, ViewHolderBinder<T> binder) {
textLabel = (TextView)v.findViewById(R.id.text_label);
this.mBinder = binder;
}
public void bind(T item) {
binder.bind(this, item);
}
}
public interface ViewHolderBinder<T> {
void bind(ViewHolder<T> viewHolder, T item);
}
public static class StringViewHolderBinder implements ViewHolderBinder<String> {
#Override
public void bind(ViewHolder<String> viewHolder, String item) {
viewHolder.textLabel.setText(item);
}
}
public static class ProductViewHolderBinder implements ViewHolderBinder<Product> {
#Override
public void bind(ViewHolder<Product> viewHolder, Product item) {
viewHolder.textLabel.setText(item.getName());
}
}
}
What I do on my projects is create a class BaseRecyclerAdapter that has all of my common operations. Then for most adapters all I have to define is the ViewHolder and the layout.
UPDATE
As Requested I posted a fuller version of my BaseRecyclerAdapter (it varies a bit based upon project need). Also include is a simple gesture callback that allows you to easily enable swipe to remove or drag to reorder operations.
NOTE: This version updates how the recycler item layouts are inflated. I now prefer to inflate the in the BaseRecyclerAdapter.ViewHolder constructor allowing the layout to be specified in the extending ViewHolder's constructor.
Example Base Adapter
public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<BaseRecyclerAdapter.ViewHolder> {
private final List<T> items = new ArrayList<>();
OnItemSelectedListener<T> onItemSelectedListener = SmartNull.create(OnItemSelectedListener.class);
public BaseRecyclerAdapter setOnItemSelectedListener(OnItemSelectedListener<T> onItemSelectedListener) {
if (onItemSelectedListener == null) {
this.onItemSelectedListener = SmartNull.create(OnItemSelectedListener.class);
} else {
this.onItemSelectedListener = onItemSelectedListener;
}
return this;
}
public boolean isEmpty() {
return items.isEmpty();
}
public void setItems(List<T> items) {
this.items.clear();
this.items.addAll(items);
notifyDataSetChanged();
}
public void addItems(T... items) {
addItems(Arrays.asList(items));
}
public void addItems(List<T> items) {
int startPosition = this.items.size() - 1;
this.items.addAll(items);
notifyItemRangeInserted(startPosition, items.size());
}
public void removeItem(int position) {
T item = items.remove(position);
if (itemRemovedListener != null) {
itemRemovedListener.onItemRemoved(item);
}
notifyItemRemoved(position);
}
public void removeItem(T t) {
int index = items.indexOf(t);
if (index >= 0) {
removeItem(index);
}
}
public void addItem(T item) {
items.add(item);
notifyItemInserted(getItemCount() - 1);
}
public void moveItem(int startPosition, int targetPosition) {
if (startPosition < targetPosition) {
for (int i = startPosition; i < targetPosition; i++) {
Collections.swap(items, i, i + 1);
}
} else {
for (int i = startPosition; i > targetPosition; i--) {
Collections.swap(items, i, i - 1);
}
}
notifyItemMoved(startPosition, targetPosition);
}
public List<T> getItems() {
return new ArrayList<>(items);
}
public void setItemAt(int position, T item){
items.set(position, item);
notifyItemChanged(position);
}
public void refreshItem(T item) {
int i = items.indexOf(item);
if (i >= 0) {
notifyItemChanged(i);
}
}
protected void setItemWithoutUpdate(int position, T item){
items.set(position, item);
}
public int indexOf(T t) {
return items.indexOf(t);
}
#SuppressWarnings("unchecked")
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.bindItemAt(getItemAt(position), position);
}
#Override
public int getItemCount() {
return items.size();
}
public T getItemAt(int position) {
return items.get(position);
}
private void onItemSelected(int position) {
if (isValidPosition(position)) {
onItemSelectedListener.onItemSelected(getItemAt(position));
}
}
boolean isValidPosition(int position) {
return position >=0 && position < items.size();
}
public abstract class ViewHolder<T> extends RecyclerView.ViewHolder implements View.OnClickListener {
public ViewHolder(ViewGroup parent, #LayoutRes int layoutId) {
super(LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false));
itemView.setOnClickListener(this);
}
public ViewHolder(View view) {
super(view);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
onItemSelected(getAdapterPosition());
}
public abstract void bindItemAt(T t, int position);
}
public interface OnItemSelectedListener<T> {
void onItemSelected(T t);
}
}
Example Implementation
public class ExampleAdapter extends com.stratospherequality.mobileworkforce.modules.common.BaseRecyclerAdapter<Long> {
#Override
protected RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(parent);
}
private class ViewHolder extends RecyclerViewHolder<Long> {
TextView text;
public ViewHolder(ViewGroup parent) {
super(parent, R.layout.row_my_layout);
// I typically use ButterKnife here but this works as well
text = (TextView) itemView.findViewById(R.id.text);
}
#Override
public void setItem(Long value, int position) {
text.setText("#" + value);
}
}
}
Base GestureCallback
public class AdapterGestureCallback extends ItemTouchHelper.SimpleCallback {
public interface OnRemoveItemCallback<T> {
void onRemoveItem(BaseRecyclerAdapter<T> adapter, T t);
}
public enum Direction {
UP(ItemTouchHelper.UP),
DOWN(ItemTouchHelper.DOWN),
LEFT(ItemTouchHelper.LEFT),
RIGHT(ItemTouchHelper.RIGHT),
START(ItemTouchHelper.START),
END(ItemTouchHelper.END);
public final int value;
Direction(int value) {
this.value = value;
}
}
private final BaseRecyclerAdapter adapter;
private OnRemoveItemCallback onRemoveItemCallback;
private boolean enabled = true;
public AdapterGestureCallback(BaseRecyclerAdapter adapter) {
super(0, 0);
this.adapter = adapter;
}
public AdapterGestureCallback setOnRemoveItemCallback(OnRemoveItemCallback onRemoveItemCallback) {
this.onRemoveItemCallback = onRemoveItemCallback;
return this;
}
public AdapterGestureCallback setEnabled(boolean enabled) {
this.enabled = enabled;
return this;
}
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
adapter.moveItem(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int position = viewHolder.getAdapterPosition();
if (onRemoveItemCallback == null){
adapter.removeItem(position);
} else {
onRemoveItemCallback.onRemoveItem(adapter, adapter.getItemAt(position));
}
}
public AdapterGestureCallback withDragDirections(Direction... dragDirections) {
setDefaultDragDirs(valueFor(dragDirections));
return this;
}
public AdapterGestureCallback withSwipeDirections(Direction... swipeDirections) {
setDefaultSwipeDirs(valueFor(swipeDirections));
return this;
}
#Override
public boolean isItemViewSwipeEnabled() {
return enabled;
}
#Override
public boolean isLongPressDragEnabled() {
return enabled;
}
public int valueFor(Direction... directions) {
int val = 0;
for (Direction d : directions) {
val |= d.value;
}
return val;
}
public AdapterGestureCallback attach(RecyclerView recyclerView) {
new ItemTouchHelper(this).attachToRecyclerView(recyclerView);
return this;
}
}
GestureCallback with swiping
new AdapterGestureCallback(adapter)
.withSwipeDirections(AdapterGestureCallback.Direction.LEFT, AdapterGestureCallback.Direction.RIGHT)
.setOnRemoveItemCallback(this)
.attach(recyclerView);
Can use generic for Holder like this:
public abstract class ActionBarAdapter<T,VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {
private Context mContext;
public SearchAdapter(Context context, List<T> items) {
mContext = context;
mItems = new ArrayList<>(items);
}
}
The approach that, for example, ArrayAdapter<T> uses is to call toString() on whatever T you pass. This will of course work for a String, and you'll have to implement toString() in your Product to return a meaningful representation.

Google Glass Fullscreen Custom Layout Cards

I have an issue. Since the Card class is deprecated and the CardBuilder.EMBED_INSIDE is fairly limited. The only option is to use a custom View. I'd also like to use the CardScrollView and the CardScrollAdapter.
visit Google Glass Immersion Custom Layout without CardBuilder.Layout.EMBED_INSIDE
But my problem is, I can't have multiple views.
Here is MyCustomViewClass:
public class MyCustomView extends FrameLayout{
public MyCustomView (Context context) {
super(context);
initView();
}
private void initView()
{
View view = inflate(getContext(), R.layout.imageview, null);
addView(view);
View view2 = inflate(getContext(), R.layout.secondview, null);
addView(view2);
}
And thats my main activity class:
public class InspectionActivity extends Activity {
private CardScrollView mCardScroller;
private GestureDetector mGestureDetector;
private View mView;
private CardScrollView _cardScroller;
private ArrayList<View> _cardsList;
private MyCustomView _myView;
protected List<CardBuilder> mCards;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
createCards();
_cardsList = new ArrayList<View>();
_myView= new MyCustomView (this);
_cardsList.add(_myView);
_cardScroller = new CardScrollView(this) ;
MainCardsScrollAdapter adapter = new MainCardsScrollAdapter(_cardsList);
_cardScroller.setAdapter(adapter);
_cardScroller.activate();
setContentView(_cardScroller);
}
private void createCards() {
mCards = new ArrayList<CardBuilder>();
}
public class MainCardsScrollAdapter extends CardScrollAdapter
{
ArrayList<View> _cardsList;
public MainCardsScrollAdapter(ArrayList<View> cardsList)
{
_cardsList = cardsList;
}
#Override
public int getCount() {
return _cardsList.size();
}
#Override
public Object getItem(int i) {
return _cardsList.get(i);
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
return _cardsList.get(i);
}
#Override
public int getPosition(Object o) {
return _cardsList.indexOf(o);
}
#Override
public int getViewTypeCount() {
return CardBuilder.getViewTypeCount();
}
#Override
public int getItemViewType(int position){
return 2;//should be changed, it's just an example
}
} }
Alright so from your post I'm guessing it's only inflating one of your layouts into the CardScrollView try the following.
Create a adapter class that looks something like this
public class mainAdapter extends CardScrollAdapter {
private List<CustomCard> mCards;
private LayoutInflater inflater;
public mainAdapter(List<CustomCard> cards, LayoutInflater inf)
{
this.mCards = cards;
this.inflater = inf;
}
#Override
public int getCount() {
return mCards.size();
}
#Override
public Object getItem(int i) {
return mCards.get(i);
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
int card = mCards.get(i).getLayout();
view = inflater.inflate(card, viewGroup, false);
return view;
}
#Override
public int getPosition(Object o) {
return this.mCards.indexOf(o);
}
}
my CustomCard class looks like this, you could just use a List<Integer> instead tho
public class CustomCard {
public int getLayout() {
return layout;
}
public int layout;
public CustomCard(int layout)
{
this.layout = layout;
}
}
In your activity class create and fill a list with the desired layouts and pass them to your adapter as follows.
in the onCreate()
CreateCards();
mCardScroller = new CardScrollView(this);
mCardScroller.setAdapter(new mainAdapter(mCards, getLayoutInflater()));
and the CreateCards() method would look something like this
public void CreateCards() {
mCards.add(new CustomCard(R.layout.firstview));
mCards.add(new CustomCard(R.layout.secondview));
mCards.add(new CustomCard(R.layout.thirdview));
}
Hope this is of use for you

Categories