I've a ViewPager which now uses Views instead of Fragments to display each tab.
Every single tab, inflates the same layout file.
Overview
In this ViewPager, I'm supposed to add Mines as Tabs, so basically every tab would correspond to a specific mine (the ones with minerals, not the bomb).
Some mines are already unlocked, but some other need to be purchased first, so I added a button to do just this.
Problem
Fact is, using fragments, it all worked fine, but now I swapped them with Views, I can buy the mine, but then, if I buy another one, the one I previously purchased, gets locked back as I never did buy it.
CODE
I'm really confused now, I don't know where the problem is, but I can surely give you the most relevant parts of the code:
MinerAdapter
public class MineAdapter extends PagerAdapter {
private Context mContext;
private LayoutInflater mLayoutInflater;
public MineAdapter(Context context) {
mContext = context;
mLayoutInflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public Object instantiateItem(ViewGroup container, final int position) {
System.out.println("Code executed");
final View itemView = mLayoutInflater.inflate(R.layout.carousal_page, container,
false);
switch (position) {
case 0:
itemView.setBackgroundResource(R.color.iron);
break;
case 1:
itemView.setBackgroundResource(R.color.coal);
break;
case 2:
itemView.setBackgroundResource(R.color.gold);
break;
}
[Some setup skipped]
// Unlock Button
itemView.findViewById(R.id.unlockButton).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (CenterRepository.getSingletonInstance().getCurrentUser().getGold() >=
CenterRepository.getSingletonInstance().getListOfLavels().get(position).getUnlockCost()) {
//If User has more gold than cost to unlock remove lock image and buy it
CenterRepository.getSingletonInstance().getCurrentUser().setGold(
CenterRepository.getSingletonInstance().getCurrentUser().getGold()
- CenterRepository.getSingletonInstance().getListOfLavels().get(position).getUnlockCost()); // Update user's gold
itemView.findViewById(R.id.unlockButton).setVisibility(View.GONE); // Remove lock button
Toast.makeText(mContext,
"Reduced " + CenterRepository.getSingletonInstance().getListOfLavels().get(position).getUnlockCost() +
"\n Updated Gold " + CenterRepository.getSingletonInstance()
.getCurrentUser().getGold(), Toast.LENGTH_LONG).show();
} else {
// Not enough money
Toast.makeText(mContext, "Not enough money to purchase You need " +
(CenterRepository.getSingletonInstance().getListOfLavels().get(position).getUnlockCost()
- CenterRepository.getSingletonInstance().getCurrentUser().getGold()) + "More", Toast.LENGTH_SHORT).show();
}
}
});
container.addView(itemView);
return itemView;
}
}
XML Layout
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/mineName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/activity_horizontal_margin"
android:layout_weight="1"
android:gravity="center_vertical"
android:text="COAL MINE"
android:textColor="#android:color/white"
android:textSize="25sp" />
<TextView
android:id="#+id/mineCost"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="5"
android:gravity="center"
android:text="1000"
android:textColor="#android:color/white"
android:textSize="50sp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="3"
android:paddingEnd="100dp"
android:paddingStart="100dp">
<TextView
android:id="#+id/mineMineral"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignTop="#+id/mineDropRate"
android:text="COAL"
android:textAlignment="center"
android:textColor="#android:color/white"
android:textSize="25sp" />
<TextView
android:id="#+id/mineDropRate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:text="1"
android:textAlignment="center"
android:textColor="#android:color/white"
android:textSize="25sp" />
</RelativeLayout>
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/unlockButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Unlock" />
</RelativeLayout>
MainActivity
public class MainActivity extends AppCompatActivity {
ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Add Test User from Activity
CenterRepository.getSingletonInstance().setCurrentUser(new User("FET", 2000, 20, 10));
//Add Test Mines
CenterRepository.getSingletonInstance().getListOfLavels().clear();
CenterRepository.getSingletonInstance().addMine(new Mine("Iron", new Mineral("Iron Mineral", 1), 100, 2));
CenterRepository.getSingletonInstance().addMine(new Mine("Coal", new Mineral("Coal Mineral", 3), 200, 2));
CenterRepository.getSingletonInstance().addMine(new Mine("Gold", new Mineral("Gold Mineral", 2), 300, 2));
viewPager = (ViewPager) findViewById(R.id.vpPager);
viewPager.setAdapter(new MineAdapter(this));
}
}
Extra
If you prefer working with GitHub, here's the project with the full code with no skipped code.
ViewPager2 supports using a RecyclerView Adapter for the adapter.
Hence you do not need to use a fragment anymore.
You can use a View just like in recyclerView and it would preserve it's snap behavior as well
Related
In my Fragment, I have three controls: two ImageViews and a Button:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:layout_width="match_parent"
android:id="#+id/rel_layout"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:background="#ffffffff"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="#+id/heading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:textStyle="bold"
android:visibility="visible"
android:textSize="25sp"
android:layout_marginTop="10dp"
android:layout_marginStart="10dp" />
<ImageView
android:id="#+id/forward"
android:background="#drawable/chevronright"
android:layout_below="#+id/heading"
android:layout_alignParentEnd="true"
android:layout_width="50dp"
android:layout_height="50dp" />
<ImageView
android:id="#+id/back"
android:background="#drawable/chevronleft"
android:layout_below="#+id/heading"
android:visibility="invisible"
android:layout_alignParentStart="true"
android:layout_width="50dp"
android:layout_height="50dp" />
<Button
android:id="#+id/skip_button"
android:text="#string/skip_button"
style="?android:attr/buttonBarButtonStyle"
android:layout_below="#+id/back"
android:layout_alignParentStart="true"
android:textStyle="bold"
android:layout_alignParentBottom="true"
android:gravity="bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_alignParentStart="true"
android:layout_below="#+id/heading" >
<TextView
android:id="#+id/body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="normal"
android:visibility="visible"
android:textSize="20sp" />
</LinearLayout>
</RelativeLayout>
In the fragment, I define onClickListeners for all three controls:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
SharedPreferences sharedPref = getActivity().getSharedPreferences("WDWHIC settings", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt("lastPage", INTRO);
editor.commit();
View view = inflater.inflate(R.layout.fragment_intro, container, false);
((AppCompatActivity)getActivity()).getSupportActionBar().setTitle(R.string.intro_page_full);
RelativeLayout topLayout = getActivity().findViewById(R.id.topLayout);
topLayout.setVisibility(View.INVISIBLE);
final Animation in = new AlphaAnimation(0.0f, 1.0f);
in.setDuration(500);
RelativeLayout rel_layout = view.findViewById(R.id.rel_layout);
Resources res = getResources();
pages = res.getStringArray(R.array.pages_array);
heading = rel_layout.findViewById(R.id.heading);
heading.setText(pages[pageNum]);
forward = rel_layout.findViewById(R.id.forward);
forward.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
back.setVisibility(View.VISIBLE);
pageNum += 2;
heading.setText(pages[pageNum]);
body.startAnimation(in);
body.setText(pages[pageNum + 1]);
body.scrollTo(0, 0);
if (pageNum == 2 * MAX_PAGES) forward.setVisibility(View.INVISIBLE);
}
});
back = rel_layout.findViewById(R.id.back);
back.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
forward.setVisibility(View.VISIBLE);
pageNum -= 2;
heading.setText(pages[pageNum]);
body.startAnimation(in);
body.setText(pages[pageNum + 1]);
body.scrollTo(0, 0);
if (pageNum == 0) back.setVisibility(View.INVISIBLE);
}
});
skip = rel_layout.findViewById(R.id.skip_button);
skip.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EditProfileFragment editProfileFragment = new EditProfileFragment();
FragmentManager manager = getActivity().getSupportFragmentManager();
manager.beginTransaction().replace(R.id.fragment_container, editProfileFragment, editProfileFragment.getTag()).commit();
getActivity().overridePendingTransition(R.anim.fadein, R.anim.fadeout);
}
});
body = rel_layout.findViewById(R.id.body);
body.startAnimation(in);
body.setText(pages[pageNum + 1]);
body.setMovementMethod(new ScrollingMovementMethod());
return view;
}
If I click on the 'skip' button while on the first page, its onClick() method gets called. But if I click on forward or back, it doesn't unless I return to the first page. What's up with this? Why should advancing pages make a difference?
Try adding android:clickable="true" to your image views.
In the documentation:
android:clickable Defines whether this view reacts to click events.
https://developer.android.com/reference/android/view/View#attr_android:clickable
Therefore, in theory, the View's onClickListener won't be fire if clickable is not set to true.
I would try setting the onClickListener functionality in the class that extends FragmentActivity.
In the class that implements your onCreateView method define a static handler and initialized it with the static handler that should be defined in the class that extends FragmentActivity.
from the class that implements onCreateView create an android message to send to the static handler of your class that extends FragmentActivity. In this message send an object which is your button that will implement the onClickListener. Note: Create and send this message from inside your onCreateView.
Once the message is received inside the class that extends FragmentActivity, send the
object that arrives in the message( which is a view that is actually your button) as a parameter to a private method that resides inside your class that extends FragmentActivity.
Inside this private method try to set the onClickListener functionality.
I don't know why this should work, but I moved the button above the heading, without changing anything else, and now onClick() gets called from every page.
<Button
android:id="#+id/skip_button"
android:text="#string/skip_button"
style="?android:attr/buttonBarButtonStyle"
android:layout_alignParentEnd="true"
android:textStyle="bold"
android:layout_marginTop="10dp"
android:layout_alignParentTop="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/heading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_below="#+id/skip_button"
android:textStyle="bold"
android:visibility="visible"
android:textSize="25sp"
android:layout_marginStart="10dp" />
Question: How to add multiple Relative Layouts to an existing Relative Layout.
Please forgive my ignorance as I am still in the process of self learning android dev and there are still a few gaps in my understanding.
My goal is to take this screen: Main Activity and Add multiple smaller Relative Layouts to a Linear Layout, in this case that layout is titled rootWorkingLayout. Now currently, my code successfully adds one of the smaller Relative Layouts as seen here: Main Activity.
My seemingly elusive goal is to have 4 or 5 of these on the screen each with different data within the TextViews (But that's the next step. for me) I am unsure of how to accomplish this.
Main Activity Java Class:
public class rootActivity extends AppCompatActivity {
private Toolbar toolbar; //Toolbar Declaration
public LinearLayout rootWorkingLayout;
public static int i = 100; //previewCounter
//Main Function
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_root);
toolbar =(Toolbar) findViewById(R.id.toolBar);
rootWorkingLayout = (LinearLayout) findViewById(R.id.rootWorkingLayout);
setSupportActionBar(toolbar);
Bundle previewReceiver = getIntent().getExtras();
//If There is a Bundle, Process it
if(previewReceiver != null) {
newPreview(previewReceiver);
}
}
//Create Options Menu
#Override
public boolean onCreateOptionsMenu (Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
//Track Options Menu
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_newReport: return true;
case R.id.action_history: return true;
case R.id.action_settings: return true;
default: return super.onOptionsItemSelected(item);
}
}
//Launch New Report Wizard
public void newReport (MenuItem menuItem)
{
Intent startNewReport = new Intent(getApplicationContext(), reportGeneratorActivity.class);
startActivity(startNewReport);//Go To Report Wizard
}
//Process New Preview
public void newPreview (Bundle previewReceiver) {
//Extract Strings from Bundle
String date = previewReceiver.getString("date");
String client = previewReceiver.getString("client");
String machine =previewReceiver.getString("machine");
String serialNum = previewReceiver.getString("serial");
//Create New Inflater
LayoutInflater previewInflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View previewLayout = previewInflater.inflate(R.layout.previewplate, null);
//Set Params
LinearLayout.LayoutParams previewParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
previewLayout.setLayoutParams(previewParams);// Add Params to Preview Plate
//Add previewLayout to rootWorkingLayout
previewLayout.setId(i);
//previewLayout.setID(i);//Assing new ID
i += 100;//Increment ID
rootWorkingLayout.addView(previewLayout);
//TODO: Configure Preview Plate
}
}
Here is the Main Activity XML:
<RelativeLayout 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:paddingBottom="#dimen/activity_vertical_margin"
tools:context="com.gdt.user.testgdt.rootActivity">
<android.support.v7.widget.Toolbar
android:id="#+id/toolBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
android:elevation="4dp"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignStart="#+id/toolBar"
android:layout_below="#+id/toolBar"
android:id="#+id/rootWorkingLayout"
android:paddingTop="10dp"
android:weightSum="1">
</LinearLayout>
</RelativeLayout>
And here is the Layout of the Relative Layout I am attempting to add multiple times to the rootWorkingLayout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/previewReportPlate"
android:background="#D1D1D1"
android:layout_below="#+id/previewReportPlateLbl"
android:layout_alignParentStart="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Client Name"
android:id="#+id/clientNamePlate"
android:textColor="#000000"
android:paddingLeft="6dp"
android:paddingTop="6dp"
android:paddingRight="6dp"
android:paddingBottom="6dp"
android:layout_alignParentLeft="true"
android:layout_marginLeft="0dp"
android:layout_alignParentTop="true"
android:layout_marginTop="0dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Machine Type"
android:id="#+id/machineTypePlate"
android:textColor="#000000"
android:paddingLeft="6dp"
android:paddingTop="6dp"
android:paddingRight="6dp"
android:paddingBottom="6dp"
android:layout_marginLeft="0dp"
android:layout_below="#+id/clientNamePlate"
android:layout_alignParentStart="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Serial Number"
android:id="#+id/serialNumberPlate"
android:textColor="#000000"
android:paddingLeft="6dp"
android:paddingTop="6dp"
android:paddingRight="6dp"
android:paddingBottom="6dp"
android:layout_marginLeft="0dp"
android:layout_below="#+id/machineTypePlate" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Date"
android:id="#+id/datePlate"
android:layout_gravity="right"
android:textColor="#000000"
android:paddingRight="10dp"
android:layout_marginLeft="691dp"
android:layout_below="#+id/serialNumberPlate"
android:layout_alignParentEnd="true" />
</RelativeLayout>
My current thoughts are that this is an issue with the previewLayout.setId or a rule that I need to declare somewhere. Likely I belive I need to construct some sort of loop eventually that goes through the process. But at this time I think I need help figuring out how to add multiple previewPlate layouts.
Thanks in advance!
Now currently, my code successfully adds one of the smaller Relative Layouts
Sure, that is because you only call your method once in onCreate.
newPreview(previewReceiver);
You could copy that line multiple times, and you will see more than one layout.
My seemingly elusive goal is to have 4 or 5 of these on the screen each with different data within the TextViews
You will need different Bundles each time you call your method to set different data, but all you need to do is call that method again.
And if you are trying to do it with that plus button in the Toolbar, you can do it like so
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_newReport:
Bundle b = new Bundle();
// TODO: set some data in the bundle
newPreview(b);
return true;
I am creating a music player app the below are list of activities:
WelcomeActivity
SongsListActivity
MusicPlayActivity
SongsListActivity will display list of songs available, on click of item it will take you to MusicPlayActivity and which will trigger SongService which in turn play song in background.
The below is MusicPlayActivity
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:background="#drawable/background">
<include layout="#layout/musicpanel"></include>
</RelativeLayout>
The below code is for musicpanel which is included in MusicPlayActivity
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Play"
android:id="#+id/playPause"
android:layout_gravity="bottom"
android:layout_marginLeft="51dp"
android:layout_marginStart="51dp"
android:layout_alignTop="#+id/stop"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Stop"
android:id="#+id/stop"
android:layout_gravity="bottom"
android:layout_marginBottom="28dp"
android:layout_alignParentBottom="true"
android:layout_toRightOf="#+id/playPause"
android:layout_toEndOf="#+id/playPause"
android:layout_marginLeft="67dp"
android:layout_marginStart="67dp" />
</RelativeLayout>
If the user click back button from MusicPlayActivity we need to display SongListActivity so here I want to display musicpanel.
My question is what is the best practice to create musicpanel?
Right now I am including it in xml but on each activity I need to set listeners for all components of musicpanel (like play, pause, next, previous) every time
Thanks in advance
You have several options:
Create a reusable widget. Make it use your player layout, setup listeners, etc. Then add it everywhere you need.
Move your player to a notification. It would be accessible from any place in your app. Notifications are quite simple and have to be in the notification area, but you can mix this solution with 1.
Move to fragments or views. Your player could be placed above main layout using FrameLayout or RelativeLayout. This is my preffered solution.
Move your player to a floating window. It's how the floating Facebook message's head is done. Tricky to do, but nice when done properly.
Usually it's done in 1/2 or 2/3 way as these combinations reduce code duplication and are quite easy to do.
I think its best for you.Using PageViwer .
1:make 2 fragments.
(1)firstActivity
(2)SecondActivity
2:Use PageViewer in your xml layout.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="2">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.8"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight=".2"
android:background="#android:color/black"
android:weightSum="3">
<ImageView
android:id="#+id/btn1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:src="#android:drawable/ic_media_play" />
<ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:src="#android:drawable/ic_media_pause" />
<ImageView
android:id="#+id/windowbtn"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:src="#android:drawable/ic_menu_revert" />
</LinearLayout>
Here is viewPager Instance in your Main Activity.
viewPager = (ViewPager) findViewById(R.id.pager);
// viewPager.setPageTransformer(true, new VerticalPageTransformer());
mAdapter = new MultiPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
viewPager.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
viewPager.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
}
and here is Multipager adapter
public class MultiPagerAdapter extends FragmentPagerAdapter {
public MultiPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
// Top Rated fragment activity
return new FirstFragment();
case 1:
// Games fragment activity
return new SecFragment();
}
return null;
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 2;
}
}
Could someone give me an idea how to begin implementing vertical, non-linear stepper control described in the Android Material Design guide here:
http://www.google.com/design/spec/components/steppers.html
you can check this library , however this is still in development.
just extend the mobileStepperSimple class and implement the methods init,onFinished.
you can add the steppers as fragments by extending the stepperFragment and implement onNextButtonHandler to handle next button click.
check the demo for more usage.
any contributions and optimization will be helpful.
Well not exactly the same but as per my requirement, I developed custom VERTICAL STEPPER.
Below is the source code of whole demo.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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:orientation="vertical">
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"/>
</LinearLayout>
Single Item for List(Design your single item of your stepper in raw.xml file)
raw.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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_marginTop="25dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="#+id/iv_upper_line"
android:layout_width="wrap_content"
android:layout_height="20dp"
app:srcCompat="#drawable/order_status_line" />
<ImageView
android:id="#+id/iv_circle"
android:layout_width="30dp"
android:layout_height="30dp"
app:srcCompat="#drawable/circle_o" />
<ImageView
android:id="#+id/iv_lower_line"
android:layout_width="wrap_content"
android:layout_height="20dp"
app:srcCompat="#drawable/order_status_line" />
</LinearLayout>
<LinearLayout
android:id="#+id/ly_status"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="#+id/tv_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:text="Order Rcived"
android:layout_gravity="left"
android:textSize="18sp"
android:textStyle="bold" />
<LinearLayout
android:id="#+id/ly_orderstatus_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical|top"
android:orientation="horizontal">
<ImageView
android:id="#+id/imageview"
android:layout_width="20dp"
android:layout_height="20dp"
app:srcCompat="#drawable/ic_restore_black" />
<TextView
android:id="#+id/tv_orderstatus_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical|top"
android:text="8:30am,Jan 31,2018"
android:textSize="18sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
orderStatusList();
}
private void orderStatusList() {
ArrayList<OrderStatusModel> arrayOfStatus =OrderStatusModel.getStoreDetail();
OrderStatusAdapter adapter = new OrderStatusAdapter(this, arrayOfStatus);
ListView listView = (ListView) findViewById(R.id.list);
listView.setAdapter(adapter);
}
Adapter Class
class OrderStatusAdapter extends ArrayAdapter<OrderStatusModel> {
Context context;
ArrayList<OrderStatusModel> order_status;
boolean isOn = false;
public OrderStatusAdapter(Contextcontext,ArrayList<OrderStatusModel>order_status{super(context, 0, order_status);
this.context = context;
this.order_status = order_status;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
// Check if an existing view is being reused, otherwise inflate the view if(convertView==null)convertView=LayoutInflater.from(getContext()).inflate(R.layout.raw,parent,false);
}
// Get the data item for this position
OrderStatusModel order_status_data = getItem(position);
// Lookup view for data population
ImageView iv_upper_line = (ImageView)
convertView.findViewById(R.id.iv_upper_line);
ImageView iv_lower_line =(ImageView)
convertView.findViewById(R.id.iv_lower_line);
final ImageView iv_circle = (ImageView) convertView.findViewById(R.id.iv_circle);
TextView tv_status = (TextView) convertView.findViewById(R.id.tv_status);
TextView tv_orderstatus_time =(TextView)
convertView.findViewById(R.id.tv_orderstatus_time);
LinearLayout ly_orderstatus_time = (LinearLayout)
convertView.findViewById(R.id.ly_orderstatus_time);
LinearLayout ly_status = (LinearLayout) convertView.findViewById(R.id.ly_status);
// Populate the data into the template view using the data object
tv_status.setText(order_status_data.getTv_status());
tv_orderstatus_time.setText(order_status_data.getTv_orderstatus_time());
if(position == 0){
iv_upper_line.setVisibility(View.INVISIBLE);
}
else if (position == order_status.size()-1){
iv_lower_line.setVisibility(View.INVISIBLE);
ly_orderstatus_time.setVisibility(View.GONE);
}
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
iv_circle.setBackgroundResource(R.drawable.bullseye);
Toast.makeText(context, "You Clicked at
item"position,Toast.LENGTH_SHORT).show();
}
});
// Return the completed view to render on screen
return convertView;
}
}
Model Class
private String tv_status;
private String tv_orderstatus_time;
public OrderStatusModel(String tv_status, String tv_orderstatus_time) {
this.tv_status = tv_status;
this.tv_orderstatus_time = tv_orderstatus_time;
}
public String getTv_status() {
return tv_status;
}
public void setTv_status(String tv_status) {
this.tv_status = tv_status;
}
public String getTv_orderstatus_time() {
return tv_orderstatus_time;
}
public void setTv_orderstatus_time(String tv_orderstatus_time) {
this.tv_orderstatus_time = tv_orderstatus_time;
}
public static ArrayList<OrderStatusModel> getStoreDetail() {
ArrayList<OrderStatusModel> status = new ArrayList<OrderStatusModel>();
status.add(new OrderStatusModel("Order Rcived", "8:30am,Jan 31,2018"));
status.add(new OrderStatusModel("On The Way", "10:30am,Jan 31,2018"));
status.add(new OrderStatusModel("Delivered", "aaaaaa"));
return status;
}
Because no Support Library solution exists (still) I have tried several of these libraries in a recent project. My favourite (for appearance, smoothness and functionality) was This Project by "ernestoyaquello". I also added some options to it on My Fork.
The only thing to note with this, is that it does not use an 'adapter' class but instead uses a callback interface.
Demo Screen from Git:
I am making an activity which has a section for comments based on addresses inputed by the user.
The user will add a new comments section by pressing a button. This is a non fixed number of sections, so I have initially added this section as a fragment in the xml.
I have an onClick function that adds another fragment to the linearlayout.
My problem is that the new fragments always add to the top of the linearlayout , i.e. above the existing fragment/fragments (i.e. the new fragment will push all the other fragments down).
How can I add the new fragment so that it displays below the existing fragment?
Code in .java file:
public class SpecialReportAdden extends ActionBarActivity {
int numOfFragments;
LinearLayout addenHolder;
TextView report;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_special_report_adden);
numOfFragments=1;
Button addenSave = (Button)findViewById(R.id.btnAddendumSave);
Button addenAddComment = (Button)findViewById(R.id.btnAddendumAddComment);
addenHolder =(LinearLayout)findViewById(R.id.AddenLinLayHolder);
addenSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//this should save all comments including those added in dynamically produced fragments
//save database
Intent i = new Intent (SpecialReportAdden.this, MenuPage.class);
startActivity(i);
}
});
addenAddComment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i("number of Fragments at start of OnClick", Integer.toString(numOfFragments));
Fragment newAddenFrag = addNewfragment(numOfFragments);
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.AddenLinLayInnerHolder, newAddenFrag);
ft.addToBackStack(null);
ft.commit();
numOfFragments++;
Log.i("number of Fragments updated", Integer.toString(numOfFragments));
}
});
}
public Fragment addNewfragment(int number) {
AddendumLinInputFragment adden = new AddendumLinInputFragment();
TextView tx = (TextView) findViewById(R.id.txtVAddendumFragReportNum);
tx.setText("Report "+number+" :");
tx.setTextColor(Color.BLACK);
TextView address = (TextView)findViewById(R.id.txtVAddendumFragAddress);
address.setText("A new address");
address.setTextColor(Color.BLUE);
return adden;
}
xml file for the .java activity
<RelativeLayout 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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="com.example.danielt.pestcontrol.SpecialReportAdden"
android:id="#+id/RellayAddenComments">
<TextView
android:id="#+id/txtVAddendumTitle" android:text="Service Report Addendum" android:textStyle="bold" android:layout_centerHorizontal="true" android:elegantTextHeight="true" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"/>
<TextView
android:id="#+id/txtVAddendumTechName"
android:layout_below="#+id/txtVAddendumTitle"
android:layout_marginTop="16dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Technician Name: "
android:textSize="18sp"
/>
<TextView
android:id="#+id/txtVAddendumDate"
android:layout_below="#+id/txtVAddendumTechName"
android:layout_marginTop="16dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Date: "
android:textSize="18sp"
/>
<ScrollView
android:id="#+id/scrlVAddendum"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/txtVAddendumDate">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/AddenLinLayHolder"
android:orientation="vertical">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/AddenLinLayInnerHolder"
android:orientation="vertical">
<fragment
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:name="com.example.danielt.pestcontrol.AddendumLinInputFragment"
android:id="#+id/addendum1CommentsFragment"
android:layout_below="#+id/txtVAddendum1Date"
android:layout_marginTop="24dp"
tools:layout="#layout/fragment_addendum_lin_input" />
</LinearLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add another Addendum Comment"
android:id="#+id/btnAddendumAddComment"
android:layout_below="#+id/scrlVAddendum"
android:layout_centerHorizontal="true"
android:layout_marginTop="36dp" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Save / Update Comments"
android:id="#+id/btnAddendumSave"
android:layout_below="#+id/btnAddendumAddComment"
android:layout_centerHorizontal="true"
android:layout_marginTop="44dp" />
</LinearLayout>
</ScrollView>
I havent added the fragment code but I will if someone wants to see it.
Thanks for any help.
You don't need fragment to hold only comment view. Just inflate new comment view and add it to the parent view.
LayoutInflater inflater = LayoutInflater.from(context);
View inflatedLayout= inflater.inflate(R.layout.yourLayout, container, false);
container.addView(inflatedLayout);
Where container is a view that hold all comments.
Regarding adding fragments, according to Fragments documentation:
If you're adding multiple fragments to the same container, then the
order in which you add them determines the order they appear in the
view hierarchy
Therefore if it's behave different, it could be related to OS version or bug :)