Using Bitmap ArrayList to dynamically populate ListView - java

I'm new to android so please be tolerant to my lack of knowledge.
My app is taking photos and saving them to Bitmap ArrayList, it works, i tested it, photos are displayable using ImageViews. Everything responsible for taking pictures looks like this:
//declaration
List<Bitmap> bmpList = new ArrayList<Bitmap>();
//onClick method of button for takin pics
public void takePic(View view){
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 0);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
if(requestCode == 0){
Bitmap image = (Bitmap) data.getExtras().get("data");
bmpList.add(image);
adapter.notifyDataSetChanged(); //more about my adapter and stuff below
}
}
I also have ListView, i'm extending ListActivity instead of just Activity becouse i found that working solution for dynamic String ArrayList in web. XML declaration of ListView: (with that method i don't have to declare it in the Java code)
<ListView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/photoButton"
android:id="#android:id/list">
</ListView>
I also use Bitmap adapter:
ArrayAdapter<Bitmap> adapter;
and then initialize it inside of onCreate method:
adapter = new ArrayAdapter<Bitmap>(this, R.layout.item, bmpList);
setListAdapter(adapter);
item.xml is the problem i have. I don't know how to create working ListView item that contains ImageView capable of displaying my Bitmap ArrayList elements preferably on the left. I tried adding just a ImageView but app crashes after saving the photo. My go-to functionality is having photo on the left, short description in the middle and ratingbar on the right, clicking on item takes user to another Activity where one can modify the description and rating, also displaying photo in full size. Some kind of hint will go a long way! Thank you in advance!

You should implement a custom adapter, to work with your images, and inflate your list. You can find useful tutorial here, which describes how to use listViews and adapters, and how to create your own list items.
You can create your custom XML item layout like usual layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/icon"
android:layout_width="22px"
android:layout_height="22px"
android:layout_marginLeft="4px"
android:layout_marginRight="10px"
android:layout_marginTop="4px"
android:src="#drawable/ic_launcher" >
</ImageView>
<TextView
android:id="#+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#+id/label"
android:textSize="20px" >
</TextView>
</LinearLayout>
But for adding images to it, you must implement your own custom adapter.

Related

How to add string at the bottom of a ScrollView

I would like to know how to add new strings at the bottom of a ScrollView every time I press a button.
For example at the beginning there is sentence1, press button, then sentence2 is under sentence1, press button, sentence3 is under sentence2, etc
I know how to make a scrollView and I have an array of strings to display:
final int[] sentences = new int[]{
R.String.sentence1,
R.String.sentence1,
R.String.sentence2,
R.String.sentence3,
R.String.sentence4
};
And I know how to make them appear one after another when a button is pressed (kind off replacing the previous one, like a TextSwitch but without the animation) :
if(nextSentenceId < sentences.length) {
officeOBSDialog.setText(sentences[nextSentenceId]);
++nextSentenceId;
}
Do you have any idea how I could manage to do that or what could I use? It occured to me that I could use like a layout inflator but I don't know how to put that to practice and where to put it. Thanks in advance
I recommend you to use ListView or RecyclerView.
https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView
However, if you consistently want to use ScrollView cause your screen UI is simple. You can simply wrap a LinearLayout with vertical orientation by a ScrollView.
activity.xml
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true">
<LinearLayout
android:id="#+id/lnContainer"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- your button declaration -->
</LinearLayout>
</ScrollView>
In your activity java file, add new row programmatically by:
private int position=0;
final int[] sentences = new int[]{
R.String.sentence1,
R.String.sentence1,
R.String.sentence2,
R.String.sentence3,
R.String.sentence4
};
//inside onCreate() method
yourButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View view){
TextView textView = new TextView(YourActivityClass.this);
textView.setText(sentences[position++]);
((LinearLayout)findViewById(R.id.lnContainer)).addView(textView);
}
});

Dynamically add Relative Layouts that have the same layout as base

How do I dynamically generate a RelativeLayout based on a xml layout (posted below)? The relative layouts are being put in a linear layout that is the child of a scroll view.
<RelativeLayout
android:id="#+id/post_0"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp">
<TextView
android:id="#+id/op_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="8dp"
android:text="Username" />
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="250dp"
android:layout_below="#+id/op_username"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_marginStart="31dp"
android:layout_marginLeft="31dp"
android:layout_marginTop="15dp"
app:srcCompat="#android:drawable/btn_star_big_on"
tools:srcCompat="#android:drawable/btn_star_big_on" />
</RelativeLayout>
Let's suppose that you've all the Images and their TextView's texts in your Database, then create a RecyclerView (if there are a relatively huge number of items) or a simple ListView, and then create a CustomAdapter class to add your RelativeLayout to your main ListView/ ScrollView/ RecyclerView.
To completely implement this first you need to have an Item class which can store a user's Username and Image ( please note that you need to pass Image URI as a string) in an Object.
public class Items {
private final int id;
private final String image;
public Items(int id,String image){
this.name=name;
this.image=image;
}
//Include all the Getters and Setters here
}
Then assuming you've all your elements into an ArrayList<Items>, then you need to implement an Adapter class, called CustomAdaper which extends ArrayAdapter and need to write a function for getView to get a particular view to fill in your ScrollView/RecyclerView/ListView
I've found a link to help you implement a CustomAdapter here.
And finally in the MainActivity, you've to add few lines,
final ListView listView = (ListView) findViewById(R.id.list_view); //name of list view file
final ArrayList<Items> arrayList = dbHelper.retrieveFromDB(); // Name of the Database class and the function to retrieve all the elements into an ArrayList in that class
CustomAdapter adapter = new CustomAdapter(this /* The current Context */, R.layout.list_item, arrayList); // Create an object of custom adapter initialize it with the desired data (in this case the arrayList) and the layout required ( layout mentioned in the question)
listView.setAdapter(adapter);
If it is a dynamic list that can have a large number of items use a recyclerview and place that relative layout inside a cardview.
If the dynamic list has a maximum potential number of items that are also few in number, you could add the relative layout and hide them, then populate and then show them as needed, but i advice you lean toward the former.

How to use a ScrollView?

This is suppose to be a scroll view with all the content added from the Java code when response is received from the API.
The problem is that I can't find a way to display the information like this in a ScrollView. I tried using an ImageButton but I couldn't get the content in it then I tried using a Button but still couldn't achieve the desired effect please can someone suggest a way I could do this.
private Button makeButton(String targetName, final String i, LinearLayout.LayoutParams buttonLayoutParams) {
Button in = new Button(this);
in.setBackground(getResources().getDrawable(R.drawable.rectangle14));
in.setText(targetName);
in.setWidth(360);
in.setHeight(72);
in.setLayoutParams(buttonLayoutParams);
in.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent myIntent = new Intent(HomeActivity.this,XSavingDetailsActivity.class);
myIntent.putExtra("i" ,i);
HomeActivity.this.startActivity(myIntent);
}
});
return in;
}
You should use a RecyclerView .Each and every component within the RecyclerView is a CardView . Also you should learn about Material Design.
Apart from the above some useful links:
https://developer.android.com/guide/topics/ui/layout/cardview.html
https://www.androidhive.info/2016/01/android-working-with-recycler-view/
https://medium.com/#nileshsingh/android-cardview-101-everything-you-should-know-5bbf1c873f5a
Just make the top-level layout a ScrollView:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<TableLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:stretchColumns="1">
<!-- everything else -->
</TableLayout>

Setting contentview after button click

When my application starts I want to have a start game button. When the button is pressed I want another activity to be shown.
In XML I Setup the button like this:
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Start"
android:id="#+id/bttnStart"
android:onClick="startGame"
/>
And this is the Java function:
public void startGame(View v ){
setContentView(R.layout.activity_start_menue);
}
My app crashes when I click the button.
Calling setContentView() multiple times is dangerous, and doesn't always work. There can be hierarchy conflicts, and inefficiencies that result from instantiating views multiple times. It's also not that helpful, because you're not in control of the container that the layout expands into.
Here is the proper way to do it.
Android provides a built-in mechanism for view-switching called a ViewFlipper. Instead of calling setContentView() for the layout you want to swap in, you can tell the ViewFlipper object to either showNext() or setDisplayedChild(int).
Here's how you would accomplish that in your main.xml.
<?xml version="1.0" encoding="utf-8"?>
<ViewFlipper xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/viewflipper"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<!-- The ViewFlipper can change through its direct children -->
<!-- Child 0 -->
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Start"
android:id="#+id/bttnStart"
android:onClick="startGame"/>
<!-- Child 1 -->
<LinearLayout
android:id="#+id/activity_start_menu"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Here's the menu!"/>
</LinearLayout>
</ViewFlipper>
Note that the views being flipped through are direct children of the <ViewFlipper> that you are using. FYI, you can have more than just two views.
Now onto the Java code in your `MyActivity'.
public class MyActivity extends Activity {
ViewFlipper viewFlipper;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
viewFlipper = (ViewFlipper) findViewById(R.id.viewflipper);
}
/**
* Switches to the activity_start_menu LinearLayout
* specified in the ViewFlipper.
*/
public void startGame(View v) {
//First way -- use showNext() & showPrevious()
viewFlipper.showNext();
//Second way -- use setDisplayedChild(int) where int is
// the index of the view starting from 0
//In this case, there are two. 0 is the button,
// and 1 is the menu layout.
viewFlipper.setDisplayedChild(1);
//You can also do fancy animations to switch between views.
// Check out the methods accessible and experiment with them!
}
}
You should end up with something like this:
Start activity
Draft:
onCreate()
setContentView(//layout 1);
Button lButton = (Button) findview....
lButton.setOnClickListener(...)
{
onClick()
{
setContentView(//layout 2);
}
}
To start new activity you should use:
Intent intent = new Intent(this, YourActivity.class);
startActivity(intent);
Or if you wouldn't change activity use for eample viewswitcher to switch layout, fragments etc

How to get the setOnCheckedChangeListener (ListView Checkboxes to work)

I flagged the other thread to be deleted, because the main question was edited so many times, that it become confusing.
So the problem is: I want to populate a ListView with checkboxes, and as I want to customize my ListView I'm not using simple_multiple_choice_mode, I'm putting my layout on list_item.xml: (for each row)
<CheckBox>
xmlns:android="http://schemas.android.com/apk/res/android" android:paddingLeft="8mm"
android:layout_width="fill_parent"
android:layout_height="wrap_removed" android:id="#+id/nomeAPP" style="?listItem">
</<CheckBox>
My ListView is on lista.xml
<ListView android:id="#android:id/list"
android:layout_width="fill_parent" android:layout_height="wrap_content"
style="?whiteBackground">
my adapter:
list=getListView();
this.setListAdapter(new ArrayAdapter<String>(this,
R.layout.list_item, aux))
So I'm trying to make a setOnCheckedChangeListener for the checkboxes, so I can store the chosed items in an array.
So I did this listener :
CheckBox cb = (CheckBox) findViewById(R.id.CheckBox01);
cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// TODO Auto-generated method stub
if (buttonView.isChecked()) {
Toast.makeText(getBaseContext(), "Checked",
Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(getBaseContext(), "UnChecked",
Toast.LENGTH_SHORT).show();
}
}
});
Problem is: I get the NULL exception. The CURIOUS thing is: if I "switch" my layout for a simple
<ScrollView android:id="#+id/widget54" android:layout_width="fill_parent"
android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout android:orientation="vertical"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<CheckBox android:text="Checkbox" android:id="#+id/CheckBox01"
android:layout_width="wrap_content" android:layout_height="wrap_content"></CheckBox>
</LinearLayout>
</ScrollView>
And forget my ListView (and my adapter), it works! So, what's wrong with my layout?
I created a new little project just to let you guys see exactly the situation. It's available HERE Right now does not work, but if you uncomment the adapter, change ListActivity to Activity and change setContentView, it will work (checked/unchecked toast text).
Another curious thing I found is that with ListActivity does not work never.... wondering if it's related...
ok, i think i got your problem,
CheckBox cb = (CheckBox) findViewById(R.id.CheckBox01);
This works in the second layout, because you might have already set the view for the activity using setcontentview().
So , the problem in your list activity is that , the above mentioned line doesn't know , which layout it has to look for to find id,
R.id.CheckBox01
you have to get access to the layout view which you are inflating the listview , lets call it a inflatedView, and then you access the check box like this.
CheckBox cb = (CheckBox) inflatedView.findViewById(R.id.CheckBox01);
if you don't set the content view, you have to tell the function findViewById(), where it has to look for the view.
I would confirm this, if you post the NPE log.
HTH.

Categories

Resources