Requirement: When the user clicks on the TextView, a date picker should open up. The default date selected should be the date in the TextView. If the date is in the past, the DatePicker dialog's 'Set' button should be disabled. If the clickable TextView is empty, the default date in the DatePicker should be today's date.
This is a scenario I've already solved and am sharing here in order to help the Xamarin community. The code isn't very optimized, just FYI.
So, what we exactly need in this scenario is access to the event that the user is changing dates on the DatePicker Dialog. This can only be done if you use a DatePicker inside your own Dialog for more control. In my opinion, you cannot get access to this event if you use the default DatePickerDialog. Thus, we create a dialog extending the DialogFragment class and then implement the DatePicker inside of it. When the user clicks the TextView, we use show the fragment. Let's begin:
Here's the MainActivity:
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Java.Util;
using Java.Text;
namespace DatePickerTest
{
[Activity(Label = "DatePickerTest", MainLauncher = true, Icon = "#drawable/icon", Theme = "#android:style/Theme.Holo.Light")]
public class MainActivity : Activity
{
private string dueDate;
private TextView dateLabel;
private DateTime date;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
dateLabel = (TextView)FindViewById(Resource.Id.dateLabel);
dueDate = dateLabel.Text;
dateLabel.Click += delegate { ShowDialog(); };
}
public void ShowDialog()
{
var transaction = FragmentManager.BeginTransaction();
var dialogFragment = new mDialogFragment();
dialogFragment.Show(transaction, "dialog_fragment");
}
//Used for communication with the fragment
public string GetDueDate()
{
return dueDate;
}
//Used for communication with the fragment
public void SetDueDate(DateTime date)
{
//Additional check so that date isn't set in the past
if (date < DateTime.Now.Date)
Toast.MakeText(this, "Something went wrong! Please try again", ToastLength.Long).Show();
else
{
SimpleDateFormat MdyFormat = new SimpleDateFormat("MM/dd/yyyy");
dueDate = MdyFormat.Format(Date.Parse(date.ToString()));
dateLabel.Text = dueDate;
}
}
}
}
Main.axml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="#+id/MyButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/Hello" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:background="#FAFAFA"
android:layout_height="wrap_content">
<TextView
android:id="#+id/dueDateLabel"
android:layout_height="45dp"
android:layout_width="wrap_content"
android:text="Due Date:"
android:padding="15dp"
android:textColor="#2E2E2E" />
<TextView
android:id="#+id/dateLabel"
android:layout_height="45dp"
android:layout_width="fill_parent"
android:hint="Some Date"
android:textColor="#2E2E2E"
android:text="03/16/2015" />
</LinearLayout>
</LinearLayout>
MDialogFragment.cs :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
using Java.Util;
using Java.Text;
namespace DatePickerTest
{
public class mDialogFragment : DialogFragment
{
DatePicker picker;
private MainActivity MActivity;
private int Year, Month, Day;
private string DueDate;
private DateTime SelectedDueDate;
private string tempString = "";
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
//Get the instance of the MainActivity
MActivity = (MainActivity) this.Activity;
//Get the currently set due date
DueDate = MActivity.GetDueDate();
//Get instance of the Calendar
Calendar Today = Calendar.Instance;
//Update the class variables
Year = Today.Get(Calendar.Year);
Month = Today.Get(Calendar.Month);
Day = Today.Get(Calendar.Date);
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
//Inflating the dialog layout
var view = inflater.Inflate(Resource.Layout.MDialogLayout, container, false);
//Finding all the views in it:
var cancel = (Button)view.FindViewById(Resource.Id.cancel);
var set = (Button)view.FindViewById(Resource.Id.set);
picker = (DatePicker)view.FindViewById(Resource.Id.pickerdate);
//DatePicker flag to make it look like the default DatePicker
picker.CalendarViewShown = false;
//Checking to see if current date is in the past, if YES, disable the 'Set' button
if ((DateTime.Parse(DueDate) < DateTime.Now)) { set.Enabled = false; }
//Initate the picker with the current due date OR today's date
picker.Init(GetDefaultYear(), GetDefaultMonth(), GetDefaultDayOfMonth(), new onDateChangedListener((picker1, year, month, day) =>
{
//Getting the DatePicker value in a string
tempString = (month + 1) + "/" + day + "/" + year;
//Parsing the value into a variable
SelectedDueDate = (DateTime.Parse(tempString).Date);
//Setting the MDatePicker dialog's Title
Dialog.SetTitle(GetDateDetails(SelectedDueDate));
//Enable/Disalbe 'Set' button depending on the condition
if (SelectedDueDate >= DateTime.Now.Date)
set.Enabled = true;
else
set.Enabled = false;
}));
//Setting Dialog Title for the first time when it opens
Dialog.SetTitle(GetDateDetails(DateTime.Parse(DueDate)));
//Click function for Cancel button
cancel.Click += delegate{Dismiss();};
//Click function for Set button
set.Click += (object sender, EventArgs e) =>
{
SetSelectedDueDate(sender, e);
};
return view;
}
private string GetDateDetails(DateTime date)
{
string DateDetails;
Calendar cal = Calendar.Instance;
SimpleDateFormat DayOfWeekFormat = new SimpleDateFormat("EEE");
SimpleDateFormat MonthFormat = new SimpleDateFormat("MMM");
DateDetails = DayOfWeekFormat.Format(Date.Parse(date.ToString())) + ", " + date.Day + " " + MonthFormat.Format(Date.Parse(date.ToString())) + " " + date.Year;
return DateDetails;
}
private void SetSelectedDueDate(object sender, EventArgs e)
{
MActivity.SetDueDate(SelectedDueDate);
Dismiss();
}
private int GetDefaultMonth()
{
//The currently set due date is in the format "MM/DD/YYYY"
if(MActivity.GetDueDate()==null || MActivity.GetDueDate() == "")
return Month;
return Convert.ToInt32(MActivity.GetDueDate().Substring(0, 2)) - 1;
}
private int GetDefaultDayOfMonth()
{
if (MActivity.GetDueDate() == null || MActivity.GetDueDate() == "")
return Day;
return Convert.ToInt32(MActivity.GetDueDate().Substring(3, 2));
}
private int GetDefaultYear()
{
if (MActivity.GetDueDate() == null || MActivity.GetDueDate() == "")
return Year;
return Convert.ToInt32(MActivity.GetDueDate().Substring(6, 4));
}
}
//We need this class and interface implementation to create and Init the DatePicker
class onDateChangedListener : Java.Lang.Object, DatePicker.IOnDateChangedListener
{
Action<DatePicker, int, int, int> callback;
public onDateChangedListener(Action<DatePicker, int, int, int> callback)
{
this.callback = callback;
}
public void OnDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth)
{
callback(view, year, monthOfYear, dayOfMonth);
}
}
}
MDialogLayout.axml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<DatePicker
android:id="#+id/pickerdate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button
android:id="#+id/cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cancel"
android:layout_weight="1"
style="?android:attr/buttonBarButtonStyle" />
<Button
android:id="#+id/set"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SET"
android:layout_weight="1"
style="?android:attr/buttonBarButtonStyle"
android:paddingTop="1dp" />
</LinearLayout>
</LinearLayout>
Related
I'm making a navigation drawer with different activities and i want to display the same navigation drawer in all activities , i take the same code and put it in all activities but when i click on the activities my app crashes all the time i don't know why
Try below code for displaying Navigation drawer on all activity, hope this example help...!
BaseActivity
public class BaseActivity extends AppCompatActivity {
ArrayList<String> menuList;
protected FrameLayout frameLayout;
protected ListView mDrawerList;
protected static int position;
private static boolean isLaunch = true;
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle actionBarDrawerToggle;
#SuppressLint("ResourceAsColor")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.navigation_drawer_base_layout);
prepareListItems();
frameLayout = findViewById(R.id.content_frame);
mDrawerLayout = findViewById(R.id.drawer_layout);
mDrawerList = findViewById(R.id.left_drawer);
View header = getLayoutInflater().inflate(R.layout.header, null);
mDrawerList.addHeaderView(header);
mDrawerList.setAdapter(new ArrayAdapter<>(this, R.layout.drawer_list_item, menuList));
mDrawerList.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
openActivity(position);
}
});
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.menu);
actionBarDrawerToggle = new ActionBarDrawerToggle(
this, /* host Activity */
mDrawerLayout, /* DrawerLayout object */
R.mipmap.ic_launcher_round, /* nav drawer image to replace 'Up' caret */
R.string.open_drawer, /* "open drawer" description for accessibility */
R.string.close_drawer) /* "close drawer" description for accessibility */ {
#Override
public void onDrawerClosed(View drawerView) {
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
super.onDrawerClosed(drawerView);
}
#Override
public void onDrawerOpened(View drawerView) {
Objects.requireNonNull(getSupportActionBar()).setTitle(getString(R.string.app_name));
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
super.onDrawerOpened(drawerView);
}
#Override
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
}
#Override
public void onDrawerStateChanged(int newState) {
super.onDrawerStateChanged(newState);
}
};
mDrawerLayout.setDrawerListener(actionBarDrawerToggle);
if (isLaunch) {
isLaunch = false;
openActivity(1);
}
}
private void prepareListItems() {
menuList = new ArrayList<>();
menuList.add(" Activity1 ");
menuList.add(" Activity2 ");
menuList.add(" Activity3 ");
menuList.add(" Activity4 ");
}
/**
* #param position Launching activity when any list item is clicked.
*/
protected void openActivity(int position) {
mDrawerList.setItemChecked(position - 1, true);
mDrawerLayout.closeDrawer(mDrawerList);
BaseActivity.position = position; //Setting currently selected position in this field so that it will be available in our child activities.
switch (position) {
case 0:
break;
case 1:
startActivity(new Intent(this, Activity1.class));
break;
case 2:
startActivity(new Intent(this, Activity2.class));
break;
case 3:
startActivity(new Intent(this, Activity3.class));
break;
case 4:
startActivity(new Intent(this, Activity4.class));
break;
default:
break;
}
// Toast.makeText(this, "Selected Item Position::" + position, Toast.LENGTH_LONG).show();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (actionBarDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
switch (item.getItemId()) {
case R.id.action_settings:
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/* Called whenever we call invalidateOptionsMenu() */
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
// If the nav drawer is open, hide action items related to the content view
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
menu.findItem(R.id.action_settings).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
}
Activity1
public class Activity1 extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getLayoutInflater().inflate(R.layout.activity_main, frameLayout);
mDrawerList.setItemChecked(position, true);
}
#Override
protected void onDestroy() {
super.onDestroy();
}
}
navigation_drawer_base_layout
<androidx.drawerlayout.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">
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ListView
android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#drawable/simple_brushed_metal"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp" />
</androidx.drawerlayout.widget.DrawerLayout>
header
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/shade">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:fontFamily="serif"
android:gravity="center"
android:text="#string/app_name"
android:textColor="#color/textColorPrimary"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="#string/developed_by_nd_software_solution"
android:textColor="#color/textColorPrimary"
android:textSize="12sp" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="8dp"
android:background="#color/textColorPrimary" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
drawer_list_item
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/activatedBackgroundIndicator"
android:fontFamily="serif"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:textColor="#color/textColorPrimary" />
activity_main
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimary">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:fontFamily="serif"
android:gravity="center"
android:text="#string/app_name"
android:textColor="#color/textColorPrimary"
android:textSize="18sp" />
</androidx.constraintlayout.widget.ConstraintLayout>
Here I have provided code for one activity (Activity1), write code for other activities like Activity2, Activity3 etc.
The codes below runs in an android emulator with Android version SDK 16. But somehow when it runs on the emulator with Android version >21, DataBinding and Realm savings doesn't get triggered..
How should I be dealing with Android versioning?
Is it because the rendered UI differs in different android versions so DataBinding wouldn't have worked either?
This code here is the ViewModel
#PerFragment
public class OnboardDOBViewModel extends BaseHelperViewModel<BaseUserView> implements IOnboardDOBViewModel {
private String TAG = getClass().getSimpleName();
private HelperRepo mHelperRepo;
private UserRepo mUserRepo;
private Helper mHelper;
public final ObservableField<Integer> datePicker = new ObservableField<>();
public final ObservableField<Integer> monthPicker = new ObservableField<>();
public final ObservableField<Integer> yearPicker = new ObservableField<>();
public ReadOnlyField dobSelected;
private CompositeDisposable mCompositeDisposable = new CompositeDisposable();
#Inject
public OnboardDOBViewModel(#AppContext Context context, UserRepo userRepo, HelperRepo helperRepo) {
super(context, userRepo, helperRepo);
Log.d(TAG, "OnboardDOBViewModel: ");
this.mUserRepo = userRepo;
this.mHelperRepo = helperRepo;
}
#Override
public void attachView(BaseUserView view, #Nullable Bundle savedInstanceState) {
super.attachView(view, savedInstanceState);
Log.d(TAG, "attachView");
mHelper = mHelperRepo.getByUser("user.id", mUserRepo.getCurrentUser(), false);
if (mHelper != null) {
Calendar c = Calendar.getInstance();
yearPicker.set(c.get(Calendar.YEAR)-23);
monthPicker.set(c.get(Calendar.MONTH));
datePicker.set(c.get(Calendar.DAY_OF_MONTH));
}
Observable<String> dobSelected = Observable.combineLatest(
Utils.toObservable(monthPicker),
Utils.toObservable(datePicker),
Utils.toObservable(yearPicker),
(integer, integer2, integer3) -> {
String dobSelected1 = String.valueOf(monthPicker.get() + 1) + "-" +
datePicker.get().toString() + "-" +
yearPicker.get().toString();
Log.d(TAG, "apply: " + dobSelected1);
SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy", Locale.getDefault());
Date date = sdf.parse(dobSelected1);
Log.d(TAG, "apply: date selected" + date);
Helper helper = mHelperRepo.getByUser("user.id", mUserRepo.getCurrentUser(), true);
assert helper != null;
helper.setDateOfBirth(date);
mHelperRepo.save(helper);
return dobSelected1;
});
this.dobSelected = Utils.toField(dobSelected);
}
This is the XML
<data>
<variable
name="vm"
type="...OnboardDOBViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:padding="30dp"
android:text="#string/toolbar_title_date_of_birth"
android:textAppearance="#style/TextAppearance.AppCompat.Large" />
<DatePicker
android:id="#+id/onboard_birth_date_picker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:calendarViewShown="false"
android:day="#={vm.datePicker}"
android:month="#={vm.monthPicker}"
android:solidColor="#color/grayMedium"
android:spinnersShown="true"
android:year="#={vm.yearPicker}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="test"
android:text="#{vm.dobSelected}"
android:visibility="visible"/>
</LinearLayout>
Found this as my answer
OnDateChanged is not called in Date picker Android lollipop
added this in, and override the config, calendar UI is now spinner style and binding works
android:datePickerMode="spinner"
i have placed a textview and a toggle button into a list view by using the following xml file and i have used an arrayadapter to set it on to my layout, my problem is when i scroll down in the list view by unchecking a few toggle buttons (which are all set to be checked by default), they go back to default state and few others change state. As i want to fetch the state of the toggle button in my later stages its very important to stick on to the state that ive assigned to the toggle button. Please help to resolve this problem. Here are my xml file and the java code i use to set it on to the adapter. thank you in prior...
xml file that is named listdecor is included here
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/lvlistdecor"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#000000"
android:orientation="horizontal"
android:weightSum="2" >
<TextView
android:id="#+id/tvlistdecor"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.5"
android:ellipsize="marquee"
android:singleLine="true"
android:text="sample"
android:textColor="#FFFFFF"
android:textSize="24sp"
android:typeface="sans" />
<CheckBox
android:id="#+id/cbusn_checked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="6sp"
android:layout_weight="0.5"
android:checked="true"
android:focusable="false"
android:padding="10dp" />
</LinearLayout>
Sir i made certain changes and also included the custom adapter to the listview and also changed to CheckBox instead of toggle buttons. but now the entire list view is not visible on my emulator. i've included my edited java class and xml file, please suggest me the changes, thank you...
The modified java code is included here
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); // Setting the window to full screen Step 1
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN); // Setting the window to full screen Step 2
setContentView(R.layout.attendance5);
facid = (TextView) findViewById(R.id.tvfacid);
facname = (TextView) findViewById(R.id.tvfacname);
subjectchosen = (TextView) findViewById(R.id.tvsubject);
// llattendlist = (LinearLayout)findViewById(R.id.llattendlist);
String Uid = getIntent().getStringExtra("Uid");
facid.setText(Uid);
String Name = getIntent().getStringExtra("Name");
facname.setText(Name);
String Sub = getIntent().getStringExtra("Sub");
subjectchosen.setText(Sub);
Attendusn = getIntent().getExtras();
if(Attendusn!=null)
{
AttendStud_usn = (ArrayList<String>)Attendusn.getStringArrayList("AttendStud_usn");
}
String AttendLen = String.valueOf(AttendStud_usn.size());
//int flag = 0 ;
//subjectchosen.setText(String.valueOf(AttendStud_usn));
myListView = (ListView) findViewById(R.id.lvnames);
// myListView.setAdapter(new ArrayAdapter<String>(this, R.layout.listdecoration,R.id.tvlistdecor, AttendStud_usn));
//ArrayAdapter<String> MyAdapter= new ArrayAdapter<String>(this,R.layout.listdecoration, R.id.tvlistdecor,AttendStud_usn);
//myListView.setAdapter(MyAdapter);
myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View item, int position,
long id) {
// TODO Auto-generated method stub
Stud_usn usn= MyAdapter.getItem(position);
usn.toggleChecked();
Stud_usnViewHolder vh_usn= (Stud_usnViewHolder) item.getTag();
vh_usn.getCheckBox().setChecked(usn.isChecked());
}
});
MyAdapter = new Stud_Adapter(this,AttendStud_usn);
myListView.setAdapter(MyAdapter);
}
private static class Stud_usn{
private String usn_no="";
private boolean checked=true;
public Stud_usn(String usn_no){
this.usn_no = usn_no;
}
public String getUsn(){
return usn_no;
}
public void setChecked(boolean checked){
this.checked=checked;
}
public Object isChecked() {
// TODO Auto-generated method stub
return checked;
}
public String toString(){
return usn_no;
}
public void toggleChecked() {
// TODO Auto-generated method stub
checked = !checked;
}
}
private static class Stud_usnViewHolder{
private CheckBox checkbox;
private TextView textview;
public Stud_usnViewHolder(TextView textview, CheckBox checkbox){
this.checkbox=checkbox;
this.textview=textview;
}
public CheckBox getCheckBox() {
// TODO Auto-generated method stub
return checkbox;
}
public TextView getTextView(){
return textview;
}
}
private static class Stud_Adapter extends ArrayAdapter<Stud_usn>{
public LayoutInflater inflater;
public Stud_Adapter(Context context, List<String> attendStud_usn) {
super(context,R.layout.listdecoration,R.id.tvlistdecor);
// TODO Auto-generated constructor stub
inflater = LayoutInflater.from(context);
}
public View getView(int position, View convertView, ViewGroup parent){
Stud_usn usn = (Stud_usn) this.getItem(position);
CheckBox checkbox;
TextView textview;
if(convertView == null){
convertView = inflater.inflate(R.layout.listdecoration,null);
textview = (TextView) convertView.findViewById(R.id.tvlistdecor);
checkbox = (CheckBox) convertView.findViewById(R.id.cbusn_checked);
}
return convertView;
}
}
}
The view objects are recycled. You have to store that info sepperately. Not in the view but in the with the data you use in the adapter. When generating the views use this info to set the button state again.
You have to implement a custom adapter. Use the BaseAdapter class.
After researching / reviewing code the past couple days, a solution eludes me. The ArrayAdapter.getView() function is not being called.
ArrayAdapter.getCount() is returning 3.
This listview is similar to the WiFi preference fragment ..
https://android.googlesource.com/platform/packages/apps/Settings.git/+/6829c48c36fceebb46989f8ee25c369fa5f7adeb/src/com/android/settings/wifi/WifiSettings.java
The code samples at GitHub (using title search terms) show that this should be working.
Queries through stackoverflow for "getView not called" have suggested that
the List was not being passed in,
the count was not being returned,
the ArrayAdapter was not attached to the ListView properly using setListAdapter vs setAdapter
the ArrayAdapter and ListView scope need to be class vs method level
the ListView may not be visible, thus android knows it would not be able to draw it on the screen so getView() method is never called to render the objects.
Provided below are the PreferenceFragment and ArrayAdapter Classes, and XML files.
Your Thoughts?
PreferenceFragment Class
public class Settings_WebServers extends PreferenceFragment
{
protected MyAdapter adapter = null;
protected ListView lv = null;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate (savedInstanceState);
addPreferencesFromResource(R.xml.settings_webservers);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
super.onCreateView (inflater, container, savedInstanceState);
View v = inflater.inflate (R.layout.webservers, container, false);
List<String> strings = new ArrayList<String> ();
strings.add ("WebServer 1");
strings.add ("WebServer 2");
strings.add ("WebServer 3");
adapter = new MyAdapter (container.getContext(), R.layout.webservers_list, strings);
lv = (ListView) v.findViewById (android.R.id.list);
lv.setAdapter (adapter);
return v;
}
#Override
public void onStart()
{
super.onStart();;
Log.d ("onStart ", "Entered Function" );
Log.d ("ListView ", String.valueOf(lv.isShown()?"shown":"hidden"));
}
// ArrayAdapter embedded class
ArrayAdapter Class
private class MyAdapter extends ArrayAdapter<String>
{
Context context;
List<String> strings = new ArrayList<String>();
int layoutResourceId;
public MyAdapter(Context context, int layoutResourceId, List<String> objects)
{
super(context, layoutResourceId, objects);
this.layoutResourceId = layoutResourceId;
this.strings = objects;
this.context = context;
}
#Override
public int getCount ()
{ return (strings.size()); }
#Override
public View getView (int position, View convertView, ViewGroup parent)
{
Log.d ("getView position", String.valueOf (position) );
TextView lblServerName = null;
String current = strings.get (position);
LayoutInflater inflater =
(LayoutInflater) context.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate
(R.layout.webservers_list, parent, false);
lblServerName = (TextView) convertView.findViewById (R.id.txtServerName);
if (lblServerName != null)
lblServerName.setText (String.valueOf(current));
return convertView;
}
}
}
Preference Header Segment
<header
android:fragment="ENetArch.Todo.Settings_WebServers"
android:icon="#drawable/icon_server"
android:title="WebServers"
android:summary="A list of servers to synchronize with"/>
xml.settings.webservers.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
</PreferenceScreen>
layout.webservers.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
layout.webservers_list.xml
<?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="?android:attr/listPreferredItemHeight"
android:padding="6dip">
<TextView
android:id="#+id/txtServerName"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="match_parent"
android:text="ENetArch"
/>
</LinearLayout>
Log Trace
04-25 15:33:02.840: D/onCreateView(2941): Entered Function
04-25 15:33:02.930: D/MyAdapter(2941): construct entered
04-25 15:33:02.930: D/MyAdapter(2941): construct exited
04-25 15:33:02.950: D/getCount(2941): 3
04-25 15:33:02.950: D/getCount(2941): 3
04-25 15:33:02.950: D/onCreateView(2941): Exiting Function
04-25 15:33:03.070: D/onStart(2941): Entered Function
04-25 15:33:03.070: D/ListView(2941): hidden
I am trying to create a ListView where each item contains a TextItem and a ListView (dynamic length) but for some reason only one item is shown in the inner ListView. Is this something that is not possible or am I doing something wrong?
Here is my layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/outerListId"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Inner list item:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Profile Name"
android:id="#+id/nameId"/>
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/innerListId"/>
</RelativeLayout>
Code:
public class ListAllActivity extends Activity {
protected class MyListItem {
public String name;
public List<String> items;
public MyListItem(String name) {
this.name = name;
this.items = items();
}
public List<String> items() {
ArrayList<String> strings = new ArrayList<String>();
strings.add("item1");
strings.add("item2");
return strings;
}
}
public class CustomListViewAdapter extends ArrayAdapter<MyListItem> {
Context context;
public CustomListViewAdapter(Context context, int resourceId, List<MyListItem> items) {
super(context, resourceId, items);
this.context = context;
}
private class ViewHolder {
TextView nameText;
ListView myList;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
MyListItem rowItem = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.profile_exercises_list_item, null);
holder = new ViewHolder();
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.nameText = (TextView) convertView.findViewById(R.id.profileNameListItemId);
holder.myList = (ListView) convertView.findViewById(R.id.innerListId);
List<String> items = rowItem.items();
holder.nameText.setText(rowItem.name);
ArrayAdapter<String> myarrayAdapter = new ArrayAdapter<String>(convertView.getContext(), android.R.layout.simple_list_item_1, items);
holder.myList.setAdapter(myarrayAdapter);
holder.myList.setTextFilterEnabled(true);
return convertView;
}
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mylayout);
ListView listView = (ListView) findViewById(R.id.outerListId);
ArrayList<MyListItem> allItems = new ArrayList<MyListItem>();
allItems.add(new MyListItem("name1"));
allItems.add(new MyListItem("name2"));
CustomListViewAdapter all = new CustomListViewAdapter(this, android.R.layout.simple_list_item_1, allItems);
listView.setAdapter(all);
listView.setTextFilterEnabled(true);
}
}
Instead of using Nested ListViews, you can use Expandable ListView.
Here are some useful links for playing with expandable ListView.
http://www.dreamincode.net/forums/topic/270612-how-to-get-started-with-expandablelistview/
http://android-adda.blogspot.com/2011/06/custom-expandable-listview.html