How to implement two fragments in single view? - android

I have an application which has 3 fragments. And it works fine viewpager.
But I need to implement similar view like in Android Play store. Initially they have "Featured" Tab. When you swipe left we can see "Categories" tab.
But half of the screen still filled with "Featured" tab contents. How can I implement that view? Any idea?

Here is the actual answer. Posting after a long time.
Add this method in your adapter:
#Override
public float getPageWidth(int position) {
if (position == 0) {
return(0.5f);
} else {
return (1.0f);
}
}

Check out ViewPagerIndicator.
Try the sample first if you want to see how it looks like.
The one you want is the Titles section.

In order to display two fragment in one view you can add a layout which width & height will be wrap content in one fragment's layout then on your onCreateView add the other fragment using fragment manager.
Code will be like this --
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
>
<LinearLayout
android:id="#+id/ll1"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="vertical"
>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<Button
android:id="#+id/tb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="test"/>
</LinearLayout>
And onCreate Will be Like --
View view ;
boolean isVisible = false;
FragmentManager fm;
FragmentTransaction ft;
Fragment menuFragment;
LinearLayout llList;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.main, container, false);
llList = (LinearLayout) view.findViewById(R.id.ll1);
menuFragment = new frg1();
fm = getFragmentManager();
Button tb = (Button) view.findViewById(R.id.tb);
tb.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(!isVisible) {
isVisible = true;
showList();
}
else {
isVisible = false;
hideList();
}
}
});
return view;
}
private void changeDisplay() {
Display display = getActivity().getWindowManager().getDefaultDisplay();
int width = (int) (display.getWidth() * 0.8 );
int height = (int) (display.getHeight() * 0.8);
if(isVisible)
{
llList.setLayoutParams(new LinearLayout.LayoutParams(width, LayoutParams.FILL_PARENT));
//lllList.setLayoutParams(new LinearLayout.LayoutParams(p))
}
else {
llList.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT));
//llList.scrollTo(0, 0);
}
}
private void showList() {
changeDisplay();
ft = fm.beginTransaction();
ft.add(R.id.ll1, menuFragment);
ft.commit();
}
private void hideList() {
changeDisplay();
ft = fm.beginTransaction();
ft.remove(menuFragment);
ft.commit();
}

Related

ViewPager displays shadows on Fragments after notifyDataSetChanged

I'm making a simple flashcard app using a ViewPager, FragmentStatePagerAdapter, and some card flipping animations found on the offical Android tutorials (https://developer.android.com/training/animation/cardflip.html). I've created a shuffle button which shuffles the cards in the deck and then calls notifyDataSetChanged on the adapter to update the card views. Once called, it successfully updates the views, but it also creates a shadow/border around each card that doesn't clear until the card is touched and flipped.
When initially launched, the cards are basically have no border.
Here is what the cards look like after I spam the shuffle button. The border darkens on every press:
Here are some snippets of the relevant parts of my code:
MainAcivity.java
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.shuffleButton:
pager.removeAllViews();
pagerAdapter.shuffle();
pager.setAdapter(pagerAdapter);
}
return true;
CardPagerAdapter.java
public class CardPagerAdapter extends FragmentStatePagerAdapter {
public static final String CARD = "CARD";
private static final float WIDTH_SCALE = 0.95f;
private int count;
private Deck deck;
private ArrayList<Card> cards;
private boolean isShuffled;
public CardPagerAdapter(FragmentManager fragmentManager, Deck deck) {
super(fragmentManager);
this.deck = deck;
this.count = deck.getSize();
this.cards = deck.getCards();
this.isShuffled = false;
}
#Override
public Fragment getItem(int position) {
CardContainerFragment cardContainerFragment = new
CardContainerFragment();
Bundle bundle = new Bundle();
bundle.putParcelable(CARD, cards.get(position));
cardContainerFragment.setArguments(bundle);
return cardContainerFragment;
}
#Override
public int getItemPosition(Object item) {
return POSITION_NONE;
}
#Override
public int getCount() {
return count;
}
/**
* Override the pageWidth in order to be able
* to see other cards on the side of the current card.
* #param position The position of the current card
* #return The multiplier by which to change the width by
*/
#Override
public float getPageWidth(int position) {
return WIDTH_SCALE;
}
public void shuffle() {
if (isShuffled) {
cards = deck.getCards();
} else {
Collections.shuffle(cards);
}
isShuffled = !isShuffled;
notifyDataSetChanged();
}
}
CardContainerFragment.java
public class CardContainerFragment extends Fragment {
public static final String FLIPPED = "FLIPPED";
private static final float DISTANCE = 8000;
private CardFragment frontCardFragment;
private CardFragment backCardFragment;
private boolean cardFlipped;
public CardContainerFragment() {
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
// Create the card fragment view
final View rootView = inflater.inflate(
R.layout.card_fragment, container, false);
this.cardFlipped = false;
Bundle bundle = this.getArguments();
// Make the front and back cards
Bundle frontBundle = (Bundle) bundle.clone();
Bundle backBundle = (Bundle) bundle.clone() ;
frontCardFragment = new CardFragment();
frontBundle.putByte(FLIPPED, (byte) 0);
frontCardFragment.setArguments(frontBundle);
backCardFragment = new CardFragment();
backBundle.putByte(FLIPPED, (byte) 1);
backCardFragment.setArguments(backBundle);
// Set the first viewed fragment to be the the front of the card
getChildFragmentManager()
.beginTransaction()
.add(R.id.container, frontCardFragment)
.commit();
// Flip the card once touched
rootView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
flipCard();
}
});
return rootView;
}
/**
* Swaps the visible fragment with the other fragment (the other side of
the card)
* Animates the transition between the change with a flip animation.
*/
public void flipCard() {
Fragment fragment;
if (cardFlipped) {
fragment = frontCardFragment;
} else {
fragment = backCardFragment;
}
getChildFragmentManager()
.beginTransaction()
.setCustomAnimations(
R.animator.card_flip_left_in,
R.animator.card_flip_left_out,
R.animator.card_flip_right_in,
R.animator.card_flip_right_out)
.replace(R.id.container, fragment)
.commit();
cardFlipped = !cardFlipped;
}
public static class CardFragment extends Fragment {
private TextView cardText;
private ImageButton starButton;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup
container,
Bundle savedInstanceState) {
// Create the card fragment view and get the card object
View view = inflater.inflate(R.layout.card_view, container,
false);
Bundle bundle = this.getArguments();
final Card card = bundle.getParcelable(CardPagerAdapter.CARD);
boolean cardFlipped = bundle.getByte(FLIPPED) != 0;
// Change camera perspective to not have the flip animation be
// distorted
float scale = getResources().getDisplayMetrics().density;
view.setCameraDistance(DISTANCE * scale);
// Set the text from the card to the fragment's textview
cardText = (TextView) view.findViewById(R.id.cardText);
if (cardFlipped) {
cardText.setText(card.getBackText());
} else {
cardText.setText(card.getFrontText());
}
// Make the star button and set it based on if the card is
// starred
starButton = (ImageButton) view.findViewById(R.id.starButton);
if (card.isStarred()) {
starButton.setImageResource(R.mipmap.ic_star_white_48dp);
} else {
starButton.setImageResource(R.mipmap.ic_star_border_black_48dp);
}
starButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!card.isStarred()) {
starButton.setImageResource(R.mipmap.ic_star_white_48dp);
} else {
starButton.setImageResource(R.mipmap.ic_star_border_black_48dp);
}
card.toggleStarred();
}
});
return view;
}
}
}
Any help at all would be appreciated.
*EDIT
As requested here is the XML
card_fragment.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:stateListAnimator="#null">
</FrameLayout>
card_view.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:stateListAnimator="#null">
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:cardUseCompatPadding="true"
android:stateListAnimator="#null">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/cardText"
android:layout_width="350dp"
android:layout_height="500dp"
android:gravity="center"
android:text="This is the card contents."
android:textAlignment="center"
android:textSize="24sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintBottom_toBottomOf="parent" />
<ImageButton
android:id="#+id/starButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:background="#android:color/transparent"
android:tint="#android:color/darker_gray"
app:layout_constraintRight_toRightOf="#+id/cardText"
app:layout_constraintTop_toTopOf="#+id/cardText"
app:srcCompat="#mipmap/ic_star_border_black_48dp" />
</android.support.constraint.ConstraintLayout>
</android.support.v7.widget.CardView>
</FrameLayout>
main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#d3d3d3"
tools:context="com.benvo.viewpager.activities.MainActivity">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<ProgressBar
android:id="#+id/deckProgressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

Dynamically set ViewPager's height with fragments

I'm trying to set ViewPager's height dynamically, so that each Fragment of the ViewPager has its own height. I based my code on the solution found by czaku here: Dynamically set ViewPager height
activity_artwork_page.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true" >
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_artwork_page"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.andrea.chatbeacon.ArtworkPageActivity">
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="4000dp" />
<fragment
class="com.example.andrea.chatbeacon.ChatFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/chat_fragment"
android:layout_marginTop="40dp"
tools:layout="#layout/fragment_chat" />
</LinearLayout>
</ScrollView>
ArtworkPageActivity.java
public class ArtworkPageActivity extends AppCompatActivity {
private ViewPager mPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_artwork_page);
mPager = (ViewPager) findViewById(R.id.pager);
PagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
}
#Override
protected void onResume() {
super.onResume();
ViewTreeObserver viewTreeObserver = mPager.getViewTreeObserver();
viewTreeObserver
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
LinearLayout artwork_slide_layout = (LinearLayout) findViewById(R.id.artwork_slide_layout);
int viewPagerWidth = mPager.getWidth();
int viewPagerHeight = artwork_slide_layout.getHeight();
layoutParams.width = viewPagerWidth;
layoutParams.height = viewPagerHeight;
mPager.setLayoutParams(layoutParams);
mPager.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
}
#Override
public void onBackPressed() {
if (mPager.getCurrentItem() == 0) {
// If the user is currently looking at the first step, allow the system to handle the
// Back button. This calls finish() on this activity and pops the back stack
super.onBackPressed();
} else {
// Otherwise, select the previous step
mPager.setCurrentItem(mPager.getCurrentItem() - 1);
}
}
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Fragment fragment = new ArtworkSlideFragment();
Bundle args = new Bundle();
args.putInt("position", position);
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
int id = getIntent().getIntExtra("id", 0);
return Variables.artworks[id].getTitles().length;
}
}
}
fragment_artwork_slide.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/artwork_slide_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ArtworkSlideFragment">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/artwork_image"
android:contentDescription="#string/artwork_image_description" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/artwork_title"
android:textColor="#android:color/black"
android:textSize="18sp"
android:layout_marginTop="#dimen/activity_vertical_margin" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/artwork_text"
android:textColor="#android:color/black"
android:textSize="15sp"
android:layout_marginTop="10dp" />
</LinearLayout>
ArtworkSlideFragment.java
public class ArtworkSlideFragment extends Fragment {
public ArtworkSlideFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Bundle args = getArguments();
int id = getActivity().getIntent().getIntExtra("id", 0);
int position = args.getInt("position", 0);
View view = inflater.inflate(R.layout.fragment_artwork_slide, container, false);
ImageView image = (ImageView) view.findViewById(R.id.artwork_image);
TextView title = (TextView) view.findViewById(R.id.artwork_title);
TextView text = (TextView) view.findViewById(R.id.artwork_text);
Glide.with(getActivity().getApplicationContext()).load(Variables.artworks[id].getImages()[position]).into(image);
title.setText(Variables.artworks[id].getTitles()[position]);
text.setText(Variables.artworks[id].getTexts()[position]);
return view;
}
}
I tried to set
viewPagerHeight = artwork_slide_layout.getHeight();
but it seems not to work. How can I set the viewPagerHeight?
I found a working solution from vabhishek at:
https://github.com/vabhishek/WrapContentViewPagerDemo
This works for me even without the CustomScrollView defined by vabhishek.

Android Fragment Layout is not replacing a view using Linear Layout

I am facing some issues for fragment in Android.
I completed a implementation of ViewPager using two fragment class with its xml layout, An MainActivity and An Adapter.
First Fragment : Linear Layout is Parent as well in second fragment, Linear Layout is parent. I have a button in my first fragment, i want to replace first fragment means switch fragment from first to second.
I am using ViewPager. Kindly Look on my source code.
PagerActivity.java
public class PagerActivity extends FragmentActivity {
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pager);
mViewPager=(ViewPager)findViewById(R.id.viewpager);
/** set the adapter for ViewPager */
mViewPager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
// mViewPager.notify();
}
}
PagerAdapter.java
public class MyPagerAdapter extends FragmentPagerAdapter {
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
/** Show a Fragment based on the position of the current screen */
if (position == 0) {
return new Welcome();
}else{
return new Locate();
}
}
#Override
public int getCount() {
return 2;
}
}
Welcome.java
Fragment 1
public class Welcome extends Fragment implements GlobalInterFace, View.OnClickListener{
private Button welcomeBtn;
private View v;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.activity_welcome, container, false);
welcomeBtn=(Button)v.findViewById(R.id.welcomeBtn);
findViewById();
setOnClickListener();
return v;
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.welcomeBtn:{
Log.e("click", "click");
Fragment fragment = new Locate();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.parent_linear, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
break;
}
}
}
Locate.java
Fragment 2
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.activity_welcome_pager_two, container, false);
locateMe=(Button)v.findViewById(R.id.locateBtn);
locateMe.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(getActivity(), SignUpActivity.class);
startActivity(i);
((Activity) getActivity()).overridePendingTransition(0,0);
}
});
return v;
}
welcome xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/parent_linear"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#color/splash_color"
android:weightSum="100">
<RelativeLayout
android:id="#+id/rel1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="50">
<com.rey.material.widget.ImageView
android:id="#+id/welcome_Image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/welcome"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
<RelativeLayout
android:id="#+id/welcomeRelativeTwo"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="50"
android:padding="#dimen/universal_margin4"
>
<com.rey.material.widget.TextView
android:id="#+id/Ready"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/welcome_ready"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:textSize="#dimen/universal_margin2"
android:layout_centerInParent="true"
/>
<com.rey.material.widget.TextView
android:id="#+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/welcome_descrition"
android:layout_below="#+id/Ready"
android:textAlignment="center"
android:layout_centerHorizontal="true"
android:layout_marginTop="#dimen/universal_margin"
/>
<com.rey.material.widget.Button
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/welcomeBtn"
app:rd_enable="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/description"
android:text="#string/welcome_btntext"
android:textColor="#color/splash_color"
android:background="#color/colorAccent"
android:layout_marginTop="#dimen/universal_margin2"
/>
</RelativeLayout>
<!-- Your RelativeLayout Items -->
</LinearLayout>
Locate.xml
same as welcome layout only layout id is changed.
When I click on WelcomeBtn, the fragment replacement is not working.mentioned this one in my source code in Welcome.java
please help me.
Your parent parent_linearis instance of LinearLayout if you want to put fragment inside this view you should change your LinearLayout to FrameLayout something like this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/parent_linear"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#color/splash_color">
//... your other layout goes here
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
And change following part of your code:
fragmentTransaction.replace(R.id.fragment_container, fragment);

Android ViewPager with PageTransformer and SceneTransition

and thank you for stopping by.
I've been facing a weird behavior using the combination of both PageTransformer and TransitionManager.
The hierarchy I'm using is fairly easy : A viewPager with each page being a fragment. The fragment has two different layouts, changing with the TransitionManager.go().
The issue :
If I just scroll through the viewPager, everything is fine, and my pageTransformer applies the right values, creating the desired parallax effect.
If I just click back and forth to change scenes inside a page, I also get the desired output.
However, whenever I use the TransitionManager.go() (let's say twice, to go back to the first layout) and then start scrolling through my viewPager, the parallax effect doesn't occur anymore.
My question :
Is there any known issue I haven't been able to find with using both a PageTransformer and a TransitionManager at the same time?
My code :
Fragment1.java
public class Fragment1 extends Fragment {
private Scene mStartScene;
private Scene mInfoScene;
private Transition mTransition;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.view_pager_item_default, container, false);
RelativeLayout rootLayout = (RelativeLayout) v.findViewById(R.id.p1);
mTransition = new ChangeBounds();
mTransition.setDuration(400);
mStartScene = Scene.getSceneForLayout(rootLayout, R.layout.view_pager_item_default, getContext());
mInfoScene = Scene.getSceneForLayout(rootLayout, R.layout.view_pager_item_details, getContext());
return (v);
}
public void changeScene(View v) {
Scene tmp = mInfoScene;
mInfoScene = mStartScene;
mStartScene = tmp;
TransitionManager.go(mStartScene, mTransition);
}
}
view_pager_item_default.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/p1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView"
android:elevation="20dp"
android:text="Item 1"
android:onClick="changeScene"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="60dp"
android:layout_width="match_parent"
android:layout_alignParentBottom="true"
android:padding="20dp"
android:layout_height="wrap_content"
android:background="#drawable/white_shape"
android:textSize="40sp"
android:gravity="center"
android:textColor="#000000"/>
<ImageView
android:id="#+id/imageView"
android:elevation="19dp"
android:scaleType="centerCrop"
android:layout_marginBottom="-10dp"
android:layout_centerHorizontal="true"
android:src="#mipmap/big_image"
android:background="#android:color/transparent"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
view_pager_item_details.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/p1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView"
android:elevation="20dp"
android:text="Item 1 description"
android:onClick="changeScene"
android:layout_marginTop="150dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="20dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/white_shape"
android:clickable="true"
android:textSize="30sp"
android:gravity="center"
android:textColor="#000000"/>
<ImageView
android:id="#+id/imageView"
android:elevation="21dp"
android:layout_marginTop="50dp"
android:layout_centerHorizontal="true"
android:src="#mipmap/small_image"
android:background="#android:color/transparent"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
My adapter is fairly simple :
public class MyPagerAdapter extends FragmentPagerAdapter {
private final List fragments;
public MyPagerAdapter(FragmentManager fm, List fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
return (Fragment) this.fragments.get(position);
}
#Override
public int getCount() {
return this.fragments.size();
}
}
Then is my PageTransformer which moves each children of the view independently
public class MyPagerTransformer implements ViewPager.PageTransformer {
private float mParallaxCoeff;
private float mDistanceCoeff;
public MyPagerTransformer(float parallax, float distance) {
mParallaxCoeff = parallax;
mDistanceCoeff = distance;
}
#Override
public void transformPage(View page, float position) {
float coefficient = page.getWidth() * mParallaxCoeff;
ViewGroup vG = (ViewGroup) page;
for (int i = vG.getChildCount() - 1; i >= 0; --i) {
View v = vG.getChildAt(i);
if (v != null) {
v.setTranslationX(coefficient * (position * position * position));
}
coefficient *= mDistanceCoeff;
}
}
}
And lastly my Activity :
public class MainActivity extends AppCompatActivity {
private Fragment1 mFrag1;
private Fragment1 mFrag2;
private Fragment1 mFrag3;
private ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_main);
mViewPager = (ViewPager) findViewById(R.id.main_view_pager);
CirclePageIndicator indicator = (CirclePageIndicator) findViewById(R.id.indicator);
if (mViewPager != null) {
mViewPager.setPageTransformer(true, new MyPagerTransformer(8.0f, 8.0f));
//vp.addOnPageChangeListener(listener);
List<Fragment> fragments = new ArrayList<>();
mFrag1 = new Fragment1();
mFrag2 = new Fragment1();
mFrag3 = new Fragment1();
fragments.add(mFrag1);
fragments.add(mFrag2);
fragments.add(mFrag3);
PagerAdapter realViewPagerAdapter = new MyPagerAdapter(super.getSupportFragmentManager(), fragments);
mViewPager.setAdapter(realViewPagerAdapter);
indicator.setViewPager(mViewPager);
}
}
public void changeScene(View v) {
switch (mViewPager.getCurrentItem()) {
case 0:
mFrag1.changeScene(v);
break;
case 1:
mFrag2.changeScene(v);
break;
case 2:
mFrag3.changeScene(v);
break;
default:
break;
}
}
}
Lastly, here's a gif showing what happens. As you can see, at the beginning "Item 1" has the parallax effect. After switching scenes back and forth, the PageTransformer won't apply anymore.
Thanks in advance !
I will answer my own question in case anyone would bump into the same issue as I did.
The problem came from the rootLayout I was using in the fragment not being "the right one", therefore the TransitionManager was adding an extra layer when going back to the first scene.
Here's what I changed :
Fragment1.java
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//view_pager_root.xml is a simple empty FrameLayout
View v = inflater.inflate(R.layout.view_pager_root, container, false);
RelativeLayout rootLayout = (RelativeLayout) v.findViewById(R.id.p1);
mTransition = new ChangeBounds();
mTransition.setDuration(400);
mStartScene = Scene.getSceneForLayout(rootLayout, R.layout.view_pager_item_default, getContext());
mInfoScene = Scene.getSceneForLayout(rootLayout, R.layout.view_pager_item_details, getContext());
return (v);
}
Since I added another layer into my hierarchy, I also had to change slightly my PageTransformer :
#Override
public void transformPage(View page, float position) {
float coefficient = page.getWidth() * mParallaxCoeff;
//vG is the FrameLayout
ViewGroup vG = (ViewGroup) page;
if (vG.getChildAt(0) instanceof ViewGroup) {
//vG is now the RelativeLayout from the scene
vG = (ViewGroup) vG.getChildAt(0);
for (int i = vG.getChildCount() - 1; i >= 0; --i) {
View v = vG.getChildAt(i);
if (v != null) {
v.setTranslationX(coefficient * (position * position * position));
}
coefficient *= mDistanceCoeff;
}
}
}

Replacing fragments within viewpager

I am currently having an issue with replacing a certain fragment within ViewPager with another. The fragment id like to replace is my "Departments" which has an Imagebutton id like to use to begin the replacement. I've tried to apply some suggestions from other similar questions (most of which were old and prior to the new api release which allows for nested fragments) and have had no success. Would using nested fragments be easier? I am new to android app development so any help would be great. Thanks in advance.
here is my FragmentAcitivty
public class ViewPagerStyle extends FragmentActivity {
private ViewPager mViewPager;
private ViewPagerAdapter adapter;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setUpView();
setTab();
}
private void setUpView(){
mViewPager = (ViewPager) findViewById(R.id.viewPager);
adapter = new ViewPagerAdapter(getApplicationContext(),getSupportFragmentManager());
mViewPager.setAdapter(adapter);
mViewPager.setCurrentItem(0);
}
private void setTab(){
mViewPager.setOnPageChangeListener(new OnPageChangeListener(){
#Override
public void onPageScrollStateChanged(int position) {}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {}
#Override
public void onPageSelected(int position) {
// TODO Auto-generated method stub
switch(position){
case 0:
findViewById(R.id.first_tab).setVisibility(View.VISIBLE);
findViewById(R.id.second_tab).setVisibility(View.INVISIBLE);
findViewById(R.id.third_tab).setVisibility(View.INVISIBLE);
break;
case 1:
findViewById(R.id.first_tab).setVisibility(View.INVISIBLE);
findViewById(R.id.second_tab).setVisibility(View.VISIBLE);
findViewById(R.id.third_tab).setVisibility(View.INVISIBLE);
break;
case 2:
findViewById(R.id.first_tab).setVisibility(View.INVISIBLE);
findViewById(R.id.second_tab).setVisibility(View.INVISIBLE);
findViewById(R.id.third_tab).setVisibility(View.VISIBLE);
break;
}
}
});
}
}
FragmentPagerAdapter
public class ViewPagerAdapter extends FragmentPagerAdapter {
private Context _context;
public ViewPagerAdapter(Context context, FragmentManager fm) {
super(fm);
_context = context;
}
#Override
public Fragment getItem(int position) {
Fragment f = new Fragment();
switch(position){
case 0:
f=PubView.newInstance(_context);
break;
case 1:
f=MyView.newInstance(_context);
break;
case 2:
f=Departments.newInstance(_context);
break;
}
return f;
}
#Override
public int getCount() {
return 3;
}
}
Departments Fragment with button
public class Departments extends Fragment {
public static Fragment newInstance(Context context) {
Departments f = new Departments();
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
View root = (View) inflater.inflate(R.layout.activity_departments, null);
ImageButton engineeringButton = (ImageButton)root.findViewById(R.id.engineeringButton);
engineeringButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
Fragment newFragment = Engineering.newInstance(null);
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.addToBackStack(null);
transaction.replace(R.id.viewPager, newFragment).commit();
}
});
return root;
}
}
Also, here is my main.xml file which hosts the viewpager
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/purple"
android:orientation="vertical" >
<TableLayout
style="#style/layout_f_w"
android:stretchColumns="*" >
<TableRow
android:id="#+id/tableRow1"
style="#style/layout_wrap"
android:background="#color/white" >
<!-- First Tab -->
<LinearLayout
android:id="#+id/first_text"
style="#style/layout_f_w"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
style="#style/text_title"
android:text="pubView"
android:textColor="#color/purple" />
</LinearLayout>
<!-- Second Tab -->
<LinearLayout
android:id="#+id/second_text"
style="#style/layout_f_w"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
style="#style/text_title"
android:gravity="center"
android:text="myView"
android:textColor="#color/purple" />
</LinearLayout>
<!-- Third Tab -->
<LinearLayout
android:id="#+id/third_text"
style="#style/layout_f_w"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
style="#style/text_title"
android:text="Dept."
android:textColor="#color/purple" />
</LinearLayout>
</TableRow>
</TableLayout>
<!-- Include Tab Indicator -->
<include
android:layout_width="fill_parent"
android:layout_height="wrap_content"
layout="#layout/indicator" />
<android.support.v4.view.ViewPager
android:id="#+id/viewPager"
android:layout_width="fill_parent"
android:layout_height="450dp" />
<ImageButton
android:id="#+id/settingsButton"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_marginLeft="50dp"
android:background="#drawable/settings_button"
android:src="#drawable/settings_button" />
</LinearLayout>
One thing i am confused on is that I don't know which id to put into the first argument of transaction.replace(r.id.viewPager, newfragment)...Ive read that it needs the id of the container but when I use this I receive the runtime error from logcat:
04-13 21:41:48.680: E/AndroidRuntime(960): java.lang.IllegalArgumentException: No view found for id 0x7f0a0029 (com.pvcalendar:id/viewPager) for fragment Engineering{4089a730 #0 id=0x7f0a0029}
I think the point is to use a fragment as a container.
In your ViewPagerAdapter:
#Override
public Fragment getItem(int position) {
/*
* IMPORTANT: This is the point. We create a RootFragment acting as
* a container for other fragments
*/
if (position == 0)
return new RootFragment();
else
return new StaticFragment();
}
RootFragment layout should look like:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/root_frame" >
</FrameLayout>
And directly, you fill it with your first "real" fragment:
public class RootFragment extends Fragment {
private static final String TAG = "RootFragment";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
/* Inflate the layout for this fragment */
View view = inflater.inflate(R.layout.root_fragment, container, false);
FragmentTransaction transaction = getFragmentManager()
.beginTransaction();
/*
* When this container fragment is created, we fill it with our first
* "real" fragment
*/
transaction.replace(R.id.root_frame, new FirstFragment());
transaction.commit();
return view;
}
}
Finally, you can replace fragments. For instance, inside your "real" fragment you could have a button:
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
FragmentTransaction trans = getFragmentManager()
.beginTransaction();
/*
* IMPORTANT: We use the "root frame" defined in
* "root_fragment.xml" as the reference to replace fragment
*/
trans.replace(R.id.root_frame, new SecondFragment());
/*
* IMPORTANT: The following lines allow us to add the fragment
* to the stack and return to it later, by pressing back
*/
trans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
trans.addToBackStack(null);
trans.commit();
}
});
I've developed an example application that shows a similar concept. You could replace a fragment inside a ViewPager without changing to a new Activity. The code is available in:
https://github.com/danilao/fragments-viewpager-example
I'm assuming you want the Engineering fragment to be on a completely new page, because you aren't using it in your ViewPagerAdapter. If that's the case, create a new Activity, with your Engineering fragment in the layout, and launch the Activity from the engineeringButton click.
The problem is you are trying to shove your Engineering fragment into the View hierarchy of R.layout.activity_departments, and there is (hopefully) no ViewPager in there, hence the error.

Categories

Resources