Context: I'm using the Wizard with in Eclipse and ADT to get a master detail view framework.
I have a good understanding of the fragments need to sit with in an activity and that with in a view etc how ever looking at the example I'm trying to work out how best to change it so I can start developing a app my self.
Is the 'dummy' content view actually needed ? All it seems to contain is the menu options ?
The questions I have is does any one know how the detail view is created ? From what I am reading the app is just taking the item ID and placing it in the detail view as text ?
Extract from Itemdetailfragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_item_detail, container, false);
if (mItem != null) {
((TextView) rootView.findViewById(R.id.item_detail)).setText(mItem.content);
}
return rootView;
}
Is the best way to re do a detail fragment for each new screen I need and place some logic behind that or code the existing one to look at the menu option selected and display the right code ?
Finally is this the best example to start working with ?
The questions I have is does any one know how the detail view is
created ? From what I am reading the app is just taking the item ID
and placing it in the detail view as text ?
Yes, that is exactly what it is doing. This is done in the detail fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_team_detail,
container, false);
// Show the dummy content as text in a TextView.
if (mItem != null) {
((TextView) rootView.findViewById(R.id.team_detail))
.setText(mItem.content);
}
return rootView;
}
You need to change it to get whatever data you need from whatever source you want to use (website, database or change the hard coded values
If you look at the DummyContent.java class you will see the comment
/** TODO: Replace all
uses of this class before publishing your app. */
Basically you should re-write this class to get the data that you want
I've actually added action bar sherlock to make this compatible with api 8 with a little help from this question Two questions about Master/Detail Flow Template
There is a hint that you could use ContentLoader in conjunction with a ContentProvider to get your data from another source such as a database or a web service
Related
I started a TabLayout Activity, which includes the following code to create the fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_find, container, false);
TextView textView = (TextView) rootView.findViewById(R.id.section_label);
textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView;
}
I've read the official documentation and still unsure how it works. If somebody could explain in detail how each part here is working that would be great.
Edit: Mainly referring to View rootView = inflater.inflate(R.layout.fragment_find, container, false); what each of these 3 parameters are doing and how inflater.inflate() is working here.
OK, here we go.
The process of inflating is simply creating your view explicitly instead of doing this implicitly, this is by using this:
public void onCreate(){
setContentView(R.layout.your_layout);
}
Compare with this question.
Now with the arguments. Compare this with this section.
R.layout.fragment_find returns ID of a fragment used somewhere in the code. R is a dynamic android class used for manipulating some of your app's resources such as views, strings etc. Compare.
container is a root from some ViewGroup. So you hgave a group of, say, buttons doing common things (for example choosing some colour in your application), and they all have same parent, in your case called a container.
attachToRoot is the last argument. According to docs:
If false, root is only used to create the correct subclass of LayoutParams for the root view in the XML.
So it is not attached to the parent we talked about in last point. Compare here.
I hope this helped.
onCreateView():
After the onCreate() is called (in the Fragment), the Fragment's onCreateView() is called. You can assign your View variables and do any graphical initialisations. You are expected to return a View from this method, and this is the main UI view, but if your Fragment does not use any layouts or graphics, you can return null (happens by default if you don't override).
Here, it's a method of the lifecycle for Fragment.
Bacground
I have been working on stripping out a library that deals with adding Accessibility with Talkback that I have created in an existing app. Originally my custom views were all ViewGroups, so I got everything working amazingly with ViewGroups (focusable navigation with D-pad, initial view focus, and content descriptions)
When I was moving this to a standalone library, I noticed that it didn't work with View. I thought ViewGroup was the superclass, but it turns out that View is the superclass. So I have been trying to find some workarounds to fix my issue. I started to do the following, and have a question based on this approach...
Code In Question
public class Accessibility {
public static ViewGroupAccessibility with(ViewGroup viewGroup) {
return new ViewGroupAccessibility(viewGroup);
}
public static ViewAccessibility with(View view){
return new ViewAccessibility(view);
}
}
I have fully implemented ViewGroupAccessibility and I intend to fully implement ViewAccessibility as it is a stub right now. So far the below code works well with TalkBack, I can do ViewGroup related stuff with ViewGroups, and it appears that I can do View related stuff with Views; however, I am wondering if this is even needed
What I know
Accessibility.with(new RelativeLayout(...)) // Returns ViewGroupAccessibility as RelativeLayout is a ViewGroup
//
...will return a ViewGroupAccessibility that can handle ViewGroup related stuff that can contain many different View and ViewGroup. (See code at the bottom of this post for real usage, and what what methods are available for ViewGroupAccessibility)
Accessibility.with(new Button(...)) // Returns ViewAccessibility as Button is a View
//
...will return a ViewAccessibility that can handle single View only related stuff (that is my assumption). Think only a Button.
What I don't know
// Hypothetical Usage
Accessibility
.with(new ClassThatExtendsView_WithMultipleComponentsThatCanHaveAccessibilitySetOnEachComponentIndividually(...));
// Custom View that extends View
public class ClassThatExtendsView_WithMultipleComponentsThatCanHaveAccessibilitySetOnEachComponentIndividually extends View {
...
}
Is this even possible? If no, then I am good. If yes, then I have a lot extra to think about
It will return a ViewAccessibility that can handle single View only, but then that would be the wrong thing to return.
Another way of asking the question is am I guaranteed that if a user calls Accessibility.with(View) that the given view will ALWAYS be a single view only? Like Just a single Button. Or can the View be made of more than one component
Full Code
You can check out the code at https://codereview.stackexchange.com/questions/134289/easily-add-accessibility-to-your-app-as-an-afterthought-yes-as-an-afterthought (there is also a GitHub link to the original code). I go in incredible detail into how the project was started, my design decisions, and my future goals all to help guide the code review process.
However, here is a snippet of a usage I have for ViewGroup
public class ContributionView extends RelativeLayout implements Mappable<Resume.Contribution> {
// Called from Constructors
private void init(AttributeSet attrs, int defStyle) {
root = (ViewGroup) LayoutInflater.from(getContext()).inflate(
R.layout.internal_contribution_view, this, true);
...
// Declare Navigation Accessibility
Accessibility.with(root)
// Disable certain views in the ViewGroup from ever gaining focus
.disableFocusableNavigationOn(
R.id.contribution_textview_creator,
R.id.contribution_textview_year)
// For all focusable views in the ViewGroup, set the D-pad Navigation
.setFocusableNavigationOn(txtProjectName)
.down(R.id.contribution_textview_description).complete()
.setFocusableNavigationOn(txtContributionDescription)
.up(R.id.contribution_textview_name)
.down(R.id.contribution_textview_link).complete()
.setFocusableNavigationOn(txtProjectLink)
.up(R.id.project_textview_description).complete()
// Set which view in the ViewGroup will have be first to be focused
.requestFocusOn(R.id.contribution_textview_name);
invalidateView();
}
private void invalidateView() {
...
// Declare Content Description Accessibility
Accessibility.with(root)
// Set the content descriptions for each focusable view in the ViewGroup
// Set the content description for the Contribution Name
.setAccessibilityTextOn(txtProjectName)
.setModifiableContentDescription(getProjectName())
.prepend("Contribution occurred on the Project called ")
.append(String.format(" by %s in %s",
getProjectCreator(),
getContributionYear())).complete()
// Set the content description for the Contribution Description
.setAccessibilityTextOn(txtContributionDescription)
.setModifiableContentDescription(getContributionDescription())
.prepend("Description: ").complete()
// Set the content description for the Contribution URL
.setAccessibilityTextOn(txtProjectLink)
.setModifiableContentDescription(getProjectLink())
.prepend("URL is ").complete();
}
...
}
Yes, there is a way to move accessibility amongst the various areas/components of a View. It requires a little work, though.
Start here:
https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeProvider.html
I have a requirement where I need to display PDF file within my Android app. I have used PDFViewer.jar to do so in some of my Activities, which is explained here https://github.com/jblough/Android-Pdf-Viewer-Library . Now I am stuck up with displaying PDF file inside a Fragment. But PDFViewer.jar has been limited to Activity. I have seen the source code of PDFViewer.jar and am unable to convert it for Fragment. Can anyone help me please.
Thanks
You should take, PdfViewerActivity.java (https://github.com/jblough/Android-Pdf-Viewer-Library/blob/master/src/net/sf/andpdf/pdfviewer/PdfViewerActivity.java), rename it to PdfViewerFragment.java.
Change extends Activity to extends Fragment in Android Studio, and correct each red line.
Also, don't forget to import the rest of the project (or you'll have missing classes)
You should especially change each need of Context (this) by getActivity() and findViewById() by getView().findViewById(R.id.foo).
Surely, it won't be enough, but it's a good place to start.
This is load PDF in fragment use PDFViewer
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_keluarga, container, false);
pdfView = (PDFView) v.findViewById(R.id.keluargaPdf);
pdfView.fromAsset("tiga.pdf").load();
// Inflate the layout for this fragment
return v;
}
I'm trying make an app that displays a big amount of text and images in a specific layout when the user clicks on a corresponding listview item. Since I want specific .xml layouts for separate 'chapters', I want only the layout of a fragment to change to the corresponding chapter.
Googling tells me I can do this with fragments, but as far as I understand, I need separate fragment classes and .xml layouts for every chapter I want to implement. With 2 or 3 chapters, that can be done, but with more chapters that will become I thought, isn't it simpler to just keep two fragments (one with a listview and one with the chapter text), but dynamically change the layout of the second fragment if the user clicks on an item in the listview.
Can this be done with some code like this (just thinking out loud)?
Int[] layouts = {
{R.layout.chapter1, R.layout.chapter2, R.layout.chapter3}
};
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
index = intent.getIntent("index", 0);
return inflater.inflate(layouts[index], container, false);
}
Or is there another way to achieve this?
Fragments at their core are View wrappers that contains states of Views. You can use them for other purposes like resource handling, but mostly they're just segments of an Activity state. It most likely would not be a good idea to have a Fragment for every single chapter unless each chapter has their own unique state that needs to be kept. However, if the Views are static, then a single Fragment is all you really need.
In this case, you simply have to have a method like this:
public void setChapter(int chapter)
{
Context ctx = getActivity();
if(ctx == null) {
// detached from Activity, so bail.
return;
}
if(chapter > layouts.length) {
return;
}
ViewGroup container = (ViewGroup) getView().findViewById(R.id.chapter_container);
container.removeAllViews();
View chapterInflater = LayoutInflater.from(ctx).inflate(layouts[chapter], container);
}
So this will wipe out all views currently in your container, inflate a new one, and put it in the container (most likely a simple FrameLayout).
The code in the original question can be used to initialize a Fragment if you want to open it at a certain point. onCreate_() methods are called only when the items is being "built" or "created". onCreateView() won't be called again though, so you need a method to change the layout once it's set.
I'm writing a calculator application in which I would like to be able to switch between 4 modes of calculation: Decimal, Binary, Octal, and Hex. In order to manage the different UIs for the different modes, I have 4 Fragment subclasses in my Activity. Each Fragment has its own XML layout file, in addition to the main XML file for the Activity. I found a guide on the Android Developer site for inflating layouts for Fragments, and I've followed that guide. However, I would like to add listeners and so on to the various components of the layouts, preferably within the onCreateLayout method of the Fragment, or somewhere else where I could do it easily and minimize code duplication.
It appears, however, that when I try to call findViewByID to access one of the inflated Views (after I've called LayoutInflater.inflate, obviously), I get a null return value. This issue occurs whether I call findViewByID from within onCreateLayout or from elsewhere in the Activity (after the Views have, theoretically, been created). What's going wrong here?
One issue I think might be a problem is that I've overloaded the names of the Views between the various Fragment layouts. For example, the "1" button in the Binary layout has the same ID as the "1" button in the Hex layout. Is this allowed, assuming the Binary and Hex layouts are never both part of the Activity at the same time?
Thanks.
I think same id in different layout is not problem in Fragement. First you have to catch the inflated view then find whatever inside this. For example --
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.frg1, container, false);
android.util.Log.v("", "!!!!!!!!!! Frg1 !!!!!!!!!");
Button b = (Button) view.findViewById(R.id.b1);
b.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
Toast.makeText(getActivity(), "here", Toast.LENGTH_SHORT).show();
}
});
return view;
}