What's the difference of this two view using View.inflate - android

Following is a xml: welcome_view.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/root_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white" >
<ImageView
android:id="#+id/welcome_bg"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.demo.src.WelcomeLayout
android:id="#+id/welcome_ad"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
This is the MainActivity, I setContentView with layout welcome_view.xml.
class MainActivity extends Activity
{
onCreate()
{
setContentView(R.layout.welcome_view);
ViewGroup view1 = findViewByID(R.id.ad_view);
}
}
WelcomeLayout has been contained in the welcome_view.xml. Please tell me the view in the following class is different with the one in above class??? Why, tell me some the inner mechanism.
class WelcomeLayout extends FrameLayout
{
onCreate()
{
super(context);
View.inflate(context, R.layout.welcome_view, null);
ViewGroup view2 = findViewById(R.id.ad_view);
}
}
Thanks!

reference:Difference between setContentView and LayoutInflater
setContentView is an Activity method only. Each Activity is provided with a FrameLayout with id "#+id/content" (i.e. the content view). Whatever view you specify in setContentView will be the view for that Activity. Note that you can also pass an instance of a view to this method, e.g. setContentView(new WebView(this)); The version of the method that you are using will inflate the view for you behind the scenes.
on the other hand, have a lifecycle method called onCreateView which returns a view (if it has one). The most common way to do this is to inflate a view in XML and return it in this method. In this case you need to inflate it yourself though. Fragments don't have a "setContentView" method
Note:link might be destroy so answer pasted.

Related

Accessing views outside of onCreateView() method

I am trying to make a particular nested FrameLayout visible dynamically. However, i am getting NullPointerException when i try to access the view outside of my fragment's onCreateView() method. So here is my implementation.
private View myView;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View fragmentView = inflater.inflate(R.layout.listView, container, false);
this.myView = fragmentView;
...
return fragmentView;
}
#Override
public void apiCompleted(ApiResult apiResult, HttpRequest httpRequest) {
if(myLocationManager.hasLocation()){
FrameLayout flayout = (FrameLayout) myView.findViewById(R.id.ldrawlayout);
flayout.setVisibility(View.VISIBLE);
}
}
listView.xml
<LinearLayout 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:background="#color/background_gray"
tools:context=".fragment.MallListFragment"
android:orientation="vertical">
<ListView
android:id="#+id/lv_malls"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
rowlist.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/row_mallx"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:paddingBottom="7dp">
<FrameLayout
android:id="#+id/ldrawlayout"
>
...
</FrameLayout>
</RelativeLayout>
LOGCAT (onCreateView method is called first)
01-15 18:40:16.905 7633-7633/? V/onCreateView METHOD CALLEDīš• onCreateView
01-15 18:40:17.280 7633-7633/? V/APICOMPLETED METHOD CALLEDīš• apiCompleted
Ok, I see the problem. You want to access the row-layout, but your listview has multiple versions of this layout, that mean you can not access the row layout from the activity, you have to do it in your listadapter or you give your single rows in the listadapter an unique id such as row.setId(row.getId + positionOfRow)
LayoutInflater Inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = Inflater.inflate(R.layout.row_mallx, null);
FrameLayout flayout = (FrameLayout) view .findViewById(R.id.ldrawlayout);
flayout.setVisibility(View.VISIBLE);
try this code in on apiCompleted
Are your sure that the onCreateView() method is called before the apiCompleted() method.
If yes, you should be able to access the view any where in your code as long as you hold the reference to it.
You can add some logs to see the order that the functions get called

How to create a fragment with a list without ListFragment

There's very little literature on this topic, and google's documents don't account for the possibility of customization (listviewanimation) of the fragment's list using ListFragment extension. Therefore, I'm going to ask this question, and then answer it as best as possible, because I also want 50 reputation points so I can finally thank great explainers on this website through comments.
For the purpose of this comment, I will have components from the listviewanimation lib laced in:
https://github.com/nhaarman/ListViewAnimations
Answer:
We will need to set up 4 components to have a proper fragment with a listview component
The Activity Creating the fragment through the activity's fragment manager.
The Fragment class which will be pretty basic fragment stuff, it will have the listview, and it will link that listview with an arrayadapter.
The Adapter class which for our purposes will only handle strings.
WITHIN THE ADAPTER CLASS the final fourth component will be a viewholder class which will allow the rows within the list to be created faster, since each row's individual components will be wrapped up in a class that will allow for quicker object instantiation.
Ok so, first will be the code for the activity, this code can be called by a button click or some other event. When the event happens, the fragment manager will be created, and that fragment manager will create a transaction which is a fancy way of saying, the manager will communicate between the activity and the newly formed fragment to get everything set up properly.
Here's the code that should be placed in your activity where the event occurs:
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
GenericFragment fragment = new GenericFragment();
fragmentTransaction.add(R.id.pager, fragment);
//Replace R.id.pager with the view that you want your fragment to go in.
fragmentTransaction.commit();
That's it! Not so bad, is it? Now let's move on to the GenericFragment class, which you can create a different name of course. I won't be posting all the code for this, but I'll step through everything you need for a fragment class that has a listview:
Have your Fragment class extend Fragment
Have an empty constructor for this class (google requires it... -__- )
Create a newInstance method which will handle the passing of data from the activity to the fragment when a 'new instance' of the fragment is created from the activity:
I'll help you with this one:
public static GenericFragment newInstance(String StuffYouWantGetsPassedFromActivityToFragment) {
GenericFragment GenericFragment = new GenericFragment();
Bundle args = new Bundle();
GenericFragment.setArguments(args);
return GenericFragment;
}
Again not so bad, right? We're still not done, we still need to override onCreateView and onCreate, then we'll be done with this simple step!
Ok for onCreateView:
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.generic_fragment_layout, container, false);
addGoalButton = (Button) view.findViewById(R.id.btn_newRow); //Created for testing purposes
lv = (ListView) view.findViewById(R.id.GenericListView);
addGoalButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) { //Created for testing purposes
genericAdapter.add("Goal");
genericAdapter.notifyDataSetChanged();
}
});
lv.setAdapter(genericAdapter);
return view;
}
That above code may seem like a monstrosity, and you're right! The high level overview is that you're getting the layout file that you want the fragment to look like. From that layout file, you're getting the listview and creating a variable to hold it in. Then you're calling that listView's 'setAdapter' method to add the next step, the adapter class. For testing purposes, I added that button, so that you can mentally extend this tutorial l8er. (delete all button code if you'd like just a list)
Ok, one last step in the fragment class: Overriding OnCreate!
The OnCreate method is where you want to instantiate all your private variables like the genericAdapter variable or anything that you'd like to use over the multiple parts of the Fragment class.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ArrayList<String> exampleItemList = new ArrayList<String>();
exampleItemList.add("item1");
exampleItemList.add("item2");
exampleItemList.add("item3");
exampleItemList.add("item4");
exampleItemList.add("item5");
exampleItemList.add("item6");
exampleItemList.add("item7");
exampleItemList.add("item8");
exampleItemList.add("item9");
exampleItemList.add("item10");
exampleItemList.add("item11");
exampleItemList.add("item12");
genericAdapter = new genericAdapter(getActivity(), 0, exampleItemList);
setHasOptionsMenu(true); // Allows the fragment to change the menu buttons
}
I added the example items to an arrayList to make this tutorial a bit more transparent about where data is coming from, and where it's going.
That's it! You're Fragment is done! It's almost over, I promise.
Let's knock these last two steps out together, creating a GenericAdapter class that extends ArrayAdapter and has a private inner ViewHolder class to wrap all the layout components in:
public class GenericAdapter extends ArrayAdapter<String>
LayoutInflater layoutInflater;
//Used to get the correct LayoutInflater to inflate each row item
public GenericAdapter(Context context, int resource, List<String> objects) {
super(context, 0, objects);
layoutInflater = layoutInflater.from(context);
}
/**
* #param position The position in the list to get the data for that row item.
* #param convertView The view for the row item that will be shown in the list.
* #param parent Having this object allows you to use the LayoutInflater for the parent.
* #return
*/
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final GenericViewHolder GenericViewHolder;
final String item = getItem(position);
if(convertView == null){
LinearLayout rootView = (LinearLayout) layoutInflater.inflate(R.layout.item_row, parent, false);
genericViewHolder = genericViewHolder.create(rootView);
rootView.setTag(genericViewHolder);
}
else{
genericViewHolder = (genericViewHolder) convertView.getTag();
}
genericViewHolder.textView.setText(item);
return genericViewHolder.rootView;
}
/**
* ViewHolder's allow for a single object to maintain a Goal row item, so that the row item
* doesn't have to create each individual component (textview layout etc.) each time the
* row object is created/recreated. Allows for fast scrolling with little latency.
*/
private static class GenericViewHolder {
public final LinearLayout rootView;
public final GripView gripView;
public final TextView textView;
private GoalViewHolder(LinearLayout rootView, GripView gripView, TextView textView) {
this.rootView = rootView;
this.gripView = gripView;
this.textView = textView;
}
public static GoalViewHolder create(LinearLayout rootView){
TextView textView = (TextView)rootView.findViewById(R.id.list_row_draganddrop_textview);
GripView gripView = (GripView)rootView.findViewById(R.id.list_row_draganddrop_touchview);
return new GenericViewHolder(rootView, gripView, textView);
}
}
}
That was again, a monstrosity, let's look at the high level overview, we created an adapter class, and a viewholder class for the adapter class to use. In the adapter's constructor we got a layoutinflater to help with inflating each row's item. Then, we created the getView method which get's called thousands of times in your app, because it handles making the each row appear when it's viewable by the user. The getView method sees if the view to be converted into a row is null or not. If it is, it will create a new data entry (a viewholder), but if it's not null, then that viewholder has already been created, so we get whatever was inside the viewholder already, so that we don't have to create a new row item.
phew! I don't expect you to understand any of that, but congrats if you do.
Ok so that's it. You should be set, and when your activity's event get's called, the fragment will show up in whatever view is containing the fragment. I'll post my xml files in my answer so that I can get those delicious upvotes (or not, I may be completely incorrect, but this worked for me!)
enjoy life, don't give up!
The activity xml, most of it is irrelevant to you the reader, but the container view for the fragment is pager:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!--Navigation Drawer Still Under Construction-->
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- As the main content view, the view below consumes the entire
space available using match_parent in both dimensions. -->
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- android:layout_gravity="start" tells DrawerLayout to treat
this as a sliding drawer on the left side for left-to-right
languages and on the right side for right-to-left languages.
The drawer is given a fixed width in dp and extends the full height of
the container. A solid background is used for contrast
with the content view. -->
<ListView
android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:background="#ffff"/>
</android.support.v4.widget.DrawerLayout>
<!--Navigation Drawer Still Under Construction-->
<!--Customizations on README at: https://github.com/astuetz/PagerSlidingTabStrip-->
<com.astuetz.PagerSlidingTabStrip
android:id="#+id/tabs"
android:layout_width="wrap_content"
android:layout_height="48dip"
app:pstsShouldExpand="true"
app:pstsIndicatorHeight="5dip"
app:pstsDividerPadding="0dip"
app:pstsDividerColor="#ff6d00"
app:pstsUnderlineColor="#ff5722"
app:pstsIndicatorColor="#ff5722"/>
<!--To scale the viewpager vertically, android:layout_above="#+id/[viewname]" -->
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/tabs"
tools:context=".MainActivity" />
</RelativeLayout>
The xml layout for the fragment:
<?xml version="1.0" encoding="utf-8"?>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="New Item"
android:id="#+id/btn_newItem"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<com.nhaarman.listviewanimations.itemmanipulation.DynamicListView
android:id="#+id/GenericListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_above="#+id/btn_newGoal" />
The specific row item:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="UseCompoundDrawables">
<com.nhaarman.listviewanimations.itemmanipulation.dragdrop.GripView
android:id="#+id/list_row_draganddrop_touchview"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:color="#android:color/darker_gray"
android:paddingBottom="4dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingTop="4dp" />
<TextView
android:id="#+id/list_row_draganddrop_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-light"
android:gravity="center_vertical"
android:minHeight="48dp"
android:textColor="?android:attr/textColorSecondary"
android:textSize="20sp"
tools:ignore="UnusedAttribute" />
</LinearLayout>
The layout portion of the 2nd code snippet got cut off and SO wasn't agreeing with my ctrl K'ing, but the long and short of it, is that it doesn't matter, because the listview is there, so it doesn't matter whether you put it in a linear layout or a relative layout.
Good luck bro's happy coding

Adding Layout to a ViewGroup Android

I have a flying in menu which based on ViewGroup.
I want that there will be a basic layout and in any activity i would be able to insert to the view group new layout and afterwards to erase it.
But it doesn't work!!! Can you help me please.
class:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.root = (FlyOutContainer) this.getLayoutInflater().inflate(R.layout.activity_main, null);
this.setAdditionalLayout(findViewById(R.id.physical_layout));
this.setContentView(root);
}
ViewGroup:
<com.nurielweizmann.calculator.view.viewgroup.FlyOutContainer xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#444488"
android:orientation="vertical"
android:id="#+id/menu">
............
</RelativeLayout>
</com.nurielweizmann.calculator.view.viewgroup.FlyOutContainer>
Function:
FlyOutContainer root;
public void setAdditionalLayout(View view){
root.addView(view,1);
}
Thanks in Advance
Try overriding the setContentView(int) instead of the onCreate(Bundle).
Make sure your base layout XML has a ViewGroup (FrameLayout, for example) available to put each Activity's content.
When overriding the setContentView(int), inflate your base layout first then inflate the Activity's layout and place the Activity's layout on the FrameLayout available.

Inflated View doesn't catch onClick event

I have an template view it looks like ;
template.xml :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/contentLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/view_background"
android:gravity="center_vertical"
tools:context=".MainActivity" >
<Button
android:id="#+id/btnMultiple"
android:layout_width="0dp"
android:layout_height="150dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_weight="1"
android:background="#drawable/button_backgroundblue"
android:onClick="btnMultiple_clicked"
android:tag="4"
android:text="#string/mc_abcd"
android:textColor="#drawable/button_textcolor"
android:textSize="#dimen/h2" />
I'm creating this view programmatically and then i'm adding this View into ViewFlipper as like ;
activity_main.java
public void btnCreateView_clicked(View view) {
ViewFlipper viewFlipper = (ViewFlipper)findViewById(R.id.flipper);
View myView = LayoutInflater.from(getApplicationContext()).inflate(R.layout.template, viewFlipper, false);
viewFlipper.addView(myView);
viewFlipper.showNext(); // Showing lastly created myView successfully. }
Also my activity has public function as like ;
activity_main.java
public void btnMultiple_clicked(View view) {
//Save the world !
}
When i press btnCreateView button from first view it's successfully creating template (myView) and then adding it into ViewFlipper. When i click btnMultiple i'm getting error and my application crashes ; "Could not find a method btnMultiple_clicked(View) in the activity class android.app.Application for onClick handler on view class android.widget.Button with id 'btnMultiple'" i'm sure there is existing method btnMultiple_clicked(View).
PS! If i add listener to btnMultiple programmatically it's gonna work but i wonder why "android:onClick="btnMultiple_clicked"" doesn't work ?
Android looks for the method defined in the onClick attribute in the Activity. The problem in your code is that you used for the LayoutInflater initialization the Application's Context and not the Context of the Activity so the method will not be found there(the Context is passed to the View). Use:
View myView = LayoutInflater.from(this).inflate(R.layout.template, viewFlipper, false);
or any other reference that points to the Activity where those buttons will be used.
This is a good example why you should use in most cases the Context of the Activity.

Change View content in activity dynamically

My abstract class extended from Activity class consists of three Views as described in the following XML snippet:
<?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"
android:background="#drawable/bg">
<LinearLayout
android:id="#+id/top_border">
...
</LinearLayout>
<View
android:id="#+id/activity_content"
...
/>
<LinearLayout
android:id="#+id/bottom_border">
...
</LinearLayout>
</LinearLayout>
And in onCreate() method I set this XML-layout as content view.
I want the Activitys which extend this one to override onCreate() and there define the activity_content View remaining borders immutable.
For example like this:
abstract public class MyActivity extends Activity {
protected View mContent;
#Override
protected onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.common_layout);
initializeContent();
}
abstract void initializeContent();
}
class OneActivity extends MyActivity {
#Override
protected void initializeContent() {
mContent = View.inflate(this, R.layout.some_view, null); // i.e. concrete View (e.g. LinearLayout, FrameLayout, GridView, etc.)
}
}
But when I do so my mContent remain the same as it was when I defined it in MyActivity's onCreate().
How can I change view's type/content depends on what Activity is in foreground?
First change the view in your main layout into a view group (for example, a LinearLayout). Then you can add views to it. If you add a unique view, it will have exactly the effect you want to achieve.
class OneActivity extends MyActivity {
#Override
protected void initializeContent() {
final ViewGroup viewGroup = (ViewGroup) findViewById(R.id.activity_content);
viewGroup.addView(View.inflate(this, R.layout.some_view, null));
}
}
In your case that should work. If your custom view group contained other views from higher up in the hierarchy, you can clean it before adding your custom view:
viewGroup.removeAllViews();
It works, I do exactly that in most of my projects.
An alternative is to look at the Fragments API, available for latest versions of the SDK.
You can't override class data members in Java, use methods instead

Categories

Resources