I have tried using CardView in ViewPager and everytime I swipe left/right on CardView it goes to the next screen. I want the card to delete itself then. Currently as a standalone both are working fine but when I combine then only viewpager is working and not cardswipe dismiss.
I tried to disable ViewPager with the code below but this code also disables CardView swipe gestures. How can I make only CardView to have gesture and when you swipe in between 2 cards then its should have ViewPager as its not connected to card element.
Or disable ViewPager completely and use it as buttons and enable swipe on CardView. I really appreciate any help. Thanks in Advance.
FYI: I have tried android_horizontal_listview in ViewPager and that works fine and exactly like this.
For ViewPager:
mPager.setOnTouchListener(new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
return true;
}
});
For CardView:
SwipeableRecyclerViewTouchListener swipeTouchListener =
new SwipeableRecyclerViewTouchListener(mRecyclerView,
new SwipeableRecyclerViewTouchListener.SwipeListener() {
#Override
public boolean canSwipe(int position) {
return true;
}
#Override
public void onDismissedBySwipeLeft(RecyclerView recyclerView, int[] reverseSortedPositions) {
for (int position : reverseSortedPositions) {
mItems.remove(position);
mAdapter.notifyItemRemoved(position);
}
mAdapter.notifyDataSetChanged();
}
#Override
public void onDismissedBySwipeRight(RecyclerView recyclerView, int[] reverseSortedPositions) {
for (int position : reverseSortedPositions) {
mItems.remove(position);
mAdapter.notifyItemRemoved(position);
}
mAdapter.notifyDataSetChanged();
}
});
mRecyclerView.addOnItemTouchListener(swipeTouchListener);
Mainactivity.java
public class MainActivity extends Activity implements ActionBar.TabListener {
ViewPager vp;
View viewpager_layout_1;
View viewpager_layout_2;
View viewpager_layout_3;
ActionBar.Tab tab_1;
ActionBar.Tab tab_2;
ActionBar.Tab tab_3;
ActionBar bar;
/////
String jsonstring1;
CardViewAdapter spinnerArray;
ImageLoader imageLoader = ImageLoader.getInstance();//
DisplayImageOptions options;
ArrayList<HashMap<String, String>> array_list1;
RecyclerView recyclerView;
RelativeLayout re1;
private Context mContext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
mContext = this;
viewpager_layout_1 = new View(mContext);
viewpager_layout_1 = getLayoutInflater().inflate(R.layout.sample1, null);
viewpager_layout_3 = new View(mContext);
viewpager_layout_3 = getLayoutInflater().inflate(R.layout.sample2, null);
viewpager_layout_2 = new View(mContext);
viewpager_layout_2 = getLayoutInflater().inflate(R.layout.sample3, null);
vp = (ViewPager) findViewById(R.id.vp);
bar = getActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setDisplayShowTitleEnabled(false);
bar.setDisplayShowHomeEnabled(false);
Vector<View> pages = new Vector<View>();
pages.add(viewpager_layout_1);
pages.add(viewpager_layout_3);
pages.add(viewpager_layout_2);
CustomPagerAdapter adapter = new CustomPagerAdapter(mContext, pages);
vp.setAdapter(adapter);
vp.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
bar.setSelectedNavigationItem(position);
}
});
tab_1 = bar.newTab();
tab_1.setCustomView(R.layout.tab_layout_1);
tab_1.setTabListener(this);
bar.addTab(tab_1);
tab_2 = bar.newTab();
tab_2.setCustomView(R.layout.tab_layout_2);
tab_2.setTabListener(this);
bar.addTab(tab_2);
tab_3 = bar.newTab();
tab_3.setCustomView(R.layout.tab_layout_3);
tab_3.setTabListener(this);
bar.addTab(tab_3);
////
imageLoader.init(ImageLoaderConfiguration.createDefault(MainActivity.this));
jsonstring1 = "[{\"category\":\"1\",\"no\":\"1\",\"image\":\"http://upload.wikimedia.org/wikipedia/commons/c/c3/Jordan_by_Lipofsky_16577.jpg\"},{\"category\":\"2\",\"no\":\"2\",\"image\":\"http://upload.wikimedia.org/wikipedia/commons/thumb/9/96/Basketball_World_Cup_2014.jpg/800px-Basketball_World_Cup_2014.jpg\"},{\"category\":\"3\",\"no\":\"3\",\"image\":\"http://upload.wikimedia.org/wikipedia/commons/4/4e/Basketball_Goal.jpg\"},{\"category\":\"4\",\"no\":\"4\",\"image\":\"http://upload.wikimedia.org/wikipedia/commons/1/10/Basketball_through_hoop.jpg\"}]";
//////////
array_list1 = new ArrayList<HashMap<String, String>>();
JSONArray arr = null;
try {
arr = new JSONArray(jsonstring1);
for (int i = 0; i < arr.length(); i++) {
JSONObject e1 = arr.getJSONObject(i);
String category = e1.getString("category").trim();
String no = e1.getString("no").trim();
String image = e1.getString("image").trim();
HashMap<String, String> map = new HashMap<String, String>();
map.put("category", category);
map.put("no", no);
map.put("image", image);
// adding HashList to ArrayList
array_list1.add(map);
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
OnItemTouchListener itemTouchListener = new OnItemTouchListener() {
#Override
public void onCardViewTap(View view, int position) {
Toast.makeText(MainActivity.this, "Tapped " + array_list1.get(position), Toast.LENGTH_SHORT).show();
}
#Override
public void onButton1Click(View view, int position) {
Toast.makeText(MainActivity.this, "Clicked Button1 in " + array_list1.get(position), Toast.LENGTH_SHORT).show();
}
#Override
public void onButton2Click(View view, int position) {
Toast.makeText(MainActivity.this, "Clicked Button2 in " + array_list1.get(position), Toast.LENGTH_SHORT).show();
}
};
spinnerArray = new CardViewAdapter(itemTouchListener, MainActivity.this, array_list1);
recyclerView = (RecyclerView) viewpager_layout_3.findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
SlideInBottomAnimationAdapter alphaAdapter = new SlideInBottomAnimationAdapter(spinnerArray);
ScaleInAnimationAdapter alphaAdapter2 = new ScaleInAnimationAdapter(alphaAdapter);
final AlphaInAnimationAdapter alphaAdapter3 = new AlphaInAnimationAdapter(alphaAdapter2);
alphaAdapter3.setDuration(500);
alphaAdapter3.setFirstOnly(true);
recyclerView.setAdapter(alphaAdapter3);
final SwipeableRecyclerViewTouchListener swipeTouchListener =
new SwipeableRecyclerViewTouchListener(recyclerView,
new SwipeableRecyclerViewTouchListener.SwipeListener() {
#Override
public boolean canSwipe(int position) {
return true;
}
#Override
public void onDismissedBySwipeLeft(RecyclerView recyclerView, int[] reverseSortedPositions) {
for (int position : reverseSortedPositions) {
// mItems.remove(position);
Toast.makeText(MainActivity.this, array_list1.get(position) + " swiped left", Toast.LENGTH_SHORT).show();
array_list1.remove(position);
alphaAdapter3.notifyItemRemoved(position);
}
alphaAdapter3.notifyDataSetChanged();
}
#Override
public void onDismissedBySwipeRight(RecyclerView recyclerView, int[] reverseSortedPositions) {
for (int position : reverseSortedPositions) {
//
Toast.makeText(MainActivity.this, array_list1.get(position) + " swiped right", Toast.LENGTH_SHORT).show();
array_list1.remove(position);
alphaAdapter3.notifyItemRemoved(position);
}
alphaAdapter3.notifyDataSetChanged();
}
});
recyclerView.addOnItemTouchListener(swipeTouchListener);
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
// Toast.makeText(getBaseContext(), tab.toString(), 5).show();
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
// Toast.makeText(getBaseContext(), tab.toString(), 5).show();
vp.setCurrentItem(tab.getPosition());
if (tab.getPosition() == 2) {
tab_2.setCustomView(null);
tab_2.setCustomView(R.layout.tab_layout_2);
tab_1.setCustomView(null);
tab_1.setCustomView(R.layout.tab_layout_1);
tab_3.setCustomView(null);
tab_3.setCustomView(R.layout.tab_layout_33);
} else if (tab.getPosition() == 1) {
tab_2.setCustomView(null);
tab_2.setCustomView(R.layout.tab_layout_22);
tab_1.setCustomView(null);
tab_1.setCustomView(R.layout.tab_layout_1);
tab_3.setCustomView(null);
tab_3.setCustomView(R.layout.tab_layout_3);
} else if (tab.getPosition() == 0) {
tab_1.setCustomView(null);
tab_1.setCustomView(R.layout.tab_layout_11);
if (tab_2 != null) {
tab_2.setCustomView(null);
tab_2.setCustomView(R.layout.tab_layout_2);
}
if (tab_3 != null) {
tab_3.setCustomView(null);
tab_3.setCustomView(R.layout.tab_layout_3);
}
}
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
// Toast.makeText(getBaseContext(), tab.toString(), 5).show();
}
public interface OnItemTouchListener {
// this will disallow the touch request for parent scroll on touch of child view
/**
* Callback invoked when the user Taps one of the RecyclerView items
*
* #param view the CardView touched
* #param position the index of the item touched in the RecyclerView
*/
public void onCardViewTap(View view, int position);
/**
* Callback invoked when the Button1 of an item is touched
*
* #param view the Button touched
* #param position the index of the item touched in the RecyclerView
*/
public void onButton1Click(View view, int position);
/**
* Callback invoked when the Button2 of an item is touched
*
* #param view the Button touched
* #param position the index of the item touched in the RecyclerView
*/
public void onButton2Click(View view, int position);
}
public class CustomPagerAdapter extends PagerAdapter {
private final Context mContext;
private final Vector<View> pages;
public CustomPagerAdapter(Context context, Vector<View> pages) {
this.mContext = context;
this.pages = pages;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
View page = pages.get(position);
container.addView(page);
return page;
}
#Override
public int getCount() {
return pages.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
public class CardViewAdapter extends RecyclerView.Adapter<CardViewAdapter.ViewHolder> {
ArrayList<HashMap<String, String>> d;
Activity a;
private List<String> cards;
private OnItemTouchListener onItemTouchListener2;
public CardViewAdapter(OnItemTouchListener onItemTouchListener, Activity a, ArrayList<HashMap<String, String>> d) {
// this.cards = cards;
this.onItemTouchListener2 = onItemTouchListener;
this.a = a;
this.d = d;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_view_layout, viewGroup, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
// viewHolder.title.setText(cards.get(i));
HashMap<String, String> item = d.get(i);
viewHolder.title.setText(item.get("category"));
imageLoader.displayImage(item.get("image"), viewHolder.im2);
}
#Override
public int getItemCount() {
// return d == null ? 0 : d.size();
return (null != d ? d.size() : 0);
// return d.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
MotionEvent motionEvent;
private int mSlop;
private int mMinFlingVelocity;
private int mMaxFlingVelocity;
private long mAnimationTime;
// Fixed properties
// private RecyclerView mRecyclerView;
private SwipeableRecyclerViewTouchListener.SwipeListener mSwipeListener;
// Transient properties
private int mViewWidth = 1; // 1 and not 0 to prevent dividing by zero
private int mDismissAnimationRefCount = 0;
private float mAlpha;
private float mDownX;
private float mDownY;
private boolean mSwiping;
private int mSwipingSlop;
private VelocityTracker mVelocityTracker;
private int mDownPosition;
private int mAnimatingPosition = ListView.INVALID_POSITION;
private View mDownView;
private boolean mPaused;
private float mFinalDelta;
///
private TextView title;
private Button button1;
private Button button2;
private ImageView im2;
public ViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.card_view_title);
im2 = (ImageView) itemView.findViewById(R.id.imageView);
}
}
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/relativelayout_1">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:id="#+id/linearlayout_1"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="#+id/vp"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
</LinearLayout>
</RelativeLayout>
sample2.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/re1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
To solve this issue I used an ItemTouchHelper provided by Android to easily swipe to delete an item from a RecyclerView.
Please see implementation below:
MainActivity:
Here I have the implementation of the ViewPager and it's child Fragments.
package za.co.gadgetgirl.testcardpager;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
}
private void setupViewPager(ViewPager viewPager) {
Adapter adapter = new Adapter(getSupportFragmentManager());
Frag1 frag1 = new Frag1();
Frag2 frag2 = new Frag2();
Frag3 frag3 = new Frag3();
adapter.addFragment(frag1, "frag1");
adapter.addFragment(frag2, "frag2");
adapter.addFragment(frag3, "frag3");
viewPager.setAdapter(adapter);
}
static class Adapter extends FragmentPagerAdapter {
private final List<Fragment> mFragments = new ArrayList<>();
private final List<String> mFragmentTitles = new ArrayList<>();
public Adapter(FragmentManager fm) {
super(fm);
}
public void addFragment(Fragment fragment, String title) {
mFragments.add(fragment);
mFragmentTitles.add(title);
}
#Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
#Override
public int getCount() {
return mFragments.size();
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitles.get(position);
}
}
}
Frag1:
On this Fragment I have a RecyclerView that has an ItemTouchHelper attached. The ItemTouchHelper listens for the onSwiped(...) method that is defined in the SimpleCallback interface and I just remove the swiped item in this method.
package za.co.gadgetgirl.testcardpager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class Frag1 extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.frag1, container, false);
final RecyclerView rv = (RecyclerView) v.findViewById(R.id.rv);
final LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rv.setLayoutManager(llm);
final RVAdapter rvAdapter = new RVAdapter(Person.initializeData());
rv.setAdapter(rvAdapter);
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0,ItemTouchHelper.LEFT|ItemTouchHelper.RIGHT) {
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
rvAdapter.removeItem(viewHolder.getAdapterPosition());
}
});
itemTouchHelper.attachToRecyclerView(rv);
return v;
}
}
RVAdapter:
public class RVAdapter extends RecyclerView.Adapter<RVAdapter.PersonViewHolder> {
//...implementation...
public void removeItem(int position) {
persons.remove(position);
notifyItemRemoved(position);
}
}
To use the ItemTouchHelper, you will need the appcompat-v7:22.2.0 dependency and above defined in your app gradle file.
I haven't use SwipeableRecyclerView before so I cannot really say much. I have a problem same as you before. I solve it by handling onTouch event of the base container of fragment (such as LinearLayout,RelativeLayout) and it work for me. Why don't you try this solution and get back to us
For the use case that you are describing, I don't think that ViewPager is the class that you want to use to get your swipe action. It seems to me that the combination of CoordinatorLayout and SwipeDismissBehavior is more appropriate.
EDIT:
See my solution below:
Layout XML:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.CardView
android:id="#+id/cardView"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.CardView>
</android.support.design.widget.CoordinatorLayout>
Activity:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CardView cardView = (CardView) findViewById(R.id.cardView);
SwipeDismissBehavior<CardView> behavior = new SwipeDismissBehavior();
behavior.setSwipeDirection(SwipeDismissBehavior.SWIPE_DIRECTION_START_TO_END);
behavior.setListener(new SwipeDismissBehavior.OnDismissListener() {
#Override
public void onDismiss(View view) {
finish(); // close activity if desired
}
#Override
public void onDragStateChanged(int state) {
}
});
((CoordinatorLayout.LayoutParams) cardView.getLayoutParams()).setBehavior(behavior);
}
}
Also, here are some examples of using the CoordinatorLayout:
How to use SwipeDismissBehavior.OnDismissListener on RecyclerView
CoordinatorLayout using the ViewPager's RecyclerView
https://lab.getbase.com/introduction-to-coordinator-layout-on-android/
http://android-developers.blogspot.co.uk/2015/05/android-design-support-library.html
I haven't been able to find many examples using SwipeDismissBehavior specifically, but the concepts are similar to the links above.
Alternatively, you may also be able to follow the suggestions of a similar post:
Android swipe layout to dismiss to get the results you desire.
Hope this helps.
Related
FragmentClass
public class BlankFragment extends Fragment {
//FragmentClass constructor with no parameter
public BlankFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
**Inflating recyclerView with Dummy data i want to load data from firebase here
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_blank, container, false);
//FInding recyclerViewByid
RecyclerView rv = (RecyclerView) rootView.findViewById(R.id.rv_recycler_view);
rv.setHasFixedSize(true);
// i have added dummy data into adapter but want toadd data from firebaseDatabase into Myadapter
MyAdapter adapter = new MyAdapter(new String[] {
"test one", // i have hardcoded these data
"test two", // but i want data from firebase to go here
"test three",
"test four",
"test five",
"test six",
"test seven"
});
rv.setAdapter(adapter); //Setting adapter
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rv.setLayoutManager(llm);
return rootView; // returning rootView
}
}
MainActivity
#MainActivity contains 3TabLayouts
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private final String TAG = "SOMETHING";
private ImageView image;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Firebase.setAndroidContext(this);
//TabLayout
TabLayout tabLayout = (TabLayout)findViewById(R.id.tab_layout);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Get the ViewPager and set it's PagerAdapter so that it can display items
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
PagerAdapter pagerAdapter =
new PagerAdapter(getSupportFragmentManager(), MainActivity.this);
viewPager.setAdapter(pagerAdapter);
// Give the TabLayout the ViewPager
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
int position = tab.getPosition();
if (position == 1)
Log.d(TAG, "onTabSelected: "); //call some method
else if (position == 2)
Log.d(TAG, "onTabSelected: "); //call some method
else
Log.d(TAG, "onTabSelected: "); //call some method
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
//SettingViewpagers
tabLayout.setupWithViewPager(viewPager);
// Iterate over all tabs and set the custom view
for (int i = 0; i < tabLayout.getTabCount(); i++) {
TabLayout.Tab tab = tabLayout.getTabAt(i);
tab.setCustomView(pagerAdapter.getTabView(i));
}
}
#Override
public void onResume() {
super.onResume();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
class PagerAdapter extends FragmentPagerAdapter {
String tabTitles[] = new String[] {
"NOTICE", // tab1 header
"FEED", // tab2 header
"RESULT" // tab3 header
};
Context context;
public PagerAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
}
#Override
public int getCount() {
return tabTitles.length;
}
#Override
public Fragment getItem(int position) {
// 3 tab classes
want to load different data in all 3 tabs
all data should be loaded from firebase
switch (position) {
case 0:
return new BlankFragment(); //FragementClass 1
case 1:
return new BlankFragment(); //FragmentClass 2
case 2:
return new SomeFragment(); //FragmentClass 3
}
return null;
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
// inflate some value should inflate some custom view here
public View getTabView(int position) {
View tab = LayoutInflater.from(MainActivity.this).inflate(R.layout.custom_tab, null);
TextView tv = (TextView) tab.findViewById(R.id.custom_text);
tv.setText(tabTitles[position]);
return tab;
}
}
}
#Adapter class
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.ScaleAnimation;
import android.widget.TextView;
public class MyAdapter extends RecyclerView.Adapter < MyAdapter.MyViewHolder > {
private String[] mDataset;
private final static int FADE_DURATION = 1000;
public MyAdapter() {
}
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class MyViewHolder extends RecyclerView.ViewHolder {
public CardView mCardView;
public TextView mTextView;
public MyViewHolder(View v) {
super(v);
mCardView = (CardView) v.findViewById(R.id.card_view);
mTextView = (TextView) v.findViewById(R.id.tv_text);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(String[] myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_item, parent, false);
// set the view's size, margins, paddings and layout parameters
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.mTextView.setText((CharSequence) mDataset[position]);
setScaleAnimation(holder.mCardView);
// setFadeAnimation(holder.mTextView);
;
}
//adding simple scale animation to CardView
private void setScaleAnimation(View view) {
ScaleAnimation anim = new ScaleAnimation(0.0 f, 1.0 f, 0.0 f, 1.0 f, Animation.RELATIVE_TO_SELF, 0.5 f, Animation.RELATIVE_TO_SELF, 0.5 f);
anim.setDuration(FADE_DURATION);
view.startAnimation(anim);
}
//Adding Fade animation
private void setFadeAnimation(View view) {
AlphaAnimation anim = new AlphaAnimation(0.0 f, 1.0 f);
anim.setDuration(FADE_DURATION);
view.startAnimation(anim);
}
#Override
public int getItemCount() {
return mDataset.length;
}
}
I'm trying to achieve the following:
I have an item view that displays a ViewPager with images of that item and some other information. When the user taps one of the ViewPager's images, I'd like there to be a transition between the image on the first screen and the same image on another ViewPager in a new Activity.
So far, I've managed to get the basic functionality working but there are a couple of key things that do not work as expected:
The transition from ViewPager A to the second Activity with ViewPager B only works when tapping the image at index 0 or 1 in ViewPager A.
There is a return animation when pressing back from ViewPager B in the new Activity - as long as I do not swipe to another image so the transition is from the full screen mode I'd be displaying in ViewPager B to the same image in ViewPager A. When swiping to another image and pressing back - there's no animation.
Number 1 is happening because the first couple of pages of the ViewPager are instantiated when it's created so the instantiateItem method of the Adapter gets called for each of these and this is where I'm setting the transitionName.
This is proven by the fact that calling this on the ViewPager makes that issue go away and the entry animation works on all screens:
detailPager.setOffscreenPageLimit(largeNumber);
Obviously this is unsustainable, I'd much rather not have such a high off screen limit.
My question is twofold:
How do I achieve the animation for each ViewPager item without keeping all the pages in memory via the above hack?
How can I ensure that a return transition takes place when swiping to another page in ViewPager B?
I've included my code below:
ItemActivity
public class ItemActivity extends AppCompatActivity {
private static final String ITEM_TAG = "item_tag";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_with_fragment_container);
ButterKnife.bind(this);
if (savedInstanceState == null) {
attachFragment();
}
}
private void attachFragment() {
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, ItemFragment.newInstance(), ITEM_TAG)
.commit();
}
#Override
public void onActivityReenter(int resultCode, Intent data) {
super.onActivityReenter(resultCode, data);
ItemFragment fragment = (ItemFragment) getSupportFragmentManager().findFragmentByTag(ITEM_TAG);
if (fragment != null) {
fragment.onReenter(data);
}
}}
ItemFragment - This is where the first ViewPager is
public class ItemFragment extends Fragment implements MyAdapter.MyListener {
public static final String EXTRA_STARTING_ALBUM_POSITION = "extra_starting_item_position";
public static final String EXTRA_CURRENT_ALBUM_POSITION = "extra_current_item_position";
public static final String[] IMAGE_NAMES = {"One", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"};
private static final int FULL_SCREEN_CODE = 1234;
private Unbinder unbinder;
private Bundle tempReenterState;
private final SharedElementCallback callback = new SharedElementCallback() {
#Override
public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
if (tempReenterState != null) {
int startingPosition = tempReenterState.getInt(EXTRA_STARTING_ALBUM_POSITION);
int currentPosition = tempReenterState.getInt(EXTRA_CURRENT_ALBUM_POSITION);
if (startingPosition != currentPosition) {
String newTransitionName = IMAGE_NAMES[currentPosition];
View newSharedElement = detailPager.findViewWithTag(newTransitionName);
if (newSharedElement != null) {
names.clear();
names.add(newTransitionName);
sharedElements.clear();
sharedElements.put(newTransitionName, newSharedElement);
}
}
tempReenterState = null;
} else {
View navigationBar = getActivity().findViewById(android.R.id.navigationBarBackground);
View statusBar = getActivity().findViewById(android.R.id.statusBarBackground);
if (navigationBar != null) {
names.add(navigationBar.getTransitionName());
sharedElements.put(navigationBar.getTransitionName(), navigationBar);
}
if (statusBar != null) {
names.add(statusBar.getTransitionName());
sharedElements.put(statusBar.getTransitionName(), statusBar);
}
}
}
};
private List<String> images = Arrays.asList("http://wowslider.com/sliders/demo-9/data/images/1293441583_nature_forest_morning_in_the_forest_015232_.jpg",
"http://wowslider.com/sliders/demo-18/data1/images/hongkong1081704.jpg",
"http://www.irishtimes.com/polopoly_fs/1.2614603.1461003507!/image/image.jpg_gen/derivatives/box_620_330/image.jpg",
"http://weknowyourdreams.com/images/sky/sky-05.jpg");
#BindView(R.id.detail_pager)
ViewPager detailPager;
public static ItemFragment newInstance() {
return new ItemFragment();
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_image_detail, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ActivityCompat.setExitSharedElementCallback(getActivity(), callback);
detailPager.setAdapter(new MyAdapter(getActivity(), images, this));
}
#Override
public void goFullScreen(final int position, View view) {
Intent intent = FullScreenActivity.newIntent(getActivity(), position, images);
startActivityForResult(intent, FULL_SCREEN_CODE, ActivityOptions.makeSceneTransitionAnimation(getActivity(), view, view.getTransitionName()).toBundle());
}
public void onReenter(Intent data) {
tempReenterState = new Bundle(data.getExtras());
int startingPosition = tempReenterState.getInt(EXTRA_STARTING_ALBUM_POSITION);
int currentPosition = tempReenterState.getInt(EXTRA_CURRENT_ALBUM_POSITION);
if (startingPosition != currentPosition) {
detailPager.setCurrentItem(currentPosition, false);
}
ActivityCompat.postponeEnterTransition(getActivity());
detailPager.post(new Runnable() {
#Override
public void run() {
ActivityCompat.startPostponedEnterTransition(getActivity());
}
});
}
#Override
public void onDestroyView() {
super.onDestroyView();
if (unbinder != null) {
unbinder.unbind();
}
}
}
FullScreenActivity - This is where the second ViewPager is housed
public class FullScreenActivity extends AppCompatActivity {
private final SharedElementCallback callback = new SharedElementCallback() {
#Override
public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
if (mIsReturning) {
if (currentImage == null) {
// If shared element is null, then it has been scrolled off screen and
// no longer visible. In this case we cancel the shared element transition by
// removing the shared element from the shared elements map.
names.clear();
sharedElements.clear();
} else if (selectedIndex != mCurrentPosition) {
// If the user has swiped to a different ViewPager page, then we need to
// remove the old shared element and replace it with the new shared element
// that should be transitioned instead.
names.clear();
names.add(currentImage.getTransitionName());
sharedElements.clear();
sharedElements.put(currentImage.getTransitionName(), currentImage);
}
}
}
};
private boolean mIsReturning;
private int mCurrentPosition;
private int selectedIndex;
private static final String ARG_PRESELECTED_INDEX = "arg_preselected_index";
private static final String ARG_GALLERY_IMAGES = "arg_gallery_images";
public static final String KEY_SELECTED_IMAGE_INDEX = "key_selected_image_index";
public static final String KEY_RETAINED_IMAGES = "key_retained_images";
private static final int DEFAULT_SELECTED_INDEX = 0;
private List<String> images;
private ImageAdapter adapter;
private ImageView currentImage;
#BindView(R.id.full_screen_pager)
ViewPager viewPager;
public static Intent newIntent(#NonNull final Context context, final int selectedIndex, #NonNull final List<String> images) {
Intent intent = new Intent(context, FullScreenActivity.class);
intent.putExtra(ARG_PRESELECTED_INDEX, selectedIndex);
intent.putStringArrayListExtra(ARG_GALLERY_IMAGES, new ArrayList<>(images));
return intent;
}
#CallSuper
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_full_screen);
ButterKnife.bind(this);
ActivityCompat.postponeEnterTransition(this);
ActivityCompat.setExitSharedElementCallback(this, callback);
if (savedInstanceState == null) {
selectedIndex = getIntent().getIntExtra(ARG_PRESELECTED_INDEX, 0);
mCurrentPosition = selectedIndex;
images = getIntent().getStringArrayListExtra(ARG_GALLERY_IMAGES);
} else {
selectedIndex = savedInstanceState.getInt(KEY_SELECTED_IMAGE_INDEX);
images = savedInstanceState.getStringArrayList(KEY_RETAINED_IMAGES);
}
setupViewPager(selectedIndex, images);
}
private void setupViewPager(final int selectedIndex, List<String> images) {
adapter = new ImageAdapter(this, images);
viewPager.post(new Runnable() {
#Override
public void run() {
viewPager.setAdapter(adapter);
viewPager.setCurrentItem(selectedIndex);
viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
mCurrentPosition = position;
}
});
ActivityCompat.startPostponedEnterTransition(FullScreenActivity.this);
}
});
}
#Override
public void finishAfterTransition() {
mIsReturning = true;
Intent data = new Intent();
data.putExtra(EXTRA_STARTING_ALBUM_POSITION, selectedIndex);
data.putExtra(EXTRA_CURRENT_ALBUM_POSITION, viewPager.getCurrentItem());
setResult(RESULT_OK, data);
super.finishAfterTransition();
}
private class ImageAdapter extends PagerAdapter {
private final LayoutInflater layoutInflater;
private final List<String> images;
private ImageLoader<ImageView> imageLoader;
public ImageAdapter(Context context, List<String> images) {
this.imageLoader = new PicassoImageLoader(context);
this.images = images;
this.layoutInflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return images.size();
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
final ImageView imageView = (ImageView) layoutInflater.inflate(R.layout.full_image, container, false);
imageView.setTransitionName(IMAGE_NAMES[position]);
imageView.setTag(IMAGE_NAMES[position]);
imageLoader.loadImage(images.get(position), imageView);
container.addView(imageView);
return imageView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((ImageView) object);
}
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
currentImage = (ImageView) object;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
}
MyAdapter
public class MyAdapter extends PagerAdapter {
private final LayoutInflater layoutInflater;
private final List<String> images;
private final MyListener listener;
private ImageLoader<ImageView> imageLoader;
public interface MyListener {
void goFullScreen(final int position, View selected);
}
public MyAdapter(Context context, List<String> images, MyListener listener) {
this.imageLoader = new PicassoImageLoader(context);
this.layoutInflater = LayoutInflater.from(context);
this.images = images;
this.listener = listener;
}
#Override
public int getCount() {
return images.size();
}
#Override
public Object instantiateItem(ViewGroup container, final int position) {
final ImageView imageView = (ImageView) layoutInflater.inflate(R.layout.pager_item_image_thing, container, false);
imageView.setTransitionName(IMAGE_NAMES[position]);
imageView.setTag(IMAGE_NAMES[position]);
if (listener != null) {
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
listener.goFullScreen(position, imageView);
}
});
}
imageLoader.loadImage(images.get(position), imageView);
container.addView(imageView);
return imageView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((ImageView) object);
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
ImageLoader
public interface ImageLoader<T extends ImageView> {
void loadImage(#NonNull final Uri imageSource, #NonNull final T imageView);
void loadImage(#NonNull final String imageSource, #NonNull final T imageView);
}
PicassoImageLoader
public class PicassoImageLoader implements ImageLoader {
private final Context context;
public PicassoImageLoader(#NonNull final Context context) {
this.context = context;
}
#Override
public void loadImage(#NonNull Uri imageSource, #NonNull ImageView imageView) {
Picasso.with(context).load(imageSource).into(imageView);
}
#Override
public void loadImage(#NonNull String imageSource, #NonNull ImageView imageView) {
Picasso.with(context).load(imageSource).into(imageView);
}
}
XML Layouts
fragment_image_detail.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="#+id/detail_pager"
android:layout_width="match_parent"
android:layout_height="390dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="This is the title"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Some other descriptive text about things"/>
</LinearLayout>
layout_full_screen.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="#+id/full_screen_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
pager_item_thing.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager_item_image"
android:layout_width="match_parent"
android:layout_height="200dp"
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:layout_marginBottom="16dp" />
full_image.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/full_image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
I have a MainActivity and Three Fragments with recyclerViews inside the three fragments, the recyclerview contain two textviews, i want the user to click on the recyclerview and the text in should be passed on to the new activity, i am a little bit new so i would appreciate it if you can give me detailed code and some explanation.
I want to click on an item in the recyclerview and that should open a new activity, data(text) should be passed from the recyclerview to the new activity.
Here is my code for the HymnModel.java
public class HymnModel {
String title;
String song;
HymnModel(String title, String song){
this.title=title;
this.song=song;
}
public String getTitle() {return title;
}
public String getSong() {
return song;
}
}
Here is the code for ItemVeiwHolder.java
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
import com.tutorialsbuzz.recyclerview.R;
public class ItemViewHolder extends RecyclerView.ViewHolder {
public TextView title_textview;
public TextView song_textview;
public ItemViewHolder(View itemView) {
super(itemView);
itemView.setClickable(true);
title_textview = (TextView) itemView.findViewById(R.id.song_title);
song_textview = (TextView) itemView.findViewById(R.id.song);
}
public void bind(HymnModel hymnModel) {
title_textview.setText(hymnModel.getTitle());
song_textview.setText(hymnModel.getSong());
}
}
Here is my Adapter class
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.tutorialsbuzz.recyclerview.R;
import java.util.ArrayList;
import java.util.List;
public class RVAdapter extends RecyclerView.Adapter<ItemViewHolder> {
private List<HymnModel> mCountryModel;
private List<HymnModel> mOriginalCountryModel;
public RVAdapter(List<HymnModel> mCountryModel) {
this.mCountryModel = mCountryModel;
this.mOriginalCountryModel = mCountryModel;
}
#Override
public void onBindViewHolder(ItemViewHolder itemViewHolder, int i) {
final HymnModel model = mCountryModel.get(i);
itemViewHolder.bind(model);
}
#Override
public ItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_row, viewGroup, false);
return new ItemViewHolder(view);
}
#Override
public int getItemCount() {
return mCountryModel.size();
}
public void setFilter(List<HymnModel> countryModels){
mCountryModel = new ArrayList<>();
mCountryModel.addAll(countryModels);
notifyDataSetChanged();
}
}
Here is the code for one my fragments
public class TabOneFragment extends Fragment implements SearchView.OnQueryTextListener {
private RecyclerView recyclerview;
private List<HymnModel> mHymnModel;
private RVAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.tab_one_fragment, container, false);
recyclerview = (RecyclerView) view.findViewById(R.id.recyclerview);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerview.setLayoutManager(layoutManager);
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setHasOptionsMenu(true);
int numOfSongs = 32;
DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
int height = metrics.heightPixels;
int width = metrics.widthPixels;
String [] titles = {HymnTitles.hymnTitle1, HymnTitles.hymnTitle2, HymnTitles.hymnTitle3, HymnTitles.hymnTitle4, HymnTitles.hymnTitle5,
HymnTitles.hymnTitle6, HymnTitles.hymnTitle7, HymnTitles.hymnTitle8, HymnTitles.hymnTitle9, HymnTitles.hymnTitle10, HymnTitles.hymnTitle11,
HymnTitles.hymnTitle12};
String [] songs = {Hymns.hymn1.substring(width/5), Hymns.hymn2, Hymns.hymn3, Hymns.hymn4, Hymns.hymn5, Hymns.hymn6, Hymns.hymn7, Hymns.hymn8, Hymns.hymn9, Hymns.hymn10, Hymns.hymn11, Hymns.hymn12};
mHymnModel = new ArrayList<>();
for (int i = 0; i < titles.length; i++) {
mHymnModel.add(new HymnModel(i + "." + " " + titles[i], " " + songs[i]));
}
adapter = new RVAdapter(mHymnModel);
recyclerview.setAdapter(adapter);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_main, menu);
final MenuItem item = menu.findItem(R.id.action_search);
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
searchView.setOnQueryTextListener(this);
MenuItemCompat.setOnActionExpandListener(item,
new MenuItemCompat.OnActionExpandListener() {
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
// Do something when collapsed
adapter.setFilter(mHymnModel);
return true; // Return true to collapse action view
}
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
// Do something when expanded
return true; // Return true to expand action view
}
});
}
#Override
public boolean onQueryTextChange(String newText) {
final List<HymnModel> filteredModelList = filter(mHymnModel, newText);
adapter.setFilter(filteredModelList);
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
private List<HymnModel> filter(List<HymnModel> models, String query) {
query = query.toLowerCase();
final List<HymnModel> filteredModelList = new ArrayList<>();
for (HymnModel model : models) {
final String text = model.getSong().toLowerCase();
if (text.contains(query)) {
filteredModelList.add(model);
}
}
return filteredModelList;
}
}
My MainActivity
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
private int[] tabIcons = {
R.drawable.ic_action_person,
R.drawable.ic_action_group,
R.drawable.ic_action_call
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tablayout);
tabLayout.setupWithViewPager(viewPager);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new TabOneFragment(), "Tab 1");
adapter.addFragment(new TabTwoFragment(), "Tab 2");
adapter.addFragment(new TabThreeFragment(), "Tab 3");
viewPager.setAdapter(adapter);
}
}
And lastly my ViewPageAdapter
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
}
Thank You.
Create an interface
public interface OnHymnClickListener {
void onHymnClick(HymnModel hymnModel);
}
Pass the listener to the adapter
public class RVAdapter extends RecyclerView.Adapter<ItemViewHolder> {
private OnHymnClickListener listener;
public void setListener(OnHymnClickListener listener) {
this.listener = listener;
}
#Override
public void onBindViewHolder(ItemViewHolder itemViewHolder, int i) {
final HymnModel model = mCountryModel.get(i);
itemViewHolder.bind(model);
itemViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(listener != null) {
listener.onHymnClick(model);
}
}
});
}
}
Let your fragment implement it
public class TabOneFragment extends Fragment implements SearchView.OnQueryTextListener, OnHymnClickListener {
#Override
public void onHymnClick(HymnModel hymnModel) {
//put data to bundle and startActivity
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
adapter = new RVAdapter(mHymnModel);
adapter.setListener(this);
recyclerview.setAdapter(adapter);
}
}
Hello first of all you always want to start your activity from activity or fragment.
Never start it from adapter.
So in your adapter constructor add this
public AdapterName(......,Context context){
...your code.
this.mContext=context;
}
pass context there.
and than inside this method
public ItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(mContext instanceof YourActivityName){
((YourActivityName)mContext).yourDesiredMethod();
}
}
});
Hi I am new to Android and get a problem with Recycler View and fragment.
There are 3 fragments that can swipe, and there is a recycler view with an adapter that is in the fragment. I got a sample code from http://developer.android.com/training/implementing-navigation/lateral.html but I get null pointer exception in List object. Thanks in advance. My code is showed below:
public class TripHistoryActivity extends FragmentActivity implements ActionBar.TabListener{
private static final String TAG = "TripHistoryActivity";
private CommonDBHelper commonDBHelper;
private List<Trip> allTrips;
private ArrayList<Trip> currentTrips;
private ArrayList<Trip> pastTrips;
private ArrayList<Trip> futureTrips;
AppSectionsPagerAdapter mAppSectionsPagerAdapter;
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_trip_history);
commonDBHelper = new CommonDBHelper(this);
TripDBHelper tripDBHelper = new TripDBHelper(commonDBHelper.getWritableDatabase());
allTrips = tripDBHelper.getAllTrips();
currentTrips = new ArrayList<>();
pastTrips = new ArrayList<>();
futureTrips = new ArrayList<>();
Calendar calendar = Calendar.getInstance();
int currentDay = calendar.get(calendar.DAY_OF_MONTH);
int currentMonth = calendar.get(calendar.MONTH);
int currentYear = calendar.get(calendar.YEAR);
for (Trip trip : allTrips) {
String date = trip.getTime().substring(0, trip.getTime().indexOf(" "));
String[] dates = date.split("/");
if (currentYear < Integer.valueOf(dates[2])) {
futureTrips.add(trip);
}
else if (currentYear > Integer.valueOf(dates[2])
|| currentMonth > Integer.valueOf(dates[0])
|| currentDay > Integer.valueOf(dates[1])) {
pastTrips.add(trip);
}
else {
currentTrips.add(trip);
}
}
mAppSectionsPagerAdapter = new AppSectionsPagerAdapter(getSupportFragmentManager());
final ActionBar actionBar = getActionBar();
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mAppSectionsPagerAdapter);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// When swiping between different app sections, select the corresponding tab.
// We can also use ActionBar.Tab#select() to do this if we have a reference to the
// Tab.
actionBar.setSelectedNavigationItem(position);
}
});
for (int i = 0; i < mAppSectionsPagerAdapter.getCount(); i++) {
// Create a tab with text corresponding to the page title defined by the adapter.
// Also specify this Activity object, which implements the TabListener interface, as the
// listener for when this tab is selected.
actionBar.addTab(
actionBar.newTab()
.setText(mAppSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to one of the primary
* sections of the app.
*/
public class AppSectionsPagerAdapter extends FragmentPagerAdapter {
public AppSectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public android.support.v4.app.Fragment getItem(int i) {
switch (i) {
case 0:
android.support.v4.app.Fragment currentTripsFragment = new CurrentTripsFragment();
Bundle currentTripsBundle = new Bundle();
currentTripsBundle.putParcelableArrayList("currentTrips", currentTrips);
currentTripsFragment.setArguments(currentTripsBundle);
return currentTripsFragment;
case 1:
android.support.v4.app.Fragment pastTripsFragment = new PastTripsFragment();
Bundle pastTripsBundle = new Bundle();
pastTripsBundle.putParcelableArrayList("pastTrips", pastTrips);
pastTripsFragment.setArguments(pastTripsBundle);
return pastTripsFragment;
default:
android.support.v4.app.Fragment futureTripsFragment = new FutureTripsFragment();
Bundle futureTripsBundle = new Bundle();
futureTripsBundle.putParcelableArrayList("futureTrips", futureTrips);
futureTripsFragment.setArguments(futureTripsBundle);
return futureTripsFragment;
}
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Current Trips";
case 1:
return "Past Trips";
case 2:
return "Future Trips";
default:
return "Fault";
}
}
}
/**
* A fragment that launches other parts of the demo application.
*/
public static class CurrentTripsFragment extends android.support.v4.app.Fragment {
private RecyclerView mRecyclerView;
private Context context;
List<Trip> currentTrips;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_current_trips, container, false);
context = rootView.getContext();
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
currentTrips = getArguments().getParcelableArrayList("currentTrips");
Log.d(TripHistoryActivity.TAG, String.valueOf(currentTrips == null));
RecyclerView.LayoutManager manager = new LinearLayoutManager(context);
mRecyclerView.setLayoutManager(manager);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
CardViewAdapter cardViewAdapter = new CardViewAdapter(currentTrips);
mRecyclerView.setAdapter(cardViewAdapter);
cardViewAdapter.setOnItemClick(new CardViewAdapter.OnItemClick() {
#Override
public void onItemClick(int position) {
handleItemClick(position);
}
});
return rootView;
}
public void handleItemClick (int position) {
Toast.makeText(context, "Clicked " + position, Toast.LENGTH_SHORT).show();
Intent intent = new Intent(context, ViewTripActivity.class);
intent.putExtra("trip", currentTrips.get(position));
startActivity(intent);
}
}
There are 2 other fragments that are same as this one so I omit them.
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.nyu.cs9033.eta.R;
import com.nyu.cs9033.eta.models.Trip;
import java.util.List;
/**
* Created by Ray on 2016/4/2.
*/
public class CardViewAdapter extends RecyclerView.Adapter<CardViewAdapter.CardViewHolder> {
private final List<Trip> trips;
public CardViewAdapter (List<Trip> trips) {
this.trips = trips;
}
public interface OnItemClick {
public void onItemClick(int position);
}
private OnItemClick onItemClick;
public void setOnItemClick (OnItemClick onItemClick) {
this.onItemClick = onItemClick;
}
#Override
public CardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.history_list_item, parent, false);
return new CardViewHolder(view);
}
#Override
public void onBindViewHolder(final CardViewHolder holder, final int position) {
holder.name.setText(trips.get(position).getName());
holder.location.setText(trips.get(position).getLocation());
holder.time.setText(trips.get(position).getTime());
if (onItemClick != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onItemClick.onItemClick(position);
}
});
}
}
#Override
public int getItemCount() {
return trips.size();
}
class CardViewHolder extends RecyclerView.ViewHolder {
private TextView name;
private TextView location;
private TextView time;
public CardViewHolder (View view) {
super(view);
name = (TextView) view.findViewById(R.id.card_trip_name);
location = (TextView) view.findViewById(R.id.card_trip_location);
time = (TextView) view.findViewById(R.id.card_trip_time);
}
}
}
This is what logcat says:
FATAL EXCEPTION: mainProcess: com.nyu.cs9033.eta, PID: 14018
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()'
on a null object reference
at com.nyu.cs9033.eta.adapters.CardViewAdapter.getItemCount(CardViewAdapter.java: 57)
at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java: 2357)
at android.view.View.measure(View.java: 18796)
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java: 715)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java: 461)
at android.view.View.measure(View.java: 18796)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java: 5951)
at android.widget.FrameLayout.onMeasure(FrameLayout.java: 194)
at android.view.View.measure(View.java: 18796)
at android.support.v4.view.ViewPager.onMeasure(ViewPager.java: 1488)
at android.view.View.measure(View.java: 18796)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java: 5951)
at android.widget.FrameLayout.onMeasure(FrameLayout.java: 194)
at android.view.View.measure(View.java: 18796)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java: 5951)
at com.android.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java: 446)
at android.view.View.measure(View.java: 18796)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java: 5951)
at android.widget.FrameLayout.onMeasure(FrameLayout.java: 194)
at com.android.internal.policy.PhoneWindow$DecorView.onMeasure(PhoneWindow.java: 2643)
at android.view.View.measure(View.java: 18796)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java: 2108)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java: 1224)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java: 1460)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java: 1115)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java: 6023)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java: 858)
at android.view.Choreographer.doCallbacks(Choreographer.java: 670)
at android.view.Choreographer.doFrame(Choreographer.java: 606)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java: 844)
at android.os.Handler.handleCallback(Handler.java: 739)
at android.os.Handler.dispatchMessage(Handler.java: 95)
at android.os.Looper.loop(Looper.java: 148)
at android.app.ActivityThread.main(ActivityThread.java: 5422)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java: 726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java: 616)
You should get bundle from onCreate() instead of onCreateView(). Try the below change in your Fragment class:
public static class CurrentTripsFragment extends android.support.v4.app.Fragment {
private RecyclerView mRecyclerView;
private Context context;
List<Trip> currentTrips;
#Override
public void onCreate(Bundle savedInstanceState){
super().onCreate(savedInstanceState);
if(getArguments()!= null){
currentTrips = getArguments().getParcelableArrayList("currentTrips");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_current_trips, container, false);
context = rootView.getContext();
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
Log.d(TripHistoryActivity.TAG, String.valueOf(currentTrips == null));
RecyclerView.LayoutManager manager = new LinearLayoutManager(context);
mRecyclerView.setLayoutManager(manager);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
CardViewAdapter cardViewAdapter = new CardViewAdapter(currentTrips);
mRecyclerView.setAdapter(cardViewAdapter);
cardViewAdapter.setOnItemClick(new CardViewAdapter.OnItemClick() {
#Override
public void onItemClick(int position) {
handleItemClick(position);
}
});
return rootView;
}
public void handleItemClick (int position) {
Toast.makeText(context, "Clicked " + position, Toast.LENGTH_SHORT).show();
Intent intent = new Intent(context, ViewTripActivity.class);
intent.putExtra("trip", currentTrips.get(position));
startActivity(intent);
}
}
You are getting a null pointer exception on your list which you are using to show list items in recycler view...please check whether you are getting your data in the list or not...problem seems to be here:
CardViewAdapter cardViewAdapter = new CardViewAdapter(currentTrips);
and here:
currentTrips = getArguments().getParcelableArrayList("currentTrips");
I am developing an app where the user can type in stuff in edittexts and get to the next view by swiping the screen. The swiping-stuff is handled by a viewpager.
What I want to do is the following:
The user should only be able to swipe when all edittexts are filled. Currently all my edittexts have a TextWatcher whichs sets a boolean value to "true" once every field is filled. When it is true, I want to enable the viewpager, when it isn't, I want to disable it.
I'm using a CustomViewPager with three Fragments. I post my CustomViewPager code:
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.Toast;
public class CustomViewPager extends ViewPager {
private boolean isPagingEnabled;
public Context context;
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.isPagingEnabled = true;
this.context = context;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (isPagingEnabled) {
return super.onTouchEvent(event);
}
Toast.makeText(context, "Please fill in the details, then swipe !",
Toast.LENGTH_LONG).show();
return false;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (isPagingEnabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}
public void setPagingEnabled(boolean b) {
isPagingEnabled = b;
}
}
PageViewActivity.java
public class PageViewActivity extends FragmentActivity {
MyPageAdapter pageAdapter;
int pageId=0;
public static CustomViewPager pager;
PageListener pageListener;
int currentPage=0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<Fragment> fragments = getFragments();
pageAdapter = new MyPageAdapter(getSupportFragmentManager(), fragments);
pager =(CustomViewPager)findViewById(R.id.viewpager);
pager.setAdapter(pageAdapter);
pager.setPagingEnabled(false);
pageListener = new PageListener();
pager.setOnPageChangeListener(pageListener);
}
private List<Fragment> getFragments(){
List<Fragment> fList = new ArrayList<Fragment>();
fList.add(MyFragmentA.newInstance("Fragment 1"));
fList.add(MyFragmentB.newInstance("Fragment 2"));
fList.add(MyFragmentC.newInstance("Fragment 3"));
return fList;
}
public void next(View v){
if(pageId<=2)
{
pager.setCurrentItem(pageId);
}
pageId++;
}
private class PageListener extends SimpleOnPageChangeListener{
public void onPageSelected(int position) {
Log.i("test", "onPageSelected " + position);
currentPage = position;
}
//Called when the scroll state changes.
public void onPageScrollStateChanged(int state)
{
}
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{
Log.i("test", "onPageScrolled " + position);
currentPage = position;
}
}
}
My Page Adapter is this:
import java.util.List;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.widget.Toast;
class MyPageAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments;
public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
#Override
public int getCount() {
return this.fragments.size();
}
}
Finally I post one of my Fragments with the only relevant code:
public class MyFragmentA extends Fragment {
EditText editname;
public static final String EXTRA_MESSAGE = "EXTRA_MESSAGE";
public static final MyFragmentA newInstance(String message)
{
MyFragmentA f = new MyFragmentA();
Bundle bdl = new Bundle(1);
bdl.putString(EXTRA_MESSAGE, message);
f.setArguments(bdl);
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View myFragmentView = inflater.inflate(R.layout.fragment_a, container, false);
editname = (EditText)myFragmentView.findViewById(R.id.name_input);
editname.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(editname.getText().toString().trim().length() == 0) {
// Can I set here isPagingEnabled = false??
Toast.makeText(getActivity(), "SwipeFlag false!", Toast.LENGTH_SHORT).show();
} else if(editname.getText().toString().trim().length() > 0) {
// Can I set here isPagingEnabled = true??
Toast.makeText(getActivity(), "SwipeFlag true!", Toast.LENGTH_SHORT).show();
}
}
});
return myFragmentView;
}
}
I know that the keypoint to block page swipe is to set the flag "isPagingEnabled" to false, but I can't understand what is the best way to set it from a Fragment at runtime.
Ok, I finally found a solution and I post it here.. The best way to block page swipe is to control if edit text is filled inside onPageScrolled in PageViewActivity.java (my MainActivity..):
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
Log.i("test", "onPageScrolled - position = " + position);
currentPage = position;
txt1 = (EditText) findViewById(R.id.name_input);
if(position == 0) {
if(txt1.getText().toString().trim().length() == 0) {
pager.setCurrentItem(0);
} else if(txt1.getText().toString().trim().length() > 0) {
// DO NOTHING
}
}
}
In that way page swipe is not allowed until the edittext field of your fragment is filled.
Another wise way to block page swipe, but ONLY in the right direction is to modify onPageSelected in this way:
boolean inibitFlag = false;
int maxAllowedPage = 1; // .. or you can set this value in your fragment..
public void onPageSelected(int position) {
Log.i("test", "onPageSelected " + position);
if(inibitFlag)
return;
if(position > maxAllowedPage) {
inibitFlag = true;
pager.setCurrentItem(currentPage);
inibitFlag = false;
} else {
currentPage = position;
}
}
Hope this helps someone!!