I'm probably missing something simple here, but I just can't see it...
So, I have a vanilla ListView a custom adapter and a relative layout.
Currently, items in the listview don't show. However, the custom adapter works, as long as the listview is not in a relative layout (ex: frame layout). On the other side, I can have the listview in a relative layout... as long as I don't use my custom adapter.
public class MainActivity : Activity
{
int count = 1;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
ListView list = new ListView (this);
list.SetBackgroundColor (Android.Graphics.Color.Red);
RelativeLayout rl = new RelativeLayout (this);
rl.SetBackgroundColor (Android.Graphics.Color.Blue);
TextView tv = new TextView (this);
tv.Text = "Some text";
tv.SetBackgroundColor (Android.Graphics.Color.Green);
rl.AddView (tv, new RelativeLayout.LayoutParams (400, 100));
List<RelativeLayout> views = new List<RelativeLayout>();
views.Add (rl);
testAdapter adapter = new testAdapter (views, this);
//ArrayAdapter<string> arrayAdapter = new ArrayAdapter<string> (this, Android.Resource.Layout.SimpleListItem1);
//arrayAdapter.Add ("cell 1");
list.Adapter = adapter;
RelativeLayout listContainer = new RelativeLayout (this);
listContainer.AddView (list, new ViewGroup.LayoutParams (400, 600));
listContainer.SetBackgroundColor (Android.Graphics.Color.LightGray);
this.AddContentView (listContainer, new ViewGroup.LayoutParams (ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent));
}
}
class testAdapter:BaseAdapter{
List<RelativeLayout> views = new List<RelativeLayout>();
Android.Content.Context context;
public testAdapter(List<RelativeLayout> inView, Android.Content.Context cntx){
views = inView;
context = cntx;
}
#region implemented abstract members of BaseAdapter
public override Java.Lang.Object GetItem (int position)
{
return position;
}
public override long GetItemId (int position)
{
return position;
}
public override View GetView (int position, View convertView, ViewGroup parent)
{
RelativeLayout temp;
if (convertView != null) {
temp = (RelativeLayout)convertView;
temp.SetBackgroundColor (Android.Graphics.Color.Green);
} else {
temp = new RelativeLayout (context);
}
temp.RemoveAllViews ();
if (position < views.Count) {
RelativeLayout refView = views [position];
View refParent = (View)refView.Parent;
if (refParent != null)
((ViewGroup)refParent).RemoveView (refView);
temp.AddView (refView);
temp.SetBackgroundColor (Android.Graphics.Color.Green);
}
return (View)temp;
}
public override int Count {
get {
return views.Count;
}
}
#endregion
}
At this point, I only need to change listContainer from a RelativeLayout to a FrameLayout and everything is well. Or I could keep the relative layout and change the adapter to the arrayAdapter that I commented out. I know this is doable but I'm not using any wrap content that usually causes these kind of issues.
Something else: The cell returned by the getView never gets any dimensions. However, if I were to force some dimensions (ex: by adding below temp.SetBackgroundColor (Android.Graphics.Color.Green); something like temp.LayoutParameters = new AbsListView(300, 100);) the green cell will actually appear, but not its content.
Sorry but for a lack of reputation i can't comment, only reply.
Maybe it's not the solution you were looking for but it might work: have you tryed leaving the list in a FrameLayout and placing the FrameLayout in a RelativeLayout?
Related
I have a ListView managed by an ArrayList/ArrayAdapter.
The ListView item is defined in an XML layout file.
At initialisation time (onCreate) I load the ListView with a variable number of items and, at that moment, I need to assign a listener to one subview (a SeekBar) of each item.
This is the relevant part of the code:
private String TAG = "MainActivity";
private ListView lv_controlli;
private ArrayAdapter<String> adapter;
private LinkedHashMap<String, String> hmControlli;
private ArrayList<String> controlli;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Init();
}
private void Init() {
lv_controlli = (ListView) findViewById(R.id.LV_Controls);
hmControlli = new LinkedHashMap<String, String>();
for (int i = 0; i < 6; i++) hmControlli.put(String.valueOf(i), "Gruppo " + i);
controlli = new ArrayList<String>(hmControlli.keySet());
adapter = new ArrayAdapter<String>(this, R.layout.control_layout, R.id.LBL_Controllo, controlli);
lv_controlli.setAdapter(adapter);
for (int i = 0; i < lv_controlli.getChildCount(); i++) {
SeekBar sb = (SeekBar) lv_controlli.getChildAt(i).findViewById(R.id.SB_Intensita);
sb.setOnSeekBarChangeListener(valueOnChange);
}
}
private SeekBar.OnSeekBarChangeListener valueOnChange = new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
Log.i(TAG,String.valueOf(seekBar.getProgress()));
}
...
};
public void click(View view) {
for (int i = 0; i < lv_controlli.getChildCount(); i++) {
SeekBar sb = (SeekBar) lv_controlli.getChildAt(i).findViewById(R.id.SB_Intensita);
sb.setOnSeekBarChangeListener(valueOnChange);
}
}
No listeners are assigned by Init() routine (called by onCreate()) because its execution happens when the ListView has not been already loaded, even though the adapter as been populated and assigned to the ListView.
The same kind of code works perfectly, instead, in the click() routine associated to a button that I press when the control is returned to the user.
So I can get the SeekBars actually usable only after my interaction and this is bad, of course.
Is there any point where the populated ListView is available before the control is returned to the user?
Thanks a lot in advance for your help.
Chances are good that the right way to solve this problem is not by trying to find a moment in time between onCreate() and when control of the app passes to the user, but by assigning your OnSeekBarChangeListener to the SeekBar inside your adapter.
You can create a subclass of ArrayAdapter that you use instead of the base ArrayAdapter implementation, then override getView() to add the listener. Something like:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
SeekBar seekBar = (SeekBar) v.findViewById(R.id.SB_Intensita);
seekBar.setOnSeekBarChangeListener(valueOnChange);
return v;
}
I'm using RecyclerView on my android project. Today I had to change RecyclerView's right margin(or height & width or position... anything) when adapter's onBindViewHolder is called.
However I just ran into the problem the RecyclerView(or any views outside RecyclerView)'s size or position or margin... is not changed from adapter's onBindViewHolder(or any methods in adapter) method.
I tried with many ways but I gained no lucks. Can anybody tell what am I missing? :(
This is my code.
CODE
public class DataDashboardFragment extends Fragment {
private RecyclerView rvDashboard = null;
private DataDashboardAdapter adapter = null;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.data_dashboard, container, false);
rvDashboard = (RecyclerView) v.findViewById(R.id.data_dashboard);
adapter = new DataDashboardAdapter();
rvDashboard.setAdapter(adapter);
// Here I add items which extracted from SQLite DAO.
List<DailyDataUsage> items = SomeDAO.getItems();
adapter.clear();
adapter.addAll(items);
adapter.NDSC();
return v;
}
...
// Adapter
public class DataDashboardAdapter extends Adapter<DataDashboardViewHolder> {
private List<DailyDataUsage> items = new ArrayList<DailyDataUsage>();
...
public void clear() {
this.items.clear();
}
public void NDSC() {
// Some edits of data before notifyDataSetChanged.
...
super.notifyDataSetChanged();
}
public void addAll(Collection<? extends DailyDataUsage> items) {
this.items.addAll(items);
}
#Override
public void onBindViewHolder(DataDashboardViewHolder holder, int position) {
// rvDashboard's right margin won't be changed :(
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) rvDashboard.getLayoutParams();
int rightMargin = 500;
params.setMargins(0, 0, rightMargin, 0);
rvDashboard.setLayoutParams(params);
rvDashboard.requestLayout();
}
}
// ViewHolder
public static class DataDashboardViewHolder extends ViewHolder {
...
}
}
Any advice or similar experience would be thankful!
P.S. It works from fragment's onCreateView method(maybe some methods before create views) though.
Actually you can change in onCreateView method in onBindViewHolder method you can set margin to the holder elements or to the total layout of adapter and not to the RecyclerView . Actually why do you Need to set margin to RecyclerView at onBindViewHolder?
When a user enters a word, it creates Buttons - one Button per letter of the word:
Illustration:
If the user enters "so" it creates 2 Buttons - 's', 'o'
If the user enters "make" it creates 4 Buttons - 'm', 'a', 'k', 'e'
I was having a hard time deciding how I should design this. Ultimately I decided to do the following: Each word is added to a vertical LinearLayout. And for each word, each letter is added to a horizontal LinearLayout. So it's a LinearLayout within a LinearLayout approach.
Here's the code I created which works:
//creates words dynamically
public void makeNewWord(LinearLayout ll, View v, EditText e){
//the horizontal linear layout
LinearLayout linearLayout2 = new LinearLayout(v.getContext());
linearLayout2.setOrientation(LinearLayout.HORIZONTAL);
//the parameters for the horizontal linear layout
LinearLayout.LayoutParams rlp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
//e is the user input
int size = e.getText().toString().length();
for (int i=0; i<size; i++){
final Button dynamicButtons = new Button(v.getContext());
dynamicButtons.setLayoutParams(rlp);
//add the buttons to the horizontal linear layout
linearLayout2.addView(dynamicButtons, rlp);
}
// ll is the vertical linear layout which I created in xml
// so for each entered word, I am adding horizontal linear layouts to my vertical layout
ll.addView(linearLayout2, 0);
}
But now I realized it's probably more efficient using a ListView, especially since I want to make the list of words to be expandable and collapsible. But Is it possible to create the above illustration using a ListView? How would I go about doing so?
I tried creating an ArrayAdapter as follows: ArrayAdapter<LinearLayout> adapter = new ArrayAdapter<LinearLayout>(this, R.id.listview). So basically it would be a ListView of horizontal LinearLayouts. Or should I make an ArrayAdapter of Buttons instead? What is the correct approach?
I can give some idea you can transform this idea in code
1. onTextChanged() method try to get length of text.
2. If you able to get text length then by subString() method get last entered text
3. Then recreate new button instance
You can use a TableLayout for this.
test.xml
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent">
<TableLayout
android:id="#+id/table_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</TableLayout>
</ScrollView>
Activity Code
private TableLayout tableLayout;
private HashMap<String, TableRow> tableRows;
#Override
public void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.test);
super.onCreate(savedInstanceState);
tableLayout = (TableLayout) findViewById(R.id.table_layout);
tableRows = new HashMap<String, TableRow>();
}
public void addWord(String word) {
if (!tableRows.containsKey(word)) {
TableRow tableRow = new TableRow(this);
for (int i = 0; i < word.length(); i++) {
String letter = String.valueOf(word.charAt(i));
Button btnLetter = new Button(this);
btnLetter.setText(letter);
tableRow.addView(btnLetter);
}
tableRows.put(word, tableRow);
tableLayout.addView(tableRow);
}
}
public void removeWord(String word) {
TableRow tableRow = tableRows.remove(word);
if (tableRow != null) {
tableLayout.removeView(tableRow);
}
}
public void showWord(String word) {
TableRow tableRow = tableRows.get(word);
if (tableRow != null) {
tableRow.setVisibility(View.VISIBLE);
}
}
public void hideWord(String word) {
TableRow tableRow = tableRows.get(word);
if (tableRow != null) {
tableRow.setVisibility(View.GONE);
}
}
Assuming you want a specific button setup, you can inflate an xml button layout dynamically. See here for details.
I would just use a horizontal list view per word.
I you want to be fancy you create a custom layout manager and the new RecyclerView.
Each character of your word would be then a item in your list view. The layout then could be simply a button.
class ListAdapter extends BaseAdapter {
private final Context fContext;
private String mWord;
public ListAdapter(Context context) {
fContext = context;
}
public void updateWord(String word) {
mWord = word;
notifyDataSetChanged();
}
#Override
public int getCount() {
return mWord == null ? 0 : mWord.length();
}
#Override
public String getItem(int position) {
return String.valueOf(mWord.charAt(position));
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Button button;
if (convertView == null) {
button = new Button(parent.getContext());
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
button.setLayoutParams(params);
} else {
button = (Button) convertView;
}
button.setText(getItem(position));
return button;
}
}
On every text change you can then just update the list.
adapter.updateWord();
Be aware the code is just out of my head and i haven't tested this, but should be enough to give you and idea.
I am totally confuse with my image list view.
I want to display 2 video poster and text view in a single row with background container ( check attach image of train)
This is single cell of vertical List view.
Depending on number of videos i have to display vertical list view but each row contain 2 video poster and text view at side of it video with train Engine image at start or end vice versa of row number.
To achieve this UI i write a custom adaptor in which i manage to display train wagon with related image-view by using relative layout.
but how can i manage on-click listener on particular item (particular video in row) on single row.and how can i add train image at start or end of each row
here is output of my code.
Here is my code
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
final Context context = CustomAdapterExample.this;
ListView ls2 = new ListView(context);
// clear previous results in the LV
ls2.setAdapter(null);
// populate
ArrayList<Device> videos = new ArrayList<Device>();
Device my_video;
for (int i=0;i<05;i++) {
my_video = new Device("video link","Video id");
videos.add(my_video);
}
CustomAdapter lvAdapter = new CustomAdapter(context, videos);
ls2.setAdapter(lvAdapter);
ls2.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> arg0, View arg1,int arg2, long arg3)
{
Toast.makeText(getBaseContext(), "You clicked on "+arg2, Toast.LENGTH_LONG).show();
}
});
setContentView(ls2);
}
And here is adaptor
class CustomAdapterView extends LinearLayout {
public CustomAdapterView(Context context, Device device)
{
super( context );
//container is a horizontal layer
setOrientation(LinearLayout.HORIZONTAL);
setPadding(0, 6, 0, 6);
LinearLayout Mainview = new LinearLayout(context);
LinearLayout.LayoutParams Cellparams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
Mainview.setLayoutParams(Cellparams);
ImageView firstImageContainer = new ImageView(context);
ImageView trackImage = new ImageView(context);
ImageView VideoViewContainer = new ImageView(context);
TextView firsttext= new TextView(context);
firsttext.setText("Testing of app");
firsttext.setTextColor(Color.RED);
firstImageContainer.setBackgroundResource(R.drawable.wagon);
VideoViewContainer.setBackgroundResource(R.drawable.video);
RelativeLayout layout = new RelativeLayout(context);
RelativeLayout.LayoutParams firstContainerParams = new RelativeLayout.LayoutParams(160, 80);
layout.setLayoutParams(firstContainerParams);
trackImage.setBackgroundResource(R.drawable.line);
RelativeLayout.LayoutParams trackRules = new RelativeLayout.LayoutParams(755,5);
trackRules.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
RelativeLayout.LayoutParams firstImageContainerParams = new RelativeLayout.LayoutParams(140, 90);
RelativeLayout.LayoutParams VideoViewContainerParams = new RelativeLayout.LayoutParams(70,60);
VideoViewContainerParams.addRule(RelativeLayout.CENTER_VERTICAL);
VideoViewContainerParams.setMargins(5, 0, 0, 0);
layout.addView(firstImageContainer, firstImageContainerParams);
layout.addView(VideoViewContainer, VideoViewContainerParams);
layout.addView(trackImage, trackRules);
ImageView secondImageContainer = new ImageView(context);
ImageView secondtrackImage = new ImageView(context);
ImageView secondVideoViewContainer = new ImageView(context);
secondImageContainer.setBackgroundResource(R.drawable.wagon);
secondVideoViewContainer.setBackgroundResource(R.drawable.video);
RelativeLayout secondLayout = new RelativeLayout(context);
RelativeLayout.LayoutParams secondContainerParams = new RelativeLayout.LayoutParams(160, 80);
secondLayout.setLayoutParams(firstContainerParams);
secondtrackImage.setBackgroundResource(R.drawable.line);
RelativeLayout.LayoutParams secondtrackRules = new RelativeLayout.LayoutParams(755,5);
trackRules.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
RelativeLayout.LayoutParams secondImageContainerParams = new RelativeLayout.LayoutParams(140, 90);
RelativeLayout.LayoutParams secondVideoViewContainerParams = new RelativeLayout.LayoutParams(70,60);
secondVideoViewContainerParams.addRule(RelativeLayout.CENTER_VERTICAL);
secondVideoViewContainerParams.setMargins(5, 0, 0, 0);
secondLayout.addView(secondImageContainer, secondImageContainerParams);
secondLayout.addView(secondVideoViewContainer, secondVideoViewContainerParams);
secondLayout.addView(secondtrackImage, secondtrackRules);
firstContainerParams.addRule(RelativeLayout.ALIGN_LEFT);
secondImageContainerParams.addRule(RelativeLayout.ALIGN_RIGHT);
Mainview.addView(layout,firstContainerParams);
Mainview.addView(secondLayout,secondContainerParams);
addView(Mainview);
}
}
public class CustomAdapter extends BaseAdapter /*implements OnClickListener*/ {
public static final String LOG_TAG = "BI::CA";
private Context context;
private List<videoData> videolist;
public CustomAdapter(Context context, List<Device> videolist ) {
this.context = context;
this.videolist = videolist;
}
public int getCount() {
return videolist.size();
}
public Object getItem(int position) {
return videolist.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent)
{
Device device = videolist.get(position);
View v = new CustomAdapterView(this.context, device );
return v;
}
}
If my implementation is wrong than please suggest me some guidance.
gallery is deprecated in API 17 i can't use it.
Is it possible to crate such Ui by using tableview or grid view??
Any Help is Appreciated.
Finally I figure it to display All contain same as on other device by using Include tag in list view layout.
<HorizontalScrollView
android:id="#+id/horizontalScrollView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<include android:id="#+id/train2" layout="#layout/train2" />
</HorizontalScrollView>
In train I have this
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<include android:id="#+id/boogi1" layout="#layout/boogi" />
<include android:id="#+id/boogi2" layout="#layout/boogi" />
<include android:id="#+id/engine" layout="#layout/engine" />
And to access each Image-view and textview i used
ImageView v1 = ((ImageView)vi.findViewById(R.id.train).findViewById(R.id.boogi1).findViewById(R.id.imageView1));
Thank you for support.
Just one question is it possible to change view for every row depending on position of row..
I think you need to try Custom Listview,,,
try this http://www.androidhive.info/2012/02/android-custom-listview-with-image-and-text/.
i am new in android and in a app i am developing i want to add a expandablelistview that cotains a registration page.
it can be like this,
Add Personal Details +
name(edittext)
ph_no(edittext)
email_id(edittext)
Save Button
Add Acocunt Details +
Transaction_id(edittext)
Transaction_type(edittext)
Total_amount(edittext)
Save Button
etc....
How can it possible?
you can use linearlayout which is in horizantal orientation and assign name for every linearlayout . so that you can expand to use expandable listview in a single xml file .
You have to create customized adapter for your Expandable listview.
you can use ExpandableListView and a customAdapter
the activity here implements onChildClickListener onGroupCollapseListener and onGroupExpandListener
Please note, i am jus typing code directly, there may be compilation errors, please fix if any, and if anything, please drop a comment
public class YourActivity extends Activity implements OnChildClickListener, OnGroupCollapseListener{
private ExpandableListView exList= null;
private ExpandableListAdapter mAdapter = null;
//add all unimplemented methods
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
placeHolder = (LinearLayout) findViewById(R.id.placeHolder);
exList= (ExpandableListView) findViewById(R.id.wl_list);
exList.setHorizontalFadingEdgeEnabled(true);
exList.setFastScrollEnabled(true);
exList.setHorizontalFadingEdgeEnabled(true);
exList.setFadingEdgeLength(30);
exList.setDividerHeight(1);
exList.isFocusable();
exList.setTextFilterEnabled(true);
exList.setSelectionAfterHeaderView();
exList.setSelected(true);
exList.setOnChildClickListener(this);
mAdapter = new ExpandableListAdapter(this);
exList.setAdapter(mAdapter);
exList.setOnGroupCollapseListener(this);
exList.setOnGroupExpandListener(this);
setContentView(exList);
}
public void onGroupCollapse(int groupPosition) {
// do whatever additional
exList.collapseGroup(groupPosition);
}
public void onGroupExpand(int groupPosition) {
// do whatever additional
exList.expandGroup(groupPosition);
}
}
and a custom adapter like, i have implemented only getChildView() method, please do the same for getGroupView() method for completion
public class ExpandableListAdapter extends BaseExpandableListAdapter {
private Activity activity;
public ExpandableListAdapter(Activity activity) {
this.activity = activity;
}
public View getCustomChildView(int groupPosition, int childPosition) {
WORKLIST_HEADER wfHeader = null;
//View view = null;
//if (view == null) {
// you can do this also, if you prefer filling up screens via xml, that is, inflate
//view = inflater.inflate(R.layout.wl_list_row, null);
//}
//or jus create a linear layout manually and add views to it like below and return the linear layout, this should do
TextView textView = null;
LinearLayout wflayout = new LinearLayout(activity);
textView = new TextView(activity);
textView.setText("name");
textView.setTextAppearance(activity, R.style.boldText);
wflayout.addView(textView);
textView = new TextView(activity);
textView.setText("email_id");
textView.setTextAppearance(activity, R.style.boldText);
wflayout.addView(textView);
// add more and button as well,
//return linear layout
return wflayout;
}
public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
View convertView, ViewGroup parent) {
return getCustomChildView(groupPosition, childPosition);
}
// add otehr unimplemented methods
}