So my application requires me to create a route for a certain bus. I have accomplished this and have created a custom info window for the marker. Now, I was asked to add a feature in which I need to show on the map POIs (points of interests) around the marker. I have successfully created this. However, I want a different Info window for these POI markers.
Here is my first info window:
public class InfoAdapter implements GoogleMap.InfoWindowAdapter {
LayoutInflater inflater = null;
private TextView textViewstopName;
private TextView arrivalTime;
public InfoAdapter(LayoutInflater inflater) {
this.inflater = inflater;
}
#Override
public View getInfoWindow(Marker marker) {
View v = inflater.inflate(R.layout.businfo_layout, null);
if (marker != null) {
textViewstopName = (TextView) v.findViewById(R.id.businfo);
textViewstopName.setText(marker.getTitle());
arrivalTime = (TextView) v.findViewById(R.id.arrivalinfo);
arrivalTime.setText(marker.getSnippet());
}
return (v);
}
#Override
public View getInfoContents(Marker marker) {
return (null);
}
}
And here is my second one (I wanted to have to default one for the POIs for now):
public class PlacesAdapter implements GoogleMap.InfoWindowAdapter{
LayoutInflater inflater = null;
public PlacesAdapter(LayoutInflater inflater) {
this.inflater = inflater;
}
#Override
public View getInfoWindow(Marker marker) {
return null;
}
#Override
public View getInfoContents(Marker marker) {
return null;
}
}
Here is where I called the first one:
private void SetupStopMarkers(){
map.setInfoWindowAdapter(new InfoAdapter(getLayoutInflater()));
addMarkersToMap(markerPoints);
}
Here is where I called the second one:
else{
map.setInfoWindowAdapter(new PlacesAdapter(getLayoutInflater()));
...
}
My info_layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="1"
android:background="#drawable/businfo_dialog">
<ImageView
android:id="#+id/busicon"
android:layout_width="30dp"
android:layout_height="30dp"
android:src="#drawable/busstop_icon"/>
<ImageView
android:id="#+id/clockicon"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_below="#+id/busicon"
android:layout_alignParentLeft="true"
android:paddingLeft="5dp"
android:src="#drawable/clock"
android:paddingBottom="10dp"/>
<TextView
android:id="#+id/businfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFFFF"
android:drawablePadding="10dp"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/busicon"
android:layout_toEndOf="#+id/busicon"
android:paddingRight="10dp"
android:paddingTop="5dp"
android:layout_alignParentTop="true" />
<TextView
android:id="#+id/arrivalinfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFFFF"
android:drawablePadding="10dp"
android:layout_centerVertical="true"
android:layout_below="#+id/businfo"
android:layout_toRightOf="#+id/clockicon"
android:layout_toEndOf="#+id/clockicon"
android:paddingRight="10dp"
android:paddingTop="5dp"/>
<TextView
android:id="#+id/placesinfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/arrivalinfo"
android:paddingTop="5dp"
android:paddingBottom="35dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:textColor="#0099cc"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:text="#string/more_info"/>
<TextView
android:id="#+id/eta_i"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/arrivalinfo"
android:layout_toEndOf="#+id/arrivalinfo"
android:paddingLeft="5dp"
android:paddingTop="5dp"
android:layout_alignTop="#+id/arrivalinfo"
android:text="ETA:"
android:textStyle="bold"
android:textColor="#FFFFFFFF"/>
</RelativeLayout>
But after calling the second info window, every marker in the map changes to that second info window. Is there a way to do this? Any help is appreciated.
Got it. So to get multiple Info windows, I had to get the marker ids corresponding to the markers. So I created a ArrayList that takes in the "id" of the marker.
ArrayList<String> markerPlaces = new ArrayList<>();
I then populated it as I add the markers to the map:
Marker marker = map.addMarker(new MarkerOptions().position(position)
.title(venuesfound.get(i).getName())
.snippet("\nOpen: " + venuesfound.get(i).getOpenNow()
+ "\n(" + venuesfound.get(i).getCategory() + ")")
.icon(BitmapDescriptorFactory.fromResource(R.drawable.measle_blue)));
markerPlaces.add(marker.getId());
Then on the InfoAdapter, I just added a condition that if the marker id is in the ArrayList that I created, then put in a different inflater.
public class InfoAdapter implements GoogleMap.InfoWindowAdapter {
LayoutInflater inflater = null;
private TextView textViewstopName;
private TextView arrivalTime;
public InfoAdapter(LayoutInflater inflater) {
this.inflater = inflater;
}
#Override
public View getInfoWindow(Marker marker) {
if (marker != null) {
if(markerPlaces.containsKey(marker.getId())) {
... //Add new inflater here.
} //checks if the marker is part of the Position marker or POI marker.
else{
View v = inflater.inflate(R.layout.businfo_layout, null);
textViewstopName = (TextView) v.findViewById(R.id.businfo);
textViewstopName.setText(marker.getTitle());
arrivalTime = (TextView) v.findViewById(R.id.arrivalinfo);
arrivalTime.setText(marker.getSnippet());
return (v);
}
}
return null;
}
#Override
public View getInfoContents(Marker marker) {
return (null);
}
}
Thank you all for the help! It certainly got me thinking!
Related
I have a class called AnimalMarker which should represent the bare minimum of a normal google maps Marker (latitude, longitutde, location) and an object Animal. And I'm using the Firebase Realtime Database to store those AnimalMarkers.
What I want to do, but don't know how to do it, is create a custom InfoWindow (I've created the new layout and an Adapter that should be passed in the MapActivity) that even though is binding to the google maps Markers, should take data from the corresponding AnimalMarker of that Marker.
The logic of my MapActivity is:
create an AnimalMarker using the latitude,longitute, and taking user input for adding an animal to it. now the AnimalMarker object has been created
add the AnimalMarker to the Firebase Realtime Database
when the DatabaseListener gets the update, it will call a method in the MapActivity to re-create the List of google-maps Markers and re-draw them.
I realise now that instead of saving just the google-maps Markers in a List, a Hashmap < AnimalMarker, Marker > would be better, and update the Hashmap when the database Listener notices the update But even so, I wouldn't know how to make the InfoWindowAdapter take the data from the associated AnimalMarker of a Marker.
Here is my code:
MapActivity
public class MapActivity extends FragmentActivity implements OnMapReadyCallback, GoogleApiClient.OnConnectionFailedListener {
...
private void initListeners() {
Log.d(TAG, "initListeners: initializing SearchText");
firebaseAuth = FirebaseAuth.getInstance();
geocoder = new Geocoder(MapActivity.this);
markersDatabase = new MarkersDatabase();
myMarkersList = new ArrayList<>();
allMarkersList = new ArrayList<>();
mMap.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener(){
#Override
public void onMapLongClick(LatLng latLng) {
List<Address> addresses = new ArrayList<>();
try {
addresses = geocoder.getFromLocation(latLng.latitude, latLng.longitude, 1);
} catch (IOException e) {
e.printStackTrace();
}
String locationTitle = addresses.get(0).getAddressLine(0);
Log.d(TAG, "onMapLongClick: addresses = " + addresses.get(0));
AnimalMarker marker = new AnimalMarker(latLng.latitude, latLng.longitude, locationTitle, firebaseAuth.getCurrentUser().getUid());
markersDatabase.addMarker(marker);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(marker.getLatitude(), marker.getLongitude()), DEFAULT_ZOOM));
}
});
}
...
private void startMarkersListener() {
markersDatabase.readCurrentUserMarkers(new MarkersDatabaseListener() {
#Override
public void onCurrentUserMarkersCallBack(List<AnimalMarker> list) {
Log.d(TAG, "onCurrentUserMarkersCallBack: myMarkersList updated");
clearAllMyMarkers();
for (AnimalMarker animalMarker : list) {
Marker marker = mMap.addMarker(new MarkerOptions()
.position(new LatLng(animalMarker.getLatitude(), animalMarker.getLongitude()))
.title(animalMarker.getLocation())
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN))
.visible(myMarkersVisible));
Log.d(TAG, "onCurrentUserMarkersCallBack: created a marker at: " + marker.getTitle());
myMarkersList.add(marker);
}
}
#Override
public void onAllMarkersCallBack(List<AnimalMarker> list) {
Log.d(TAG, "onCurrentUserMarkersCallBack ----> onAllMarkersCallBack: should never reach here");
}
});
}
MarkerInfoWindowAdapter
public class MarkerInfoWindowAdapter implements GoogleMap.InfoWindowAdapter{
private final View mWindow;
private Context context;
public MarkerInfoWindowAdapter(Context context) {
this.context = context;
mWindow = LayoutInflater.from(context).inflate(R.layout.marker_info_window, null);
}
private void renderWindowText(Marker marker, View view) {
// example code to come here
String title = marker.getTitle();
TextView titleTextView = (TextView) view.findViewById(R.id.miwLocation);
if(!title.equals("")) {
titleTextView.setText(title);
}
}
#Override
public View getInfoWindow(Marker marker) {
renderWindowText(marker, mWindow);
return mWindow;
}
#Override
public View getInfoContents(Marker marker) {
renderWindowText(marker, mWindow);
return mWindow;
}
}
layout of my desired information in the custom InfoWindow:
<?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="match_parent"
android:background="#drawable/white_border"
android:orientation="horizontal"
android:padding="10dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/miwLocation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_gravity="center_horizontal"
android:layout_marginStart="150dp"
android:layout_marginTop="5dp"
android:ellipsize="end"
android:maxLines="2"
android:text="miwLocation"
android:textColor="#000000"
android:textSize="20sp"
android:textStyle="bold" />
<ImageView
android:src="#drawable/dog_icon"
android:id="#+id/miwImage"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_below="#+id/miwLocation"
android:layout_alignParentStart="true"
android:layout_marginStart="18dp"
android:layout_marginTop="10dp" />
<TextView
android:id="#+id/miwAnimalName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/miwLocation"
android:layout_marginStart="30dp"
android:layout_marginTop="12dp"
android:layout_toEndOf="#+id/miwImage"
android:layout_toRightOf="#id/miwImage"
android:ellipsize="end"
android:maxLines="2"
android:text="miwAnimalName"
android:textColor="#000000"
android:textSize="17sp" />
<TextView
android:id="#+id/miwAnimalAge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/miwAdultCB"
android:layout_marginStart="20dp"
android:layout_marginTop="10dp"
android:layout_toRightOf="#id/miwImage"
android:text="3 yrs"
android:textColor="#000000"
android:textSize="20sp" />
<CheckBox
android:id="#+id/miwAdultCB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/miwAnimalName"
android:layout_marginLeft="20dp"
android:layout_marginTop="8dp"
android:layout_toRightOf="#id/miwImage"
android:text=" Adult"
android:textSize="20dp" />
<CheckBox
android:id="#+id/miwNeuteredCB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/miwAnimalName"
android:layout_marginLeft="20dp"
android:layout_marginTop="8dp"
android:layout_toRightOf="#id/miwAdultCB"
android:text=" Neutered"
android:textSize="20dp" />
</RelativeLayout>
</LinearLayout>
Image of it:
I've found the solution after understanding the answer in this post
custom info window adapter with custom data in map v2
The easiest approach would to create an anonymous Adapter and use the global HashMap< Marker, AnimalMarker > inside it.
Something like this
getMap().setInfoWindowAdapter(new InfoWindowAdapter() {
#Override
public View getInfoWindow(Marker arg0) {
return null;
}
#Override
public View getInfoContents(Marker arg0) {
// set layout, use Marker/AnimalMarker here
}
});
Intro:
To put things into perspective, I am attempting to use fragments to create a Sudoku game.
The Sudoku board consists of 9 sub-grids, each containing 9 cells, so 9 cells in one grid, and 9 of these grids form the Sudoku board, arranged in a 3x3 fashion.
Method:
Home screen containing some information, of which a GridLayout contains 9 Framelayouts where each Sudoku Fragment will be placed into
The 9 Sudoku Fragments will make up the Sudoku board.
sudoku_cell extends a LinearLayout with an onClickListener, since extending a TextView, I was unable to inflate the sudoku_cell layout (Is it possible to do so?)
In my main activity, I have a GridLayout containing 9 FrameLayouts. These layouts have column and row locations set to form a 3x3 matrix, this is where each of the fragments will be added into.
These FrameLayouts are named on a 0-based index: frame00, frame01, frame02, frame10, etc
Documentation says:
As mentioned here on developer.android.com, I am required to have an:
Inflator method for the fragment, i.e. onCreateView() which inflates the fragment
A Layout container of sorts to root/place the fragment in, in the main activity (in my case)
A FragmentManager and FragmentTransactionManager to handle the fragments, adding and commiting them.
Problem:
TL;DR: Simply, my fragments are not showing.
After calling the commit(), I expect to see a 3x3 board of sudoku_grid fragments, each containing 9 sudoku_cells. However, this does not get shown
I have searched SO, reread the documentation, and searched more but cannot understand why it is not showing.
I have tried:
When inflating my fragment, I inflate a sudoku_cell layout instead, this does infact show a 9 cell grid.
However each cell should be a grid containing 9 cells, this leads me to believe that there may be an issue on the Sudoku_Grid - Sudoku_Cell side, possibly the sudoku_cell layout is not being inflated correctly or being rooted correctly.
Usually an LayoutInflator, and ViewGroup is passed allowing one to inflate a layout, but in the case of the sudoku_cell, I cannot find such a method to override, is this the cause?
The code:
sudoku_cell.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/cellText"
android:layout_width="35dp"
android:layout_margin="1px"
android:textSize="18dp"
android:layout_height="35dp"
android:textAlignment="center"
android:textColor="#color/clBlack">
</TextView>
</LinearLayout>
SudokuCell.java
public class SudokuCell extends LinearLayout{
private LinearLayout layout;
private TextView textView;
private Context mContext;
private Point location;
private int index;
public SudokuCell(Context context) {
super(context);
}
public SudokuCell(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layout = (LinearLayout) inflater.inflate(R.layout.sudoku_cell, this, true);
textView = layout.findViewById(R.id.cellText);
setText("");
}
public void setStaticText(String s){
if (textView != null) {
textView.setText(s);
textView.setTypeface(textView.getTypeface(), Typeface.BOLD);
}
}
public void setText(String s){
if (textView != null)
textView.setText(s);
}
public Point getLocation() {
return location;
}
public void setLocation(Point location) {
this.location = location;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
9 of these sudoku_cell's get added to a sudoku_grid as shown below in the onCreateView() and populateGrid() methods:
sudoku_grid.xml
<?xml version="1.0" encoding="utf-8"?>
<GridLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="2px"
android:id="#+id/grid_layout"
android:columnCount="3"
android:rowCount="3">
</GridLayout>
SudokuGrid.java
public class SudokuGrid extends Fragment{
private GridLayout gridLayout;
private List<GridFragmentListener> listeners = new ArrayList<>();
private Context mActitityContext;
private boolean FRAGMENT_LOCATION_CENTRE;
private float SCREEN_DP;
private int GRID_MARGINS_DP = 1;
private int colorOdd, colorEven;
private List<Integer> presetGrid;
private View previousView;
private Drawable previousViewDrawable;
public void addGridListener(GridFragmentListener gridFragmentListener) {
listeners.add(gridFragmentListener);
}
public void removeGridListener(GridFragmentListener gridFragmentListener) {
listeners.remove(gridFragmentListener);
}
protected void notifyValueChanged(View value) {
for (GridFragmentListener listener : listeners) listener.onValueChange(value);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mActitityContext = getActivity();
View v = inflater.inflate(R.layout.sudoku_grid, container, false);
//set grid view
gridLayout = v.findViewById(R.id.grid_layout);
populateGrid();
return v;
}
private void populateGrid() {
for (int i = 0; i < 9; i++) {
SudokuCell sudokuCell = new SudokuCell(mActitityContext);
sudokuCell.setBackgroundColor(((i % 2) == 0) ? R.color.clOdd : R.color.clEven);
System.out.printf("Sudoku Cell ID [ index = " + String.valueOf(i) + " ] - getId() = " + sudokuCell.getId());
sudokuCell.setLocation(getPoint(i));
sudokuCell.setIndex(i);
sudokuCell.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
notifyValueChanged(view);
}
});
sudokuCell.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
SudokuCell cell = (SudokuCell) view;
if (b)
view.setBackgroundColor(ContextCompat.getColor(mActitityContext, R.color.clSelected));
else
view.setBackgroundColor(ContextCompat.getColor(mActitityContext, (cell.getIndex() % 2 == 0) ? R.color.clOdd : R.color.clEven));
}
});
sudokuCell.setStaticText(String.valueOf(i));
gridLayout.addView(sudokuCell, i);
}
}
private Point getPoint(int i) {
int y = 0;
while (i > 2){
y++;
i -= 3;
}
return new Point(i, y);
}
#Override
public void onStart() {
super.onStart();
try {
addGridListener((GridFragmentListener) getActivity());
} catch (ClassCastException e) {
throw new ClassCastException(
getActivity().getClass().toString()
+ " does not implement the DetailsFragment.DetailsFragmentListener interface.");
}
}
#Override
public void onStop() {
super.onStop();
removeGridListener((GridFragmentListener) getActivity());
}
}
In my main activity, I handle the creation of 9 sudoku_grid fragments which are placed into each respective FrameLayout, to form a 3x3 matrix of Sudoku_Grids, which will form the Sudoku board
activity_main_sudoku.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="wrap302.nmu.task1.MainActivitySudoku"
android:background="#color/clDarkGrey">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="#+id/linearLayout2">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/textView"
android:text="#string/app_title"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:textColor="#color/clWhite"
android:textAppearance="#style/TextAppearance.AppCompat.Display1"
android:textAlignment="center"
android:textStyle="bold"
android:fontFamily="sans-serif"/>
<TextView
android:text="#string/lblScore"
android:textColor="#color/clWhite"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="#+id/lblScore"
android:textAppearance="#style/TextAppearance.AppCompat.Button" android:textAlignment="center"
android:layout_marginBottom="5dp"/>
</LinearLayout>
<GridLayout
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnCount="3"
android:rowCount="3"
android:id="#+id/main_sudokugrid_container">
<FrameLayout
android:layout_column="0"
android:layout_row="0"
android:layout_width="wrap_content"
android:background="#color/clWhite"
android:layout_height="wrap_content" android:id="#+id/frame00"/>
<FrameLayout
android:layout_column="1"
android:layout_row="0"
android:layout_width="wrap_content"
android:background="#color/clWhite"
android:layout_height="wrap_content" android:id="#+id/frame01"/>
<FrameLayout
android:layout_column="2"
android:layout_row="0"
android:layout_width="wrap_content"
android:background="#color/clWhite"
android:layout_height="wrap_content" android:id="#+id/frame02"/>
<FrameLayout
android:layout_column="0"
android:layout_row="1"
android:layout_width="wrap_content"
android:background="#color/clWhite"
android:layout_height="wrap_content" android:id="#+id/frame10"/>
<FrameLayout
android:layout_column="1"
android:layout_row="1"
android:layout_width="wrap_content"
android:background="#color/clWhite"
android:layout_height="wrap_content" android:id="#+id/frame11"/>
<FrameLayout
android:layout_column="2"
android:layout_row="1"
android:layout_width="wrap_content"
android:background="#color/clWhite"
android:layout_height="wrap_content" android:id="#+id/frame12"/>
<FrameLayout
android:layout_column="0"
android:layout_row="2"
android:layout_width="wrap_content"
android:background="#color/clWhite"
android:layout_height="wrap_content" android:id="#+id/frame20"/>
<FrameLayout
android:layout_column="1"
android:layout_row="2"
android:layout_width="wrap_content"
android:background="#color/clWhite"
android:layout_height="wrap_content" android:id="#+id/frame21"/>
<FrameLayout
android:layout_column="2"
android:layout_row="2"
android:layout_width="wrap_content"
android:background="#color/clWhite"
android:layout_height="wrap_content" android:id="#+id/frame22"/>
</GridLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:gravity="center" android:id="#+id/linearLayout">
<GridLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingTop="0dp">
<Button
android:layout_row="0"
android:layout_column="0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn1"
android:text="1"/>
<Button
android:layout_row="0"
android:layout_column="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn2"
android:text="2"/>
<Button
android:layout_row="0"
android:layout_column="2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn3"
android:text="3"/>
<Button
android:layout_row="1"
android:layout_column="0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn4"
android:text="4"/>
<Button
android:layout_row="1"
android:layout_column="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn5"
android:text="5"/>
<Button
android:layout_row="1"
android:layout_column="2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn6"
android:text="6"/>
<Button
android:layout_row="2"
android:layout_column="0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn7"
android:text="7"/>
<Button
android:layout_row="2"
android:layout_column="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn8"
android:text="8"/>
<Button
android:layout_row="2"
android:layout_column="2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn9"
android:text="9"/>
<Button
android:layout_row="0"
android:layout_column="3"
android:layout_rowSpan="3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="fill_vertical"
android:id="#+id/btnClear"
android:text="Clear"/>
</GridLayout>
</LinearLayout>
</RelativeLayout>
MainActivitySudoku.java
public class MainActivitySudoku extends AppCompatActivity implements GridFragmentListener {
private FragmentManager fragmentManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_sudoku);
createSudokuGrid();
}
private void createSudokuGrid() {
fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransactionManager = fragmentManager.beginTransaction();
fragmentTransactionManager.add(R.id.frame00, new SudokuGrid());
fragmentTransactionManager.add(R.id.frame01, new SudokuGrid());
fragmentTransactionManager.add(R.id.frame02, new SudokuGrid());
fragmentTransactionManager.add(R.id.frame10, new SudokuGrid());
fragmentTransactionManager.add(R.id.frame11, new SudokuGrid());
fragmentTransactionManager.add(R.id.frame12, new SudokuGrid());
fragmentTransactionManager.add(R.id.frame20, new SudokuGrid());
fragmentTransactionManager.add(R.id.frame21, new SudokuGrid());
fragmentTransactionManager.add(R.id.frame22, new SudokuGrid());
fragmentTransactionManager.commit();
}
#Override
protected void onStart() {
super.onStart();
Toast.makeText(this, "Activity Started & Viewable", Toast.LENGTH_SHORT).show();
}
// GridFragmentListener
#Override
public void onValueChange(View view) {
//todo something here with received view
}
}
Well, the solution proved simpler than expected.
In short, the solution was to move the SudokuCell constructor code from the
SudokuCell(Context context, AttributeSet attrs)
to the
SudokuCell(Context context)
since that was the constructor I was calling.
A few other changes can be made for improvement, this solves the fragments not being displayed.
Quite a simple error
Ok - I have given you a sample of how to add your fragments so they will display. If you go through this and emulate the process this will assist you. I've used basic examples in the layout so we can have ids to use in the classes.
You'll also need to manage the app lifecycle and the back press button on how you want to manage your stack with your fragments and maintaining any data.
Activity
public class MyActivity extends Activity {
Fragment fragment;
FrameLayout frameLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_myactivity);
View view = this.findViewById(android.R.id.content);
frameLayout = (FrameLayout) findViewById(R.id.frag);
fragment = new MyFragment();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.frag, fragment);
fragmentTransaction.commit();
}
}
Layout for Activity
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
.../...>
.../...
<FrameLayout
android:id="#+id/frag"
// sort out your layout here with the frameLayouts
android:layout_below="#+id/your_id"
/>
.../...
</RelativeLayout>
Fragment
public class MyFragmentextends Fragment {
FragmentManager fragmentManager;
Fragment fragment;
public static MyFragmentnewInstance(String item {
fragment =
new MyFragment();
// pass data from activity
Bundle args = new Bundle();
args.putString(ITEM, item);
fragment.setArguments(args);
return fragment;
}
public DeliveryDisplayFromDispenserFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
item = getArguments().getString(ITEM);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view =
inflater.inflate(R.layout.myfragment, container, false);
}
}
Layout for Fragment
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
.../...>
// fragment layout
</RelativeLayout>
I need to do app like slideshow of images and vidoes from fiels from the device.
I have tried several projects - but no one can display videos.
What is the best way to do ot. All I need is to display, repeatedly, images and videos from the devices without the UI will stuck
There are some of the projects that i tried:
https://github.com/daimajia/AndroidImageSlider
https://github.com/marvinlabs/android-slideshow-widget
Thank you
I am showing a list of videos:
The Activity code:
public class VideoListActivity extends AppCompatActivity {
private ListView lvVideos;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_list);
lvVideos = (ListView)findViewById(R.id.lvVideos);
lvVideos.setAdapter(new VideosListAdapter(this));
}
}
The adapter code:
public class VideosListAdapter extends BaseAdapter {
private static LayoutInflater inflater = null;
private ArrayList<VideoData> listVideoData = new ArrayList<>();
private String[] creationDates = new String[0];
public VideosListAdapter(VideoListActivity videoListActivity) {
inflater = (LayoutInflater) videoListActivity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// here is a listVideoData and the creationDates initialisation code.
}
#Override
public int getCount() {
return listVideoData.size();
}
#Override
public Object getItem(int position) {
return listVideoData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
if (vi == null) {
vi = inflater.inflate(R.layout.row_video, null);
}
VideoData videoData = listVideoData.get(position);
VideoView videoView = (VideoView)vi.findViewById(R.id.videoView);
videoView.setVideoPath(videoData.getVideoFilePath());
TextView tvDate = (TextView) vi.findViewById(R.id.tvDate);
tvDate.setText(creationDates[position]);
TextView tvInfo = (TextView) vi.findViewById(R.id.tvPuppetInfo);
tvInfo.setText("Whatever you want" );
// must add this: -otherwise I don't know why, but is not working the click
RelativeLayout relativeLayout = (RelativeLayout)videoView.getParent();
relativeLayout.setClickable(true);
relativeLayout.setOnClickListener(rlClickListener);
return vi;
}
View.OnClickListener rlClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
VideoView videoView = (VideoView)v.findViewById(R.id.videoView);
videoView.start();
}
};
}
A code part in the row_video.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:orientation="vertical">
<!-- Yes, it is in pixel, hardcoded, because this is what is requested -->
<VideoView
android:id="#+id/videoView"
android:layout_width="1280px"
android:layout_height="720px"
android:layout_centerHorizontal="true" />
<TextView
android:id="#+id/tvDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/videoView"
android:layout_below="#+id/videoView"
android:layout_marginTop="5dp"
android:focusable="false"
android:text="25/12/2016 12:59:59"
android:textAppearance="?android:attr/textAppearanceLarge"
/>
<TextView
android:id="#+id/tvStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="#+id/videoView"
android:layout_below="#+id/videoView"
android:layout_marginTop="5dp"
android:drawableRight="#drawable/red_check"
android:text="whatever you want"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textStyle="bold" />
<TextView
android:id="#+id/tvInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/videoView"
android:layout_centerHorizontal="true"
android:layout_marginTop="1dp"
android:gravity="center"
android:layout_toLeftOf="#+id/tvStatus"
android:layout_toRightOf="#+id/tvDate"
android:focusable="false"
android:text=""
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
I hope it worth an upvote ! ( click )
I'm finding it hard to search for what I'm looking for so I thought I'd try and explain it here. I currently have a Custom ListView within a ScrollView. Each ListView item contains the Branch details for a shop, i.e. street address, city, phone. I've used the setListViewHeightBasedOnChildren function shown below to get around the "scrolling a ListView in a ScrollView" problem by expanding the ListView to it's full height.
What I would like to do now is, if a shop has greater than 2 branches, show 2 of the branches and then have a button at the bottom of the list view that says "Show More". If possible the button would sit on top of the list, partially showing the third branch to give it a transparent gradient effect something similar to this. Clicking on the button would ideally animate the ListView as it opens downward. I understand this is a big ask but I would just like to know if it is possible and a point in the right direction. I can work on a custom solution myself once I have an idea where to start.
My ListView implementation and Layout files can be seen below:
BranchListAdapter.java
public class BranchListAdapter extends ArrayAdapter<HashMap<String, String>> {
private Context mContext;
private LayoutInflater mLayoutInflater;
public BranchListAdapter(Context context) {
super(context, android.R.layout.simple_list_item_1);
mContext = context;
mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final View view;
if(convertView == null) {
view = mLayoutInflater.inflate(R.layout.fragment_shop_details_branch_list_item, parent, false);
} else {
view = convertView;
}
final HashMap<String, String> branch = getItem(position);
TextView address = (TextView) view.findViewById(R.id.branch_list_item_address);
TextView city = (TextView) view.findViewById(R.id.branch_list_item_city);
TextView phone = (TextView) view.findViewById(R.id.branch_list_item_phone);
address.setText(branch.get("address"));
city.setText(branch.get("city"));
phone.setText(branch.get("phone"));
return view;
}
public void setData(List<HashMap<String, String>> branches) {
clear();
if(branches != null) {
for(HashMap<String, String> branch : branches) {
if(!branch.get("address").equals(""))
add(branch);
}
}
}
}
fragment_shop_details_branch_list_adapter.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.GridLayout
android:id="#+id/branch_list_item_grid"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:grid="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
grid:columnCount="2"
grid:orientation="vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="8dp"
xmlns:tools="http://schemas.android.com/tools">
<TextView
android:text="Address"
android:textColor="#000000"
android:textSize="16sp"
grid:layout_column="0"
grid:layout_gravity="center_vertical"
grid:layout_row="0"
/>
<TextView
android:id="#+id/branch_list_item_address"
android:layout_width="0dp"
android:gravity="center"
android:maxLines="2"
tools:text="31 Fitzwilliam Manor, The Island"
android:textColor="#000000"
android:textSize="16sp"
grid:layout_column="1"
grid:layout_gravity="fill_horizontal"
grid:layout_row="0"
/>
<TextView
android:text="City"
android:textColor="#000000"
android:textSize="16sp"
grid:layout_column="0"
grid:layout_gravity="center_vertical"
grid:layout_row="1"
/>
<TextView
android:id="#+id/branch_list_item_city"
android:layout_width="0dp"
android:gravity="center"
android:maxLines="2"
tools:text="Dublin"
android:textColor="#000000"
android:textSize="16sp"
grid:layout_column="1"
grid:layout_gravity="fill_horizontal"
grid:layout_row="1"
/>
<TextView
android:text="Phone"
android:textColor="#000000"
android:textSize="16sp"
grid:layout_column="0"
grid:layout_gravity="center_vertical"
/>
<TextView
android:id="#+id/branch_list_item_phone"
android:layout_width="0dp"
android:gravity="center"
android:maxLines="2"
tools:text="01 456 7890"
android:textColor="#000000"
android:textSize="16sp"
grid:layout_column="1"
grid:layout_gravity="fill_horizontal"
grid:layout_row="2"
/>
<Button
android:id="#+id/branch_list_item_button_showmap"
style="?android:attr/borderlessButtonStyle"
android:text="#string/show_on_map"
android:textColor="#0645AD"
android:textSize="14sp"
grid:layout_column="0"
grid:layout_columnSpan="2"
grid:layout_columnWeight="1"
grid:layout_gravity="center"
grid:layout_row="4"/>
</android.support.v7.widget.GridLayout>
Expand List View to Full Height function
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
if (listItem instanceof ViewGroup) {
listItem.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
And finally this is how the ListView is implemented in the Fragment:
mBranchListAdapter = new BranchListAdapter(getActivity());
mBranchListAdapter.setData(mShop.getBranchDetails());
mBranchListView.setAdapter(mBranchListAdapter);
MiscUtils.setListViewHeightBasedOnChildren(mBranchListView);
I am working on an Android project in which I am currently working on chat functionality. Now, whenever an user sends a message, it is added in the ListView, which is populated by BaseAdapter. A new message is added by baseAdapterObject.add(item);.
Now, whenever an user sends a message, I am adding it directly to the already existing List and then waiting for a reply from the server confirming the message was delivered. For the first step, I would like to show a Gray checkmark, and for 2nd message received from server, I would like to show Blue checkmark.
Unfortunately, I don't know how to access the already populated list and change the background image of an ImageView. . Each message has a random-number, with which I can compare for which message I received confirmation.
Code :
public void recieveUpdatedMessageFromServer(String channelName, Map<String, Object> input){
String randomNumberFromServer = ((Map) input.get("data")).get("random").toString();
if (randomNumberFromServer.equals(randomNos)) {
messageRecieved = true;
randomNos = "";
}
chatMessagesAdapter.add(insertMap);
runOnUiThread(new Runnable() {
#Override
public void run() {
chatMessagesAdapter.notifyDataSetChanged();
}
});
public class ChatMessagesAdapter extends BaseAdapter {
private Activity activity = null;
private ArrayList<HashMap<String, String>> data;
private LayoutInflater inflater = null;
public ChatMessagesAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
data = d;
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void add(HashMap<String, String> item) {
data.add(item);
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
if (convertView == null)
vi = inflater.inflate(R.layout.chat_messages_row, parent, false);
TextView chatText = (TextView) vi.findViewById(R.id.chatText);
ImageView userImage = (ImageView) vi.findViewById(R.id.chatImage);
TextView firstName = (TextView) vi.findViewById(R.id.personName);
ImageView checkMark = (ImageView) vi.findViewById(R.id.checMarkChat);
HashMap<String, String> chatList;
chatList = data.get(position);
chatText.setText(chatList.get(ChatMessagesActivity.chatText));
checkMark.setBackgroundResource(R.drawable.blue_icon);
firstName.setText(chatList.get(ChatMessagesActivity.firstName));
if (!(chatList.get(ChatMessagesActivity.chatImageId).equals("0"))) {
Picasso.with(context).load(StaticRestTemplate.baseURL + "image/" + chatList.get(ChatMessagesActivity.chatImageId)).fit().into(userImage);
}
return vi;
}
}
}
chat_messages_row.xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="130dp"
android:orientation="horizontal"
android:padding="2.5dip">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="125dp"
android:id="#+id/frameLayout2">
<ImageView
android:id="#+id/chatImage"
android:layout_width="107dp"
android:layout_height="107dp"
android:padding="2dp" />
</FrameLayout>
<TextView
android:id="#+id/chatText"
android:layout_width="230dp"
android:layout_height="76dp"
android:layout_gravity="right|center_vertical"
android:layout_alignParentBottom="true"
android:layout_toRightOf="#+id/frameLayout2"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:id="#+id/personName"
android:layout_alignParentTop="true"
android:layout_alignRight="#+id/chatText"
android:layout_alignEnd="#+id/chatText"
android:layout_toRightOf="#+id/textView"
android:layout_toEndOf="#+id/textView"
/>
<ImageView
style="?android:attr/buttonStyleSmall"
android:layout_width="40dp"
android:layout_height="40dp"
android:id="#+id/checMarkChat"
android:background="#drawable/blue_icon"
android:layout_alignParentBottom="true"
android:layout_alignRight="#+id/personName"
android:layout_alignEnd="#+id/personName" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Small Text"
android:id="#+id/textView"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginLeft="49dp"
android:layout_marginStart="49dp"
android:layout_marginTop="208dp" />
</RelativeLayout>
I hope this much information is enuf. Kindly let me know if anything else required. Thank you. :-)
Consider using a class object to help.
For example, you can create a list of message objects:
class Message {
private String message;
private boolean gray_tick;
private boolean blue_tick;
....
}
Change your hashmap in your BaseAdapter to take in the corresponding object.
private ArrayList<HashMap<String, Message>> data;
From there, you can set your BaseAdapter to read these values and show the correct coloured ticks at the right time.
Hope this helps!