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.
Related
My app has quite a few separate activity/fragment pairs, and relies on the Android universal back button for much of its navigation. This button works fine, EXCEPT when I'm trying to return from a DetailView activity back to a list of search results.
Here's what the search results code looks like:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle saveInstanceState) {
View v = inflater.inflate(R.layout.results_fragment, container, false);
ListView lv;
lv = (ListView)v.findViewById(R.id.listViewResults);
lv.setAdapter(SearchResultsAdapter);
lv.setEmptyView(v.findViewById(R.id.emptyElement));
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
ItemType selectedItem;
selectedItem = (ItemType)adapter.getItemAtPosition(position);
Intent i = new Intent(getActivity(), DetailViewActivity.class);
i.putExtra(DetailViewFragment.RESULT_ID, resultIdNumber);
startActivity(i);
}
});
// ... some other stuff
return v;
}
The DetailView is simply a collection of images and text.
The search returns expected results, and selecting the item shows the correct DetailViewFragment.
It seems like a very typical architecture, so I'm not sure why navigation back to the results page should be so problematic. I tried setting breakpoints to determine if the results activity ever restarted, but apparently it did not.
If you want to make something when the back button is pressed, you have to override it:
#Override
public void onBackPressed()
{
// code here
finish(); // to end activity:
}
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 have an activity and inside it a fragment, where i'm trying to display a gridview with pictures.
If I try to access the view in onCreateView() of the fragment, i do get a non-null handler and all is OK :
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.bar_pics_grid, container, false);
GridView gridview = (GridView) v.findViewById(R.id.gridview);
return v;
However, since i need to get data from a DB first, so I access the gridview in a custom function :
public void loadData(Bar bar) {
if (showBarDetails.getBar() != null) {
bar = showBarDetails.getBar();
GridView gridview = (GridView) getView().findViewById(R.id.gridview);
barImageArray = bar.getImages().toArray(new BarImage[bar.getImages().size()]);
gridview.setAdapter(new PicsAdapter(showBarDetails, barImageArray));
}
}
In the latter case, gridview is always null, which means this function is called before onCreateView - any ideas why is this happening ?
I initialize the Fragment in the activity's onCreate function as follows :
picsFragment = new PicsFragm(this);
Then I have an AsyncTask pulling data from the DB where I call :
#Override
protected void onPostExecute(AsyncTaskResult<Bar> result) {
if (result.getError() == null) {
sbd.setBar(result.getResult());
if (sbd.getPicsFragment().isResumed())
sbd.getPicsFragment().loadData(sbd.getBar());
}
}
Many thanks
Since your custom function is called before the onCreateView, I would suggest initializing a global variable(s) in your custom function then calling the variable(s) in your onCreateView method.
//global variable declaration like a string or data source e.g
String myValue;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.bar_pics_grid, container, false);
//Get your global variable here
String getValue = myValue;
GridView gridview = (GridView) v.findViewById(R.id.gridview);
return v;
}
public void loadData(String bar) {
//initialize your global variable here
myValue = bar;
}
The Android documentation suggests that to communicate from an activity to a hosted fragment, the fragment can define a callback interface and require that the host activity implement it. The basic pattern involves implementing onAttach in your fragment, and casting the activity to a callback inteface.
See http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity
I'd use a ReentrantLock to fix this. Create a variable in your fragment activity to hold the Database data:
private ReentrantLock dataLocker = new ReentrantLock();
private PicsAdapter adapter = null;
In loadData(Bar bar) rather than loading it directly into the grid view, load it into that variable:
if (showBarDetails.getBar() != null)
{
bar = showBarDetails.getBar();
barImageArray = bar.getImages().toArray(new BarImage[bar.getImages().size()]);
dataLocker.lock();
try
{
adapter = new PicsAdapter(showBarDetails, barImageArray);
//Check if the grid view is made (this is run after inflation)
GridView gridview = (GridView) getView().findViewById(R.id.gridview);
if (gridview != null)
{
gridview.setAdapter(adapter);
}
}
finally
{
dataLocker.unlock();
}
}
Then when you inflate your view, you make lock the dataLocker whilst you inflate. Once inflated, set the adapter if it already exists.
dataLocker.lock();
try
{
View v = inflater.inflate(R.layout.bar_pics_grid, container, false);
GridView gridview = (GridView) v.findViewById(R.id.gridview);
if (adapter != null)
gridview.setAdapter(adapter);
return v;
}
finally
{
dataLocker.unlock();
}
I'm not sure what thread you called execute on the AsyncTask on, so we use the ReentrantLock to make sure the threads aren't interfering with each other.
I have a weird situation with a custom ArrayAdapter.
When I try to update the adpater with new data, instead of the data being updated, the new data are inserted to the beginning of the listview and the old data are remaining and visible once you scroll the listview.
UPDATE
It seems that the problem is caused by the ArrayList from the fragment bundle.
If I don't set the listview in the onCreateView from the fragment bundle, my update code works fine, but now I'm puzzled why this:
ArrayList<Collection> cityStoresList = fragmentBundle.getParcelableArrayList("stores");
mStoresList.addAll(cityStoresList);
is causing the items to always remain on the list?
END OF UPDATE
Here are parts of the code: (Collection is a custom object model class)
ArrayList<Collection> mStoresList = new ArrayList<Collection>();
/** List Adapter */
private StoresListAdapter mListAdapter;
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
boolean attach = false;
if (container == null) {
attach = true;
}
Bundle fragmentBundle = getArguments();
ArrayList<Collection> cityStoresList = fragmentBundle.getParcelableArrayList("stores");
mStoresList.addAll(cityStoresList);
//inflater code not added here, but is present
mListAdapter = new StoresListAdapter(getActivity(), mStoresList);
mListView.setAdapter(mListAdapter);
return layout;
}
My custom adapter is as follows:
public class StoresListAdapter extends ArrayAdapter<Collection> {
public StoresListAdapter(Context c, ArrayList<Collection> array) {
super(c, 0, array);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// View from recycle
View row = convertView;
// Handle inflation
if (row == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.row_store, null);
}
// Get the Store
Collection store = getItem(position);
//rest of code follows
return row;
}
}
Now when I want to update my adapter I use the following:
public void updateAdapter(ArrayList<Collection> storesList, final int listIndex) {
mStoresList.clear();
mStoresList.addAll(storesList);
mListAdapter.notifyDataSetChanged();
}
And this creates the issue I mentioned. The new items appear fine, but the previous ones are still visible and added after the new ones.
It's like adding the new items in the ArrayList as the first items, instead of just replacing the old ones.
Any ideas, suggestions?
Ok, finally found the problem.
Because the whole thing is within a fragment, the oncreateView is actually called when I'm attaching the array, so what happens is that my updateAdapter method is called, the items are added and displayed, before the view is actually visible.
Then the oncreateView method is fired and the original bundle items are being added to the Arraylist....
I have the following class in my program:
public class RZoom extends Activity {
private ArrayList<FItem> m_FItems;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fchooser);
TextView tvName = (TextView)findViewById(R.id.txtTitleShow);
m_fItems = ((ArrayList<FItem>)this.getIntent().getSerializableExtra("fItems"));
tvName.setText(this.getIntent().getExtras().getString("RName"));
ListView lv = (ListView)findViewById(R.id.listView1);
FItemAdapter adapter = new FItemAdapter(this, R.layout.row, m_FItems);
lv.setAdapter(adapter);
}
}
This class displays a custom Listview and everything works fine. My questions are:
How do I capture an item click on the Listview? All the examples I've seen seem to inherit ListActivity instead of Activity, like I'm doing.
Is there a way to iterate through the items in the listview and set the background color of the item to Red, depending on the actual item? (In other words, I want to programmically highlight an item depending on the actual item)
Any help would be appreciated!
lv.setOnItemClickListener()
Override FItemAdapter's getView() to change colors depending on the item/position
For your first question you need to grab the ListView from its ID, as you are inheriting from Activity and not from ListActivity:
ListView lv_GetViewList = (ListView)findViewById(R.id.myListView);
lv_GetViewList.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3)
{
// Your Code here
}
});
2 . You can override the getView() function and then grab the desired control of the row depending upon the conditions you want to use for a particular Control or all of the controls, say, a TextView. And you can set its background color:
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
TextView tv_Text = (TextView) v.findViewById(R.id.myRowTextView);
if(tv_Text != null)
{
tv_Text.setBackgroundColor(Color.RED);
}
return v;
}