here is my OnClick Activity
lst.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> lst, View view,
int position, long id) {
Intent intent1;
// int itemPosition=lst.;
switch (position) {
case 0:
I would want to add my action point at every case:
Related
so I have an application that is as follows:
login page where the user enters his credentials and can access the main app if his credentials are correct. and if he checks the remember me checkbox, his username and password will be saved in shared preferences so that he can directly go to the main app in the second time.
the main app has a tabbed layout with a viewpager. in one of the tabs, which is a fragment, I use a recyclerview to display data, that I get from a database, in rows.
now in each row there is a reply button that will show details corresponding to each row when clicked. the details will be shown in a new fragment.
so the point is that I managed to replace the tab's fragment with the new fragment using this code in the recyclerview's adapter:
public class recyclerviewAdapter : RecyclerView.Adapter
{
// Event handler for item clicks:
public event EventHandler<int> ItemClick;
List <summary_request> summary_Requests=new List<summary_request>();
//Context context;
public readonly stores_fragment context;
public recyclerviewAdapter(stores_fragment context, List<summary_request> sum_req)
{
this.context = context;
summary_Requests = sum_req;
}
public override RecyclerView.ViewHolder
OnCreateViewHolder(ViewGroup parent, int viewType)
{
View itemView = LayoutInflater.From(parent.Context).
Inflate(Resource.Layout.recycler_view_data, parent, false);
recyclerview_viewholder vh = new recyclerview_viewholder(itemView, OnClick);
return vh;
}
public override void
OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
recyclerview_viewholder vh = holder as recyclerview_viewholder;
vh.by_user.Text = summary_Requests[position].By;
vh.warehousename.Text = summary_Requests[position].warehousename;
vh.project.Text = summary_Requests[position].project;
vh.operations_note.Text = summary_Requests[position].destination_Note;
vh.source_Note.Text = summary_Requests[position].source_Note;
vh.stockType.Text = summary_Requests[position].stockType;
vh.requestStatus.Text = summary_Requests[position].requestStatus;
vh.reply.Click += delegate
{
summary_detail_req fragment = new summary_detail_req();
var fm = context.FragmentManager.BeginTransaction();
fm.Replace(Resource.Id.frameLayout1, fragment);
fm.AddToBackStack(null);
fm.Commit();
int nb = context.FragmentManager.BackStackEntryCount;
Toast.MakeText(context.Context, nb.ToString(), ToastLength.Long).Show();
};
}
private void Reply_Click(object sender, EventArgs e)
{
Toast.MakeText(context.Context, "reply" , ToastLength.Long).Show();
}
public override int ItemCount
{
get { return summary_Requests.Count; }
}
// Raise an event when the item-click takes place:
void OnClick(int position)
{
if (ItemClick != null)
ItemClick(this, position);
}
}
but my context.FragmentManager.BackStackEntryCount remain zero! I don't get it. in my main activity, I am using this code for the backpress function:
stores_fragment.recyclerviewAdapter adapter;
public override void OnBackPressed()
{
string userName = pref.GetString("Username", String.Empty);
string password = pref.GetString("Password", String.Empty);
if (userName != String.Empty || password != String.Empty && adapter.context.FragmentManager.BackStackEntryCount == 0)
{
this.FinishAffinity();
}
else
base.OnBackPressed();
}
but i'm not getting what i want. this function is getting me out of the whole app.the first part of the if statement is because without it, when the I press the back button from the main activity it takes me back to the login page and I don't want that.
my question is what should I do to manage my fragments and the backpress function?
thanks in advance.
so the point is that I managed to replace the tab's fragment with the new fragment using this code in the recyclerview's adapter
According to your description, you want to open another fragment from recyclerview Button.click, if yes, please take a look the following code:
on OnBindViewHolder
int selectedindex;
// Fill in the contents of the photo card (invoked by the layout manager):
public override void
OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
selectedindex =position;
PhotoViewHolder vh = holder as PhotoViewHolder;
// Set the ImageView and TextView in this ViewHolder's CardView
// from this position in the photo album:
vh.Image.SetImageResource(mPhotoAlbum[position].PhotoID);
vh.Caption.Text = mPhotoAlbum[position].Caption;
vh.btnreply.Click += Btnreply_Click;
}
To show detailed activity. MainActivity is the current activity for recyclerview.
private void Btnreply_Click(object sender, EventArgs e)
{
Showdetailed(selectedindex);
}
private void Showdetailed(int position)
{
var intent = new Intent();
intent.SetClass(MainActivity.mac, typeof(DetailsActivity));
intent.PutExtra("selectedid", position);
MainActivity.mac.StartActivity(intent);
}
The detailedactivity.cs:
public class DetailsActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your application here
var index = Intent.Extras.GetInt("selectedid", 0);
var details = DetailsFragment.NewInstance(index); // Details
var fragmentTransaction = FragmentManager.BeginTransaction();
fragmentTransaction.Add(Android.Resource.Id.Content, details);
fragmentTransaction.Commit();
}
}
The DetailsFragment.cs:
public class DetailsFragment : Fragment
{
public int ShownPlayId => Arguments.GetInt("selectedid", 0);
public static DetailsFragment NewInstance(int index)
{
var detailsFrag = new DetailsFragment { Arguments = new Bundle() };
detailsFrag.Arguments.PutInt("selectedid", index);
return detailsFrag;
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Use this to return your custom view for this Fragment
// return inflater.Inflate(Resource.Layout.YourFragment, container, false);
if (container == null)
{
// Currently in a layout without a container, so no reason to create our view.
return null;
}
var scroller = new ScrollView(Activity);
var text = new TextView(Activity);
var padding = Convert.ToInt32(TypedValue.ApplyDimension(ComplexUnitType.Dip, 4, Activity.Resources.DisplayMetrics));
text.SetPadding(padding, padding, padding, padding);
text.TextSize = 24;
Photo photo =PhotoAlbum.mBuiltInPhotos[ShownPlayId];
text.Text = photo.Caption;
scroller.AddView(text);
return scroller;
}
}
About implementing fragment, you can take a look:
https://learn.microsoft.com/en-us/samples/xamarin/monodroid-samples/fragmentswalkthrough/
I'm using viewpager to display pictures. I just need three fragments basically: previous image to preview, current display image and next image to preview. I would like to just display a preview of previous and next image, it will change to full image when user actually swipe to it. So I'm thinking of just using 3 fragment to achieve this. Code is below:
private class ImagePagerAdapter extends FragmentStatePagerAdapter implements ViewPager.OnPageChangeListener {
private ImageFragment mImageFragment;
private ImagePreviewFragment mPreviousPreviewFragment;
private ImagePreviewFragment mNextPreviewFragment;
public ImagePagerAdapter(FragmentManager fm, ImageFragment image, ImagePreviewFragment previous, ImagePreviewFragment next) {
super(fm);
mImageFragment = image;
mPreviousPreviewFragment = previous;
mNextPreviewFragment = next;
}
#Override
public Fragment getItem(int position) {
if (position == mPager.getCurrentItem()) {
mImageFragment.display(position);
return mImageFragment;
}
if (position < mPager.getCurrentItem()) {
mPreviousPreviewFragment.display(position - 1);
return mPreviousPreviewFragment;
}
mNextPreviewFragment.display(position + 1);
return mNextPreviewFragment;
}
#Override
public int getCount() {
return 100;
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
Log.d(TAG, "onPageScrolled");
}
#Override
public void onPageSelected(final int position) {
Log.d(TAG, "onPageSelected " + position);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
notifyDataSetChanged();
}
}, 500);
}
#Override
public void onPageScrollStateChanged(int state) {
Log.d(TAG, "onPageScrollStateChanged " + state);
}
#Override
public int getItemPosition(Object item) {
return POSITION_NONE;
//return POSITION_UNCHANGED;
}
}
So basically, I pre-created three fragments to display previous/next preview and current image and return them for getItem(). I also notifydatasetchange() in onpageselected() to make all three position to update the fragment when user swipe to new page.
But the problem is that it will throw out
Fragment already added IllegalStateException
when the fragments are added a second time. I think it's because it's been added before. I can create a new fragment every time but I think that's wasteful. So how can I reuse the already created fragment and just update them?
Thanks,
Simon
FragmentStatePagerAdapter design suggests creating a new Fragment for every page (see Google's example). And unfortunately you cannot readd a Fragment once it was added to a FragmentManager (what implicitly happens inside adapter), hence the exception you got. So the official Google-way is to create new fragments and let them be destroyed and recreated by the adapter.
But if you want to reuse pages and utilize an analogue of ViewHolder pattern, you should stick to views instead of fragments. Views could be removed from their parent and reused, unlike fragments. Extend PagerAdapter and implement instantiateItem() like this:
#Override
public Object instantiateItem(ViewGroup container, final int position) {
//determine the view type by position
View view = viewPager.findViewWithTag("your_view_type");
if (view == null) {
Context context = container.getContext();
view = LayoutInflater.from(context).inflate(R.layout.page, null);
view.setTag("your_view_type");
} else {
ViewGroup parent = (ViewGroup) item.getParent();
if (parent != null) {
parent.removeView(item);
}
}
processYourView(position, view);
container.addView(view, MATCH);
return view;
}
You should add some extra logic to determine the view type by position (since you have 3 types of views), I think you can figure that out.
I need help with reloading a Fragment that is part of a ViewPager. Here is my current setup:
ReportActivity extends FragmentActivity and uses ViewPager to host 4 Tabs
TAB 1 to 4. Each Tab is a Fragment with seperate layout.
ViewPager uses TabsPagerAdapter to switch between the tabs and this works as expected.
TAB1Fragment displays a graph using a static dataset. Now I have added a spinner to dynamically change the dataset and I am looking for ways to reload the Fragment so it can re-display the graph with the correct dataset. The following ints correspond to the values of the Spinner.
static final int REPORT_PERIOD_DAY = 0;
static final int REPORT_PERIOD_WEEK = 1;
static final int REPORT_PERIOD_MONTH = 2;
static final int REPORT_PERIOD_YEAR = 3;
I have a method that correctly calculates the correct data based on the the int passed in, what I am struggling with is how to create an Intent or any other method that will recreate TAB1Fragment and passes it an int parameter.
Here is where I want to re-create the Fragment
mReportPeriodSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
switch (position){
case 0:
//How can I re-load the Fragment here?
reloadFragment(REPORT_PERIOD_DAY);
break;
case 1:
reloadFragment(REPORT_PERIOD_WEEK);
break;
case 2:
reloadFragment(REPORT_PERIOD_MONTH);
break;
case 3:
reloadFragment(REPORT_PERIOD_YEAR);
break;
}
}
Please can you give me an idea of how to write the code that goes into the method reloadFragment(Int period)
I would recommend re-configuring the existing fragment, rather than constructing a new fragment with the new report period.
I'm guessing that you currently configure your graph inside TAB1Fragment's onCreateView. If you move that configuration code to onResume, then you can call the same function when the user selects something in the spinner.
public class TAB1Fragment extends Fragment {
int reportPeriod;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = ...
reportPeriod = REPORT_PERIOD_DAY; // default report period
return rootView;
}
#Override
public void onResume() {
super.onResume();
configureGraph();
}
private void configureGraph() {
//TODO put all the code that draws your graphs here, using reportPeriod
}
public void reloadFragment(int reportPeriod) {
this.reportPeriod = reportPeriod;
configureGraph();
}
}
If this approach really doesn't work for you, and you really need a new fragment each time, then this question explains how to get the tag for a fragment so that you can tell the FragmentManager to replace it:
Replace Fragment inside a ViewPager
I have 3 ListFragments being handled by a viewPager (managed by a FragmentAdapter) - they work perfectly. Now when the user clicks an item in ListFragment #1, a new Fragment should open with the details. It's behaving strangely in the following manner:
Only clicking a list item twice opens the DetailFragment, yet debugging shows the first click indeed goes into the DetailFragment, but doesn't show the view (the view still shows the current ListFragment).
After clicking the 2nd time, the DetailFragment does show it's layout, but not the elements within it (like TextView, etc).
If the user 'accidently' swipes the screen when DetailFragment is showing, the viewPager sets it in place of the 2nd ListFragment! Only when pressing back on the DetailFragment view will 'reset' the viewPager to it's correct ListFragment. Of course if the user swipes when in a DetailFragment, the next ListFragment of the viewPager should appear, and the DetailFragment should be removed.
Thanks for any tips muddling through Android's odd world of fragments and views :)
public class PlanetFragment extends ListFragment{
LayoutInflater inflater;
ListView list;
ArrayList<HashMap<String, String>> planetListArray;
HashMap<String, String> planetMap;
Activity activity;
Context context;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.planets_tab_layout, container, false);
inflater=(LayoutInflater)getLayoutInflater(savedInstanceState);
activity = getActivity();
context = PlanetFragment.this.getActivity();
String dbTableName = "Table_Planets";
SQLiteHelper info = new SQLiteHelper(getActivity().getBaseContext());
info.open();
ArrayList<HashMap<String, String>> datafromSQL = info.getData(dbTableName);
if(!datafromSQL.isEmpty()){
planetListArray = new ArrayList<HashMap<String, String>>();
for (int i = 0; i<datafromSQL.size(); i++){
planetMap = new HashMap<String, String>();
planetMap.put(PLANET_ID, datafromSQL.get(i).get(KEY_PLANET_ID));
planetMap.put(ZODIAC_ID, datafromSQL.get(i).get(KEY_ZODIAC_ID));
planetMap.put(DEGREES, datafromSQL.get(i).get(KEY_DEGREES));
planetMap.put(CONTENT, datafromSQL.get(i).get(KEY_CONTENT));
planetListArray.add(planetMap);
}
info.close();
}
list = (ListView) v.findViewById(android.R.id.list);
PlanetAdapter adapter=new PlanetAdapter(getActivity(), R.layout.planets_row, planetListArray);
list.setAdapter(adapter);
return v;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//the dividers
getListView().setDivider(getResources().getDrawable(R.drawable.purplebartop));
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
HashMap<String, String> item = planetListArray.get(position);
Bundle bundle = new Bundle();
bundle.putSerializable("itemMap", item);
bundle.putInt("position", position);
Fragment frag = DetailFragment.newInstance();
frag.setArguments(bundle);
if (frag != null) {
getActivity().getSupportFragmentManager()
.beginTransaction()
.replace(R.id.pager, frag, "frag")
.addToBackStack("frag")
.commit();
}
}
}
public class DetailFragment extends Fragment{
Context context;
Activity activity;
TextView planetName;
public static android.support.v4.app.Fragment newInstance() {
DetailFragment f = new DetailFragment();
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
inflater=(LayoutInflater)getLayoutInflater(savedInstanceState);
View v = inflater.inflate(R.layout.dialog_details, container, false);
activity = getActivity();
context = DetailFragment.this.getActivity();
planetName = (TextView)v.findViewById(R.id.planetNameExpanded);
planetName.setText("planetX");
return v;
}
}
EDIT:
Instead of getActivity().getSupportFragmentManager() I have also tried getChildFragmentManager() but it always gives the error: The method getChildFragmentManager() is undefined for the type PlanetFragment.
When you click on a list item, you are indeed constructing a new details fragment and telling the fragment manager to replace the tag "frag" with that fragment. However, you are not telling the view pager to switch over to that fragment.
Since you already have a back-pointer to your activity, you could use findViewById to find your view pager, and then call viewPager.setCurrentItem.
I think you might be asking for trouble by constructing a new details fragment inside of the list fragment. When you use a FragmentPagerAdapter, the adapter usually constructs the fragments. I would have implemented this by letting the adapter make the fragments, and then in your onListItemClick find the existing details fragment and call a method on it to configure it with the new data. But maybe just the setCurrentItem will fix your problem.
EDIT
First, I would write your FragmentPagerAdapter so you can use getItem to fetch the existing fragment, without creating a new one each time.
public class PlanetFragmentAdapter extends FragmentPagerAdapter {
private Fragment [] fragments = new Fragments[3];
public PlanetFragmentAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return 3;
}
#Override
public Fragment getItem(int position) {
Fragment fragment = fragments[position];
if (fragment == null) {
switch (position) {
case 0:
fragment = new PlanetFragment();
break;
case 1:
fragment = new DetailFragment();
break;
case 2:
fragment = new MysteryFragment();
break;
}
fragments[position] = fragment;
}
return fragment;
}
}
Also add functions in your activity to work with your fragments:
public void setPage(int position) {
viewPager.setCurrentItem(position);
}
public DetailFragment getDetailFragment() {
return (DetailFragment) viewPager.getItem(1); // now it doesn't create a new instance
// you could also use getSupportFragmentManager().findFragmentById() here
}
Now when you click on an item in your list fragment, you can get the existing detail fragment, configure it, and set the ViewPager to show the detail fragment.
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
HashMap<String, String> item = planetListArray.get(position);
Bundle bundle = new Bundle();
bundle.putSerializable("itemMap", item);
bundle.putInt("position", position);
PlanetActivity pa = (PlanetActivity) activity;
DetailFragment frag = pa.getDetailFragment();
frag.setArguments(bundle);
pa.setCurrentItem(1);
}
In my application i have created a simple custom dialog. I have to call that in a fragment class.Dont know how to proceed can anyone help me with this? Is there any way that we can use simple dialog in fragment without going for Dialogfragment?
using dialog fragment would be the better practice.
Dialog Fragment They have given different dialog fragment concepts will match all the needs related to dialog. other than this
Simple alert dialog in fragment
AlertDialog ad = new AlertDialog.Builder(getActivity())
.create();
ad.setCancelable(false);
ad.setTitle(title);
ad.setMessage(message);
ad.setButton(context.getString(R.string.ok_text), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
ad.show();
custom dialog in fragment
final Dialog dialog = new Dialog(getActivity);
dialog.setContentView(R.layout.custom);
dialog.setTitle("Title...");
// set the custom dialog components - text, image and button
TextView text = (TextView) dialog.findViewById(R.id.text);
text.setText("Android custom dialog example!");
ImageView image = (ImageView) dialog.findViewById(R.id.image);
image.setImageResource(R.drawable.ic_launcher);
Button dialogButton = (Button) dialog.findViewById(R.id.dialogButtonOK);
// if button is clicked, close the custom dialog
dialogButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
dialog.show();
UPDATE 1 :
Here i give u one example that i used to show date picker using dialog fragment
public static class SelectDateFragment extends DialogFragment implements
DatePickerDialog.OnDateSetListener {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Calendar calendar = Calendar.getInstance();
int yy = calendar.get(Calendar.YEAR);
int mm = calendar.get(Calendar.MONTH);
int dd = calendar.get(Calendar.DAY_OF_MONTH);
return new DatePickerDialog(getActivity(), this, yy, mm, dd);
}
#Override
public void onDateSet(DatePicker view, int yy, int mm, int dd) {
dobString = myYear + "-" + myMonth + "-" + myDay;
populateSetDate(yy, mm + 1, dd);
}
#Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
}
}
And to show the dialog
public void selectDate(View view) {
DialogFragment newFragment = new SelectDateFragment();
newFragment.show(getSupportFragmentManager(), "DatePicker");
}
which will be called from a button click..