I have a fragment and I am setting listview on fragment.
Following is the code:
public class AttachmentsFragment extends Fragment {
ListView lstView = null;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
}
#Override
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//retains fragment instance across Activity re-creation
setRetainInstance(true);
objects = new ArrayList<AttachModel>();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = null;
view = inflater.inflate(R.layout.tab_attachment, container, false);
lstView = (ListView) view.findViewById(R.id.listViewAttachment);
adapter = new AttachAdapter(getActivity(), 0, 0, objects);
lstView.setAdapter(adapter);
return view;
}
}
In the adapter I have a progress bar and a textview to show the progress of the progress bar. A button to start and stop the progress bar
public class AttachAdapter extends ArrayAdapter<AttachModel> implements OnClickListener {
Context context;
ArrayList<AttachModel> objects = new ArrayList<AttachModel>();
AttachModel info;
//Activity act;
AttachModel model;
public AttachmentsAdapter(Context context, int resource,
int textViewResourceId, ArrayList<AttachmentsModel> objects) {
super(context, textViewResourceId, textViewResourceId, objects);
this.context = context;
this.objects = objects;
}
// no. of attachments available
#Override
public int getCount() {
return objects.size();
}
#Override
public AttachmentsModel getItem(int position) {
return objects.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, final ViewGroup parent) {
View row = convertView;
ViewHolder holder = null;
if(null == row) {
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.attachment_list_item, parent, false);
//textview for showing progress
holder.textViewProgress = (TextView) row.findViewById(R.id.txtViewPg);
//progress bar to show the progress
holder.progressBar = (ProgressBar) row.findViewById(R.id.pgBar);
holder.progressBar.setTag(position);
holder.textViewProgress.setVisibility(TextView.VISIBLE);
holder.img_view_fileIcon.setVisibility(ImageView.VISIBLE);
holder.progressBar.setVisibility(ProgressBar.VISIBLE);
//to start stop the progress bar
holder.button = (Button)row.findViewById(R.id.img_btn_download);
holder.button.setVisibility(Button.VISIBLE);
holder.button.setTag(position);
holder.button.setOnClickListener(this);
row.setTag(holder);
} else {
holder = (ViewHolder) row.getTag();
}
return row;
}
private class ViewHolder {
TextView textViewProgress;
ProgressBar progressBar;
Button button;
boolean downloadFlag = false;
}
#Override
public void onClick(View v) {
View vParent=(View) v.getParent();
ViewHolder tempHolder = null;
tempHolder=(ViewHolder) vParent.getTag();
//toggle button like functionality
if(!tempHolder.downloadFlag) {
tempHolder.downloadFlag = true;
tempHolder.progressBarStatus = 0;
async = new AsyncTaskAttachments(tempHolder, objects.get(Integer.parseInt(v.getTag().toString())).getFilePath());
tempHolder.async.execute();
objects.get((Integer)tempHolder.progressBar.getTag()).setAsyncTask(tempHolder.async);
}else {
tempHolder.downloadFlag = false;
tempHolder.progressBar.setProgress(0);
tempHolder.textViewProgress.setVisibility(TextView.GONE);
tempHolder.textViewProgress.setText("");
tempHolder.progressBarStatus = 0;
tempHolder.async.cancel(true);
}
}
public class AsyncTaskAttachments extends AsyncTask<Void, Void, Void> {
private ViewHolder holder;
public AsyncTaskAttachments(ViewHolder holder, String filePath) {
this.holder = holder;
this.filePath = filePath;
}
public void attach(Activity act) {
this.act = act;
}
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
holder.progressBarStatus = 0;
for(int i=0; i<=10; i++) {
try {
Thread.sleep(1000);
holder.progressBarStatus = i*10;
if(isCancelled()) {
break;
}
publishProgress();
}catch (Exception e) {
// TODO: handle exception
}
}
return null;
}
/* (non-Javadoc)
* #see android.os.AsyncTask#onPostExecute(java.lang.Object)
*/
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
/* (non-Javadoc)
* #see android.os.AsyncTask#onPreExecute()
*/
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
holder.progressBarStatus = 0;
holder.textViewProgress.setText("" + holder.progressBarStatus + "%");
holder.progressBar.setProgress(holder.progressBarStatus);
}
/* (non-Javadoc)
* #see android.os.AsyncTask#onProgressUpdate(Progress[])
*/
#Override
protected void onProgressUpdate(Void... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
// TODO Auto-generated method stub
holder.progressBar.setProgress(holder.progressBarStatus);
holder.textViewProgress.setText("" + holder.progressBarStatus + "%");
}
}
}
Note: This is just to show the way I am doing it. This is just a glimpse. I need to know whether I am on the right track or not.
On Orientation change, the progress bar is not able to retain and start the progress from where the orientation change.
Thanks in advance
When orientation changes, your activity (and fragments in contains) are re-created. So You call your asyncTask again and it's setting progress to zero:
holder.progressBarStatus = 0;
Solution: save progress in fragment's onSaveInstanceState(), resotre in onCreateView() ans make asyncTask use this value for initial progress setting.
I know this question is old and it's been answered, so just for the record: you can keep the state of a progress bar after orientation change with a viewmodel. I had a progress bar in a fragment and the progress bar was activated upon pressing a button. The trick is setting a variable in the viewmodel when the progress bar is activated and reading this variable in the onCreatView method of the fragment. This way, the progress bar will continue doing the same thing it did before orientation change (spinning / not spinning). This can be applied to other situations with modifications.
Viewmodel:
// create livedata variable
private final MutableLiveData<Boolean> mIsProgressBarActive = new MutableLiveData<>();
// get status from viewmodel
public LiveData<Boolean> getProgressBarStatus() {return mIsProgressBarActive; }
// save status to viewmodel
public void setProgressBarStatus(boolean status) {
mIsProgressBarActive.postValue(status);
}
Fragment onCreate:
super.onCreate(savedInstanceState);
mViewModel = ViewModelProviders.of(getActivity()).get(yourViewModel.class);
Fragment onCreateview:
View content = inflater.inflate(R.layout.your_fragment, container, false);
ProgressBar progressBar = content.findViewById(R.id.progressbar);
// if it was spinning, keep progress bar spinning after orientation change
if(mViewModel.getProgressBarStatus().getValue()) {
progressBar.setIndeterminate(true);
}
// activate progress bar and save its state to viewmodel
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
progressBar.setIndeterminate(true);
mViewModel.setProgressBarStatus(true);
}
});
Xml layout:
<ProgressBar
android:id="#+id/progressbar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="false"/>
Its done.. For all those who are facing this problem or will face this in the future.
Do not try to recreate the view.
Just inflate your listview once in the onCreate() method.
Because, the oncreate and ondestroy methods are called only once when the fragment is retained. So inorder to maintain the state of the progress bar, put the code in the oncreate method.
Related
I have two fragments in one activity and there is a ViewPager element in main_activity.xml. I have created two different classes that exteds Fragment class for each fragments and overrided onCreateView methods. The first fragment is a channels list. So it's a listview that its each row consist of a textview and a button. I want when the user click the button, get passed the row to listView in second fragment. I created a interface in ChannelsFragment named FavButtonClickedListener and overrided this interface in MainActivity.java. Then I added onAttach() method into ChannelsFragment in order to reference MainActivity. In getView method of Adapter of ChannelsFragment class I have set the clicklistener to imageButtons in each row and I called whenFavButtonClicked.onFavButtonClicked(); My code is working for SharedPreferences hovewer I need to restart the application to see changes in favorites list. I want to add the rows dynamically. I don't know where I wrong please help me
ChannelsFragment :
public class ChannelsFragment extends Fragment {
ViewGroup rootVg;
Context context;
FavButtonClickedListener whenFavButtonClicked;
private final List<String> favValues = new ArrayList<String>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.channels_list_layout, container, false);
final ListView channelsList = (ListView) rootView.findViewById(R.id.channelsListView);
String[] chNames = new String[]{"ChA","ChB","ChC"};
final ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < chNames.length; ++i) {
list.add(chNames[i]);
}
//set adapter to listview
MyListAdapter listAdapter = new MyListAdapter(getActivity(),chNames);
channelsList.setAdapter(listAdapter);
return rootView;
}
public interface FavButtonClickedListener {
public void onFavButtonClicked(int position,List<String>favs);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
context = getActivity();
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
whenFavButtonClicked = (FavButtonClickedListener)context;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
}
ChannelsFragment Adapter class:
public class MyListAdapter extends ArrayAdapter<String>{
private final Context context;
private final String[] values;
URL channelUrl;
public MyListAdapter(Context context, String[] values) {
super(context, R.layout.list_item_complex, values);
this.context = context;
this.values = values;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
public long getCount(int position) {
// TODO Auto-generated method stub
return values.length;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.list_item_complex, parent, false);
TextView chNameText = (TextView) rowView.findViewById(R.id.chName);
ImageView imageView = (ImageView) rowView.findViewById(R.id.chImage);
final ImageButton imageButton = (ImageButton)rowView.findViewById(R.id.starButon);
Button chButton = (Button)rowView.findViewById(R.id.chButon);
chNameText.setText(values[position]);
//Set the channels' logo appropriately
if(values[position].equals("CHa")){
imageView.setImageResource(R.drawable.CHaImage);
imageButton.setId(0);
}else if(values[position].equals("CHb")){
imageView.setImageResource(R.drawable.CHbImage);
imageButton.setId(1);
}else if(values[position].equals("Chc")){
imageView.setImageResource(R.drawable.CHcImage);
imageButton.setId(2);
}else{
imageView.setImageResource(R.drawable.defult_bacground_logo);
}
}
//Determine the target url for each channel correctly
chButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent("android.intent.action.Activity2");
String chName = null;
if(values[position].equals("CHa")){
i.putExtra("CHa", "http://www.cha.com/");
chName = "CHa";
i.putExtra("nameofCh", ChName);
startActivity(i);
}
if(values[position].equals("CHb")){
i.putExtra("CHb", "http://www.chb.com/");
chName = "CHb";
i.putExtra("nameofCh",ChName);
startActivity(i);
}
if(values[position].equals("CHc")){
i.putExtra("CHc", "http://www.chc.com/");
chName = "CHc";
i.putExtra("nameofCh",ChName);
startActivity(i);
}
});
final Context konteks;
konteks = this.getContext();
//set button click for favorite channels list
// I use this imageButton for create a favorites list in listview in FavoritesChannels
//fragment. I want when the user click this button, the row that has been clicked, get
//passed to FavoritesChannels fragment
imageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
imageButton.setImageResource(R.drawable.button_states_star);
SharedPreferences prefs = konteks.getSharedPreferences("favorites",Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
if(imageButton.getId()==0){
editor.putBoolean("CHaChecked", true);
editor.commit();
favValues.add("CHa");
whenFavButtonClicked.onFavButtonClicked(position,favValues);
Toast.makeText(getActivity(), "CHa have been added to favlist", Toast.LENGTH_SHORT).show();
}
else if(imageButton.getId()==1){
editor.putBoolean("CHbChecked", true);
favValues.add("CHb");
editor.commit();
whenFavButtonClicked.onFavButtonClicked(position,favValues);
Toast.makeText(getActivity(), "CHb have been added to favlist", Toast.LENGTH_SHORT).show();
}
else if(imageButton.getId()==2){
editor.putBoolean("CHcChecked", true);
favValues.add("CHc");
editor.commit();
whenFavButtonClicked.onFavButtonClicked(position,favValues);
Toast.makeText(getActivity(), "CHc have been added to favlist", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(getActivity(), "CH have been added to favlist", Toast.LENGTH_SHORT).show();
}
}
});
return rowView;
}
}
MainActivity.java:
onFavButtonClicked() implementation is at end of file
public class MainActivity extends ActionBarActivity implements ActionBar.TabListener,KanallarFragment.FavButtonClickedListener {
private static final int NUM_PAGES = 2;
public SharedPreferences prefs;
FragmentTransaction fragmentTransaction;
/**
* The pager widget, which handles animation and allows swiping horizontally to access previous
* and next wizard steps.
*/
private ViewPager mPager;
/**
* The pager adapter, which provides the pages to the view pager widget.
*/
private PagerAdapter mPagerAdapter;
//Initiate Actionbar instance and define its tab names
private ActionBar actionBar;
private String[] tabs = { "Channels", "Favorites"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fragMgr = getSupportFragmentManager();
fragmentTransaction = fragMgr.beginTransaction();
fragmentTransaction.add(new FavoriteFragment(), "favsFragment");
fragmentTransaction.add(new ChannelsFragment(), "channelsFragment");
// Instantiate a ViewPager and a PagerAdapter.
mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
//ViewPager's PageChangeListener
mPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
//Retrieve actionbar and set some properties
actionBar = getSupportActionBar();
//actionBar.setHomeButtonEnabled(true);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setStackedBackgroundDrawable(getResources().getDrawable(R.drawable.actionbar_gradient));
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setDisplayShowTitleEnabled(true);
// Adding Tabs to actionbar
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name).setTabListener(this));
}
for(int i = 0; i<actionBar.getTabCount(); i++){
LayoutInflater inflater = LayoutInflater.from(this);
View customView = inflater.inflate(R.layout.tab_layout, null);
TextView titleTV = (TextView) customView.findViewById(R.id.action_custom_title);
titleTV.setText(tabs[i]);
ImageView tabImage = (ImageView)customView.findViewById(R.id.tab_icon);
if(i==0){
tabImage.setImageResource(R.drawable.television_icon_64);
}else{
tabImage.setImageResource(R.drawable.star_icon);
}
actionBar.getTabAt(i).setCustomView(customView);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/*public void onTabSelected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
mPager.setCurrentItem(tab.getPosition());
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}*/
private class ViewPagerAdapter extends FragmentStatePagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position){
case 0:
return new ChannelsFragment();
case 1:
return new FavoritesFragment();
}
return null;
}
#Override
public int getCount() {
return NUM_PAGES;
}
}
#Override
public void onTabReselected(Tab arg0,FragmentTransaction arg1) {
// TODO Auto-generated method stub
}
#Override
public void onTabSelected(Tab arg0,FragmentTransaction arg1) {
// TODO Auto-generated method stub
mPager.setCurrentItem(arg0.getPosition());
}
#Override
public void onTabUnselected(Tab arg0,FragmentTransaction arg1) {
// TODO Auto-generated method stub
}
public void onFavButtonClicked(int position,List<String>favs) {
// TODO Auto-generated method stub
FavoritesFragment favFrag = (FavoritesFragment)getSupportFragmentManager().findFragmentByTag("favsFragment");
if(favFrag !=null){
favFrag.updateList(position,favs);
}
}
And FavoritesFragment class that contain updateList() method :
public class FavorilerFragment extends Fragment {
Context context;
private final List<String> values = new ArrayList<String>();
private final List<String> favValues = new ArrayList<String>();
ListView listView;
TextView textView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Context context = getActivity();
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.favorites_list_layout, container, false);
listView = (ListView)rootView.findViewById(R.id.f_channels_ListView);
textView = (TextView)rootView.findViewById(R.id.favListMessage);
SharedPreferences prefs = context.getSharedPreferences("favorites",getActivity().MODE_PRIVATE);
//-----SharedPreferences values for adapter----
if(prefs.getBoolean("CHaChecked", false)){
values.add("Cha");
}
if(prefs.getBoolean("CHbChecked", false)){
values.add("Chb");
}
if(prefs.getBoolean("ChcChecked", false)){
values.add("Chc");
}
//-----------------------------------------------
if(values.size() == 0){
textView.setText("Favorites List is empty");
}else{
textView.setText("");
}
MyListAdapter adapter = new MyListAdapter(getActivity(),values);
listView.setAdapter(adapter);
return rootView;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
context = getActivity();
}
public void updateList(int position,List<String> argfavValues){
for(int a= 0;a<argFavValues.size();a++){
favValues.add(argFavValues.get(a));
}
MyListAdapter = new MyListAdapter(getActivity(),favValues);
adaptor.notifyDataSetChanged();
listView.setAdapter(adapter);
}
public static class MyListAdapter extends ArrayAdapter<String>{
private final Context context;
private final List<String> values = new ArrayList<String>();
URL ChUrl;
public MyListAdapter(Context context, List<String> values) {
super(context, R.layout.list_item_complex_fav, values);
this.context = context;
for(int i=0;i<values.size();i++){
this.values.add(values.get(i));
}
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
public long getCount(int position) {
// TODO Auto-generated method stub
return values.size();
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.list_item_complex_fav, parent, false);
TextView chNameText = (TextView) rowView.findViewById(R.id.ChName);
ImageView imageView = (ImageView) rowView.findViewById(R.id.ChannelsImage);
Button chButton = (Button)rowView.findViewById(R.id.chButon);
chNameText.setText(values.get(position));
//Set the channels' logo appropriately
if(values.get(position).equals("CHa")){
imageView.setImageResource(R.drawable.CHaImage);
}else if(values.get(position).equals("CHb")){
imageView.setImageResource(R.drawable.CHbImage);
}else if(values.get(position).equals("CHc")){
imageView.setImageResource(R.drawable.CHcImage);
else{
imageView.setImageResource(R.drawable.default_logo);
}
return rowView;
}
}
Per the official documentation, fragment to fragment communication should be routed through the activity.
You need to create an interface in your channels fragment with some callback method defined, like onSelected. When a list item is selected, call that interface method using the activity context:
public class ChannelsFragment extends ListFragment {
OnItemSelectedListener mCallback;
public interface OnItemSelectedListener {
public void onSelected(int position);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mCallback = (OnItemSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnItemSelectedListener");
}
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
mCallback.onSelected(position);
}
}
Then, your activity needs to implement ChannelFragment.OnItemSelectedListener and define the callback method.
public void onSelected(int position) {
Fragment2 fragment = (Fragment2)
getSupportFragmentManager().findFragmentById(R.id.fragment2);
if (fragment != null) {
fragment.updateValue(position);
}
}
You can pass data via parameters. To send the data to the other fragment, create a public method in the fragment which can be called directly from the activity.
I am trying to blink listView Custom rows although I am looking for Fade in Fade out animation for listview rows, but in below code I am just changing image after a second and having problem in setting up and accessing background outside listView getViews. I am using Activity and listView is a component in that activity.
Please advice how to access items of listview outside my BaseAdapter in custom method
public class MyView extends Activity implements {
private Timer activeCallBlinker;
MyListAdapter mActiveAdapter;
private class MyListAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<HashMap<String, String>> data;
private LayoutInflater inflater = null;
ViewHolder viewHolder = null;
public MyListAdapter(Activity act,
ArrayList<HashMap<String, String>> dta) {
activity = act;
data = dta;
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return data.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public View getView(final int position, View convertView,
ViewGroup parent) {
// TODO Auto-generated method stub
View view = null;
if (convertView == null) {
view = inflater.inflate(R.layout.my_listitem, null);
viewHolder = new ViewHolder();
viewHolder.cellBgImg = (ImageView) view.findViewById(R.id.cellBgImage); /// Works fine and setting
view.setTag(viewHolder);
} else {
view = convertView;
}
viewHolder = (ViewHolder) view.getTag();
viewHolder.cellBgImg.setImageResource(R.drawable.stripe_flash);
return view;
}
}
public void populateAndBlink() {
mActiveAdapter = new MyListAdapter(ActiveCallView.this, calledPartyArr);
AnimationAdapter animAdapter = new SwingBottomInAnimationAdapter(mActiveAdapter);
animAdapter.setAbsListView(getListView());
lvActiveCall.setAdapter(animAdapter);
//// After successful population with animation
I am looking to blink it with Fade in Fade out but I can't find a good way so just changing images of background for my listadapter items
activeCallBlinker = new Timer();
startActiveTimer();
}
public void startActiveTimer (){
final int wantedPosition = globalRowIndex;
final Handler handler = new Handler ();
activeCallBlinker.scheduleAtFixedRate (new TimerTask (){
public void run (){
handler.post (new Runnable (){
public void run (){
runOnUiThread(new Runnable() // start actions in UI thread
{
#Override
public void run()
{
View cellView = mActiveAdapter.getView(wantedPosition, null,getListView());
//ViewHolder viewHolder = (ViewHolder) cellView.getTag();
ViewHolder viewHolder = new ViewHolder();
viewHolder.cellBgImg = (ImageView)cellView.findViewById(R.id.cellBgImage);
viewHolder.timerLbl = (TextView)cellView.findViewById(R.id.timerLbl);
if(viewHolder.timerLbl.getVisibility() == View.VISIBLE)
viewHolder.timerLbl.setVisibility(View.INVISIBLE); //// Unable to set InVisibility
else
viewHolder.timerLbl.setVisibility(View.VISIBLE); //// Unable to set Visibility
String resName = getResourceNameFromClassByID(R.drawable.class, R.drawable.stripe);
Log.d("Resource Name", resName);
final Drawable d1 = getResources().getDrawable(R.drawable.stripe);
final Drawable d2 = getResources().getDrawable(R.drawable.strip_header);
if (viewHolder.cellBgImg.getDrawable().equals(d1)) { //// Unable to check Drawable image for setting up background only else is called
Log.d("Resource Name", d1.toString());
viewHolder.cellBgImg.setImageResource(R.drawable.stripe_flash); //// Unable to change image of backkground
} else {
Log.d("Resource Name", d2.toString());
viewHolder.cellBgImg.setImageResource(R.drawable.stripe); //// Unable to change image of backkground
}
}
});
}
});
}
}, 0, 1000);
}
public ListView getListView() {
return lvActiveCall;
}
}
I appreciate pskink comments but Method for taking action on listView need to be called after a minor delay until an unless listView dynamic row addition with animation is completed
Therefore I create a seperate Thread runnable and called my method in it
worker = Executors.newSingleThreadScheduledExecutor();
Runnable myRunnable = createRunnable(i);
worker.schedule(myRunnable, 2, TimeUnit.SECONDS);
private Runnable createRunnable(final int wantedPosition){
Runnable aRunnable = new Runnable(){
public void run(){
runOnUiThread(new Runnable() // start actions in UI
// thread
{
#Override
public void run() {
ApplyActionOnActiveCallsAfterDelay(wantedPosition);
}
}
};
return aRunnable;
}
I have AsyncTask class called LoadXMLData, and as you can see I parse XML data in doInBackground() method.
public class LoadXMLData extends AsyncTask<String, RSSFeed, RSSFeed>{
public static final int DIALOG_DOWNLOAD_PROGRESS = 0;
private ProgressDialog mProgressDialog;
private Context context;
RSSFeed feed;
public LoadXMLData(Context context) {
this.context = context;
mProgressDialog = new ProgressDialog(context);
mProgressDialog.setMessage("Molimo Vas, sačekajte. Podaci se učitavaju.");
}
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressDialog.show();
Log.d("OVDE SAM:", "onPreExecute()");
}
#Override
protected RSSFeed doInBackground(String... urls) {
// Obtain feed
DOMParser myParser = new DOMParser();
feed = myParser.parseXml(urls[0]);
Log.d("OVDE SAM:", "PARSIRAM XML");
return feed;
}
#Override
protected void onPostExecute(RSSFeed result) {
mProgressDialog.dismiss();
super.onPostExecute(result);
}
}
And I have few fragments, where I need to get data from that AsyncTask. How I could do that?
Here is the code of an fragment called NajnovijeFragment.
public class NajnovijeFragment extends Fragment{
GridView lv;
RSSFeed feed;
CustomListAdapter adapter;
private String RSSFEEDURL = "http://balkanandroid.com/feed/";
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_najnovije, container,
false);
lv = (GridView) view.findViewById(R.id.GridView1);
// Set an Adapter to the ListView
adapter = new CustomListAdapter();
lv.setAdapter(adapter);
// Set on item click listener to the ListView
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// actions to be performed when a list item clicked
int pos = arg2;
Bundle bundle = new Bundle();
bundle.putSerializable("feed", feed);
Intent intent = new Intent(getActivity(), DetailsActivity.class);
intent.putExtras(bundle);
intent.putExtra("pos", pos);
startActivity(intent);
}
});
return view;
}
#Override
public void onDestroy() {
super.onDestroy();
adapter.imageLoader.clearCache();
adapter.notifyDataSetChanged();
}
class CustomListAdapter extends BaseAdapter {
private LayoutInflater layoutInflater;
public ImageLoader imageLoader;
public CustomListAdapter() {
layoutInflater = (LayoutInflater) getActivity().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
imageLoader = new ImageLoader(getActivity().getApplicationContext());
}
public int getCount() {
// TODO Auto-generated method stub
// Set the total list item count
return feed.getItemCount();
}
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return null;
}
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return 0;
}
public View getView(int position, View convertView, ViewGroup parent) {
// Inflate the item layout and set the views
View listItem = convertView;
int pos = position;
if (listItem == null) {
listItem = layoutInflater.inflate(R.layout.list_item, null);
}
// Initialize the views in the layout
ImageView iv = (ImageView) listItem.findViewById(R.id.thumb);
TextView tvTitle = (TextView) listItem.findViewById(R.id.title);
TextView tvDate = (TextView) listItem.findViewById(R.id.tvDate);
// Set the views in the layout
imageLoader.DisplayImage(feed.getItem(pos).getImage(), iv);
tvTitle.setText(feed.getItem(pos).getTitle());
tvDate.setText(feed.getItem(pos).getDate());
return listItem;
}
}
}
The easiest way to get data from an ASyncTask is by implementing a callback.
Create an Interface:
public interface OnXMLLoadFinishedListener {
public void onXMLDataReady(RSSFeed results);
}
In you LoadXMLData:
private OnXMLLoadFinishedListener listener;
public void setOnXMLLoadFinishedListener(OnXMLLoadFinishedListener listener){
this.listener = listener;
}
#Override
protected void onPostExecute(RSSFeed result) {
super.onPostExecute(result);
listener.onXMLDataReady(RSSFeed results);
}
In your Fragment:
public class NajnovijeFragment extends Fragment implements OnXMLLoadFinishedListener{
and override onXMLDataReady:
#override
public void onXMLDataReady(RSSFeed results){
//display your data.
}
Make sure that when you create your AsyncTask instance you set the listener otherwise this will not work:
LoadXMLData xmlLoader = new LoadXMLData();
xmlLoader.setOnXMLLoadFinishedListener(this);
Your AsyncTask already knows context, so you could call back into your activity (called ActivityMain for illustrative purposes) in onPostExecute. e.g.
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
((ActivityMain) context).loadCompleteHandler(param1,param2,...)
}
It's then up to you how you want to implement loadCompleteHandler in your activity. Now your activity might not exist, so you must be careful to cancel the AsyncTask when the activity is removed. Fragments belonging to an activity can also access the activity.
AsyncTask is a Class that is very related to the UI, if you need to update the UI with this XML parsing you should take this consideration:
Make the asynctask an inner class in your fragment or
Pass the fragment to your asynctask
Update the fragment's view in onPostExecute()
In any case you should check if your activity is null, if so... avoid updating views, something like that:
onPostExecute(Object xml) {
if(getActivity != null) {
// update Views like...
textViewLabel.setText(parsedXml.getTitle);
}
}
I would suggest you to use SafeAsyncTask, which is a java class from the Roboguice Project, only one file, and it is related to java.util.concurrent.Callable, just copy and paste the source:
SafeAsyncTask.java
How to use it!
Problem : in Listview swaps text inside of EditText. it happen when keyboard invisible or visible. as shown in below images.
Code : ListView Activity Class :
public class DayPlannerFormActivity extends Activity {
private TextView txtHeader;
private Context mContext;
private ListView lvDayplannerFrom;
private FormDayPlannerAdapter adapter;
private Activity activity;
final Handler mHandler = new Handler();
private Vector<DayPlannerForm> list = new Vector<DayPlannerForm>();
final Runnable mUpdateResults = new Runnable() {
public void run() {
updateResultsInUi();
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dayplanner);
mContext = this;
activity = this;
txtHeader = (TextView) findViewById(R.id.txtHeader);
txtHeader.setText(R.string.haivlate);
lvDayplannerFrom = (ListView) findViewById(R.id.lvDayplanner);
startfetchOperation();
}
private void updateResultsInUi() {
adapter= new FormDayPlannerAdapter(activity,list);
lvDayplannerFrom.setAdapter(adapter);
}
protected void startfetchOperation() {
Thread t = new Thread() {
#Override
public void run() {
getData();
}
};
t.start();
}
private void getData() {
try{
list.clear();
DayPlannerForm dpf = new DayPlannerForm("Task Name 1","","");
list.add(dpf);
dpf =new DayPlannerForm("Task Name 2","","");
list.add(dpf);
mHandler.post(mUpdateResults);
} catch (Exception e){
mHandler.post(mUpdateResults);
}
}
#Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
try{
if(lvDayplannerFrom != null)
lvDayplannerFrom.setAdapter(null);
} catch (Exception e){}
}
}
Code : List View Adapter Class
public class FormDayPlannerAdapter extends BaseAdapter {
private Activity mActivity;
private static Vector<DayPlannerForm> list;
private static LayoutInflater inflater;
private Context mContext;
public FormDayPlannerAdapter ( Activity _activity,Vector<DayPlannerForm> _list) {
mActivity = _activity;
mContext = _activity;
list = _list;
inflater = (LayoutInflater)mActivity.getSystemService(mActivity.LAYOUT_INFLATER_SERVICE);
}
public static class ViewHolder{
public TextView txtTaskName;
public CheckBox chbAction;
public EditText edtDecription;
}
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View vi=convertView;
ViewHolder holder;
if(convertView==null){
vi = inflater.inflate(R.layout.dayplanner_listitem_form, null);
holder=new ViewHolder();
holder.txtTaskName=(TextView)vi.findViewById(R.id.txtTaskName);
holder.chbAction = (CheckBox) vi.findViewById(R.id.chbAction);
holder.edtDecription = (EditText) vi.findViewById(R.id.edtDecription);
vi.setTag(holder);
}
else
holder=(ViewHolder)vi.getTag();
holder.txtTaskName.setText(list.get(position).getTaskName());
return vi;
}
}
How to resolve this problem
Problem solve bye Adding android:windowSoftInputMode="adjustPan" this attribute in activity tag in the manifest.xml
On first look i think that problem occurring by the the following code:-
DayPlannerForm dpf = new DayPlannerForm("Task Name 1","","");
list.add(dpf);
dpf =new DayPlannerForm("Task Name 2","","");
list.add(dpf);
You should take different objects of DayPlannerForm Class for each Task Name.
DayPlannerForm dpf1,dpf2;
dpf1 = new DayPlannerForm("Task Name 1","","");
list.add(dpf1);
dpf2 =new DayPlannerForm("Task Name 2","","");
list.add(dpf2);
I think this might solve your problem.
I trying to create List View i face some problem when orientation changes.
Problem is: when i changes orientation of screen list-view add duplicate list item in list. how to restrict this data change
Code Is:
public class DayPlannerActivity extends Activity {
private TextView txtHeader;
private Context mContext;
private ListView lvDayplanner;
private DayPlannerAdapter adapter;
private Activity activity;
private static Vector<DayPlanner> list = new Vector<DayPlanner>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dayplanner);
mContext = this;
activity = this;
txtHeader = (TextView) findViewById(R.id.txtHeader);
txtHeader.setText(R.string.haivlate);
String[] Checks = {"select","Check1","Check2"};
DayPlanner dp = new DayPlanner("11:00 PM", Checks);
list.add(dp);
dp = new DayPlanner("12:00 PM", Checks);
list.add(dp);
lvDayplanner = (ListView) findViewById(R.id.lvDayplanner);
adapter= new DayPlannerAdapter(activity,list);
lvDayplanner.setAdapter(adapter);
}
}
List Adapter :
public class DayPlannerAdapter extends BaseAdapter {
private Activity mActivity;
private static Vector<DayPlanner> list;
private static LayoutInflater inflater;
public DayPlannerAdapter ( Activity _activity,Vector<DayPlanner> _list) {
mActivity = _activity;
list = _list;
inflater = (LayoutInflater)mActivity.getSystemService(mActivity.LAYOUT_INFLATER_SERVICE);
}
public static class ViewHolder{
public TextView txtScheduledTime;
public Spinner spnrChecks;
public Button btnGo;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View vi=convertView;
ViewHolder holder;
if(convertView==null){
vi = inflater.inflate(R.layout.dayplanner_listitem, null);
holder=new ViewHolder();
holder.txtScheduledTime=(TextView)vi.findViewById(R.id.txtScheduledTime);
holder.spnrChecks = (Spinner) vi.findViewById(R.id.spnrChecks);
holder.btnGo = (Button) vi.findViewById(R.id.btnGo);
vi.setTag(holder);
}
else
holder=(ViewHolder)vi.getTag();
holder.txtScheduledTime.setText(list.get(position).getScheduledTime());
ArrayAdapter<String> spnrAdapter=new ArrayAdapter<String>(mActivity,
android.R.layout.simple_spinner_item, list.get(position).getChecks());
spnrAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
holder.spnrChecks.setAdapter(spnrAdapter);
holder.btnGo.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent i = new Intent();
i.setClass(mActivity,DayPlannerFormActivity.class);
mActivity.startActivity(i);
}
});
return vi;
}
}
Since Android automatically saves Views states when the orientation changes, you need a way to know if it's not the first call to onCreate. Luckily, it's easy: Override onSaveInstanceState, and store even 1 value to make the bundle your get in onCreate not-null.
#Override
public void onSaveInstanceState(Bundle outInstanceState) {
outInstanceState.putInt("value", 1);
}
Then, when the activity is recreated, the parameter savedInstanceState in onCreate will not be null. So just do the test:
if(savedInstanceState != null)
Before you add data to your views.
its because your list of dayplanner objects is static, so when you change the orientation of the view it recreates the activity but since in java a static object is not recreated, but saved for that type, it makes the list have two of the same.
Way too late the party here,will still answer as it might be useful to someone else. I was also having the same issue it was resolved by PROPERLY implementing the view holder design pattern.