Currently there are two fragment : one for the area for adding image view, text view.
The other is a list fragment
I would like to include both in one fragment , that means the area fragment is at the top of the list fragment , however, they are two class so how to include them , or I need to re-arrange the code to one class?
Also, how do I change the list fragment to fragment ?(Since setadapter and onclick event are not available in fragment class).Thanks.
code example : the List fragment part
public class SlidingMenuListFragment extends ListFragment {
protected List<SlidingMenuListItem> slidingMenuList;
private SlidingMenuBuilderBase slidingMenuBuilderBase;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// We set here a custom layout which uses holo light theme colors.
return inflater.inflate(R.layout.sliding_menu_holo_light_list, null);
}
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// We get a list from our specially created list data class.
slidingMenuList = SlidingMenuList.getSlidingMenu(getActivity());
if (slidingMenuList == null)
return;
// We pass our taken list to the adapter.
SlidingMenuListAdapter adapter = new SlidingMenuListAdapter(
getActivity(), R.layout.sliding_menu_holo_light_list_row, slidingMenuList);
setListAdapter(adapter);
}
// We could define item click actions here, but instead we want our builder
// to be responsible for that.
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
l.setSelection(position);
SlidingMenuListItem item = slidingMenuList.get(position);
slidingMenuBuilderBase.onListItemClick(item);
}
// We can not provide a builder as an argument inside a fragment
// constructor, so that is why we have separate method for that.
public void setMenuBuilder(SlidingMenuBuilderBase slidingMenuBuilderBase) {
this.slidingMenuBuilderBase = slidingMenuBuilderBase;
}
Since Android 4.2, you can use Nested Fragments.
And to older versions, you should use the Support Library
Related
I have an activity with an AutoCompleteTextView (text).
When i select an item the code below is executed:
text.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Bundle args= new Bundle();
for (Student s: studentsBook.getStudentsList()){
if (s.getName().equals(((TextView)view).getText().toString())){
args.putSerializable("Student",s);
break;
}
}
theLayout.setVisibility(View.GONE); //removing elements (button, textviews...)
addButton.setVisibility(View.GONE); //removing elements
//simply adding a fragment through supportfragmentmanager and fragment transactions
//Fragment receives arguments (args) which contain a string to be showed.
//A tag: "DataFragment" is provided in order to get the fragment back in other parts of code.
//getMainView returns the container in which the fragment has to be created/showed.
dataFragment=(StudentDataFragment)addFragment(StudentDataFragment.class,R.layout.student_data_fragment,getMainView().getId(),args,"DataFragment");
}
});
The fragment has only this method:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
myLayout=(ViewGroup)inflater.inflate(R.layout.student_data_fragment,container,false);
student=(Student)getArguments().getSerializable("Student");
tv=((TextView)myLayout.findViewById(R.id.textView17));
tv.setText(student.toString());
return myLayout;
}
I can't see the string, it seems that the gui gets not updated, but if an orientation change happens the string appears..
I also managed the back button to remove the fragment if present and set visible the elements "gone". The code runs successfully but no gui refresh appears to be run.
No threads are involved in this situation, so i think we are in the UI-thread right?
Solved, just messing up the content view of the activity in other parts of code
I want to dynamically change my UI by checking some condition in my onCreate activity . But my app crashes .
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.busdetail);
Intent i=getIntent();
String s=i.getStringExtra("fname");
Log.d("ssssss: ",s);
if(s=="itemName1")
{
for(int k=0;k<itemName1.length;k++)
{
arrayk[k]=itemName1[k];
}
}
CustomList adapter = new CustomList(this, arrayk, imageId);
list = (ListView) findViewById(R.id.list);
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//String selectedItem = itemName[+position];
// Toast.makeText(getApplicationContext(),selectedItem,Toast.LENGTH_LONG).show();
Intent intent = new Intent(BusDetail.this, AddComment.class);
startActivity(intent);
}
});
}
Here if (s=="itemName1") then I copy itemName1 into arrayk. Both itemName1 and arrayk are string array . But when I clicked an item, my app crashes. When I avoid if condition block then my app runs well.
Two things.
First, to compare a String, don't use == ! You have to compare the value of the String, not the object itself. Your condition is wrong now... == compares the object references but not the content.
Use the following condition: if(s.equals("itemName1"))
or use equalsIgnoreCase("itemName1") if you want to ignore the case.
Then Remember that during the onCreate, your UI is not ready yet. If you have any change to do in the UI, do it in the onCreateView
//////////////////////////////////////////////////////////
onCreateView is working this way:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View mainview = inflater.inflate(R.layout.yourlayout, container, false);
//mainview is your main view, use it to find your elements, assign them listeners, change text, attributes, etc
return mainview; //you have to return this view
}
It is basically working like onCreate except that this is were you have to manage everything linked to your views and to your UI. It's also there that you have to inflate the view you need, and to return it.
I have a listview that is populated via an adapter. I need one of the items (which are just bits of text) in the listview to have a different background compared to the others (to mark it as the currently selected one).
I have all of the background logic, I just need a way to say listview.setBackgroundById(int position)
or something like that.
How do I do this?
This needs to be as simple as possible, 'cause all of the other things done in the Activity are currently working perfectly. :)
As asked, this is my Adapter that I'm using:
public class SampleAdapter extends ArrayAdapter<SampleItem> {
private String title;
public SampleAdapter(Context context) {
super(context, 0);
}
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.row_station, null);
}
TextView title = (TextView)convertView.findViewById(R.id.station_name);
font.setFont(title, 2, getActivity());
title.setText(getItem(position).title);
RelativeLayout info = (RelativeLayout)convertView.findViewById(R.id.info_relative_button);
info.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
MainActivity.setCurrentTab(41);
MainActivity.setBackDisabled(true);
Log.e("current tab:",String.valueOf(MainActivity.getCurrentTab()));
Fragment fragment = new StationInfo();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
UserManager.getInstance().setStationId(getItem(position).id);
}
});
return convertView;
}
}
The SampleItem has 2 String fields, title and id, it's very simple.
You need to use a custom list adapter and have it return views with your desired background. Create a class extending ListAdapter or any of the existing SimpleAdapter etc and override getView to inflate a suitable view for your element, and add any logic you need to set the background of that view.
There is no way to tell the listview itself to decorate some of its elements by id or position.
Update: I just noticed you added the list adapter code.
Since you are already implementing getView, to change the background of your element simply call convertView.setBackgroundColor, or have two different views inflated depending on the situation.
(BTW it's really bad practice to call static methods on your activity like in your onClickListener.)
In ListView adapter:
#Override
public View getView(int position, View view, ViewGroup viewGroup) {
if(view==null)
....
//for example every even list item to be grey, every odd to be white
if(((position+1)%2)==0)
view.setBackgroundColor(mContext.getResources().getColor(R.color.grey));
else view.setBackgroundColor(mContext.getResources().getColor(android.R.color.white));
Hope you get an idea...
I'm planning to convert an existing android application to fragments layout.
The idea is to have the classical two panel layout (item list on left, and details on right).
Actually the application is composed by 4 activites:
A ChoiceListActivity with all the available options
3 different activities, one for each operation available on the tool.
Now i started to work on the conversion and i created a FragmentActivity classs, that is the main class:
public class MainFragment extends FragmentActivity {
private static final String TAG = "MainFragment";
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_main);
if(findViewById(R.id.fragment_container)!=null){
Log.i(TAG, "No Tablet");
Intent i = new Intent(MainFragment.this, main.ChoiceActivity.class);
startActivity(i);
} else {
Log.i(TAG, "Tablet");
}
}
}
And i created a ChoiceListFragment:
`
public class ChoiceListFragment extends ListFragment {
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
Toast.makeText(getActivity(), getListView().getItemAtPosition(position).toString(), Toast.LENGTH_LONG).show();
super.onListItemClick(l, v, position, id);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String[] options = getResources().getStringArray(R.array.listitems);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(inflater.getContext(), R.layout.list_item, options);
setListAdapter(adapter);
return super.onCreateView(inflater, container, savedInstanceState);
}
}
That fragment will be the left side of the panel.
My problem is for the right side. The idea is that for every element of the list the corresponding activity (or fragment?) will be shown.
So what is the correct way?
Is a good idea to start an activity in the right fragment when the user select an item?
Or i must switch between fragments programmatically? And how to do that (i found many tutorials, but they use always the same activity for the right panel changing some data inside it)?
I have created the following class for the right fragment (but i'm not sure that i'm doing it correctly):
public class RightFragment extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.main, container, false);
}
}
I noticed that i can eventually change the layout using the LayoutInflater object during onCreate method, but this simply siwtch the layout on the screen, The objects declared in the layout aren't initialized (nor eventListener added, etc). So how to do that?
Maybe i should Create an Intent and use startActivity to launch the existing activities, or this is a bad idea into a fragment?
Actually the xml layout is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<fragment
android:id="#+id/choicelist_fragment"
android:name="main.fragments.ChoiceListFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<fragment
android:id="#+id/right_fragment"
android:name="main.fragments.RightFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
</LinearLayout>
Ok i found myself the solution, it was not clear on a first moment, but reading some documentation, looking at many tutorials maybe i understand how it works.
First of all i removed the second fragment *right_fragment* from the layout (check the question), i replaced it with an empty FrameLayout called *activity_container* that will be the container of my fragments.
The idea behind is simply use the FragmentManager to replace the fragment inside the container.
So i updated the onListItemClick method into the ChoiceListFragment, and depending on what is the list item tapped, it creates a new Fragment and replace it into the *activity_container*. The updated method is similar to the following:
public void onListItemClick(ListView l, View v, int position, long id) {
String itemName = getListView().getItemAtPosition(position).toString();
switch(position){
case OPTION_ONE: getFragmentManager().beginTransaction().replace(R.id.activity_container, new OptionOneFragment()).commit();
break;
case RESISTOR_VALUE:
getFragmentManager().beginTransaction().replace(R.id.activity_container, new OptionTwoFragment()).commit();
break;
default:
Toast.makeText(getActivity(), getListView().getItemAtPosition(position).toString(), Toast.LENGTH_LONG).show();
break;
}
super.onListItemClick(l, v, position, id);
}
In that way every component of the application has its own fragment, handled by a different class.
You're on the right track. On small screens, clicking a list item starts a DetailActivity, which is a simple wrapper around a DetailFragment. On a larger screen, clicking the list item would replace the right hand side with a new instance of DetailFragment.
If you are using eclipse and ADT, I would suggest taking a look at the MasterDetailFlow template, which can be accessed by creating a new Android project or a new Android Activity.
EDIT: SOLVED. If there's anything focusable in the XML of the items, it will break the touch of the list, in other words, android:focusable=false to all the checkboxes, switches or anything like that of ur list. And done =)
Ok so, here's my problem.
I wrote a app that uses tabs and fragments, and it all goes the way I want except for the thing that when I try to capture a onItemClick on a listView it does not even mark the row as touched/pressed/selected.
I've been reading a little bit about and many people have the same issue, but I did not found any responses that helped me at all.
I don't want to implement a ListFragment, in fact I don't even know how/why I should, and since all my code is already working, I don't know if implementing one will give me much more work to do, so, here it is:
Is it possible to implement a listener for a click on a listView, inside a fragment? and if it is, HOW?
PD: minSDK=14, tatgetSDK=15
Just put
android:focusable="false"
android:clickable="false"
in layout.
For all textviews,buttons etc.
Here's a code snippet that'll do what you want.
ListView lv;
//code to get the listView instance using findViewByID etc
lv.setOnItemClickListener(new OnItemClickListener()
{
#Override public void onItemClick(AdapterView<?> arg0, View arg1,int position, long arg3)
{
Toast.makeText(EnclosingActivity.this, "Stop Clicking me", Toast.LENGTH_SHORT).show();
}
});
People usually trip on this, see if you have got this covered:
All clicks and call backs (eg: the menu/actionbar callbacks) are sent to the activity the fragment is bound to, so they must be in the activity class and not the fragment class.
This may be helpful
Answer by raghunanadan in below link solved my problem
listview OnItemClick listner not work in fragment
Add this to the layout
android:descendantFocusability="blocksDescendants"
Two awesome solutions were this, if your extending ListFragment from a fragment, know that mListView.setOnItemClickListener wont be called before your activity is created, As #dheeraj-bhaskar implied. This solution ensured it is set when activity has been created
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
mListView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long rowId) {
// Do the onItemClick action
Log.d("ROWSELECT", "" + rowId);
}
});
}
While looking at the source code for ListFragment, I came across this
public class ListFragment extends Fragment {
...........................................
................................................
final private AdapterView.OnItemClickListener mOnClickListener
= new AdapterView.OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View v, int position, long id)
{
onListItemClick((ListView)parent, v, position, id);
}
};
.................................................................
........................................................................
public void onListItemClick(ListView l, View v, int position, long id)
{
}
}
An onItemClickListener object is attached and it calls onListItemClick()
As such the other similar solution, which works in the exact same way is to override onListItemClick()
#Override
public void onListItemClick(ListView l, View v, int position, long rowId) {
super.onListItemClick(l, v, position, id);
// Do the onItemClick action
Log.d("ROWSELECT", "" + rowId);
}
Here is an overview of the workflow, create your ListView and it's corresponding Adapter(used to map your underlying data to the items in the ListView), set the adapter to the ListView, and then add an OnItemClickListener to it.
More details and sample code can be found at: http://developer.android.com/guide/topics/ui/declaring-layout.html#AdapterViews
If you want to pass data from fragment to any activity on Listview click then you can modify your code like...
class HistoryFragment extends Fragment { ListView historyListView;
public HistoryFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v= inflater.inflate(R.layout.fragment_history, container, false);
historyListView= (ListView) v.findViewById(R.id.historyDataListView);
sendRequest(); //it is my meathod to load the listview and set the adapter
return v;
}
public void onStart() {
super.onStart();
historyListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent=new Intent(getActivity(), DisplayDetails.class);
intent.putExtra("text", historyListView.getItemAtPosition((int) l).toString());
startActivity(intent);
// Toast.makeText(getActivity(),"Hello.. "+historyListView.getItemAtPosition((int) l).toString(),Toast.LENGTH_LONG).show();
}
});
}}
the button will affect the listener, try avoid using button and re compile,
it should work