i have the following problem, I am writing an app that repeats the http://www.rottentomatoes.com/mobile/ website, if you look on the site there are deviders the "Opening this Week", "Top Box Office" and "Also in Theaters" so my question is, how do i add this custom rows to the ListView that holds all the movies
here is what i have so far, please pitch me some ideas so it will look exactly like on the site
The easiest way to achieve this would be to include the dividers in the layout of item views. Then make them VISIBLE only when the view maps to the first item of a new category, otherwise leave them as GONE.
Example (in semi-pseudocode):
First, make your item layout like this:
<LinearLayout orientation=vertical>
<TextView id=divider>
<your original item layout>
</LinearLayhout>
Then, in the adapter's getView():
Film item = getItem(position);
boolean needsDivider = (position == 0 || getItem(position - 1).filmCategory != film.filmCategory);
if (needsDivider)
{
dividerView.setVisibility(View.VISIBLE);
dividerView.setText(getFilmCategoryName(film.filmCategory));
}
else
dividerView.setVisibility(View.GONE);
A more fancy solution would be to use a library like StickyListHeaders. It doesn't work as your mobile site example, but it's probably even better (e.g. the headers don't scroll up out of the screen).
Related
I am trying to create a small application where I have various file locations stored in a Vaadin grid, the grid currently only shows two columns - ID and File Name, and I would like to see as a notification the file location too whenever I click on a row.
Meaning, every time I click a row from the grid I would like it to show me the location, using Notification.show(), like that:
(Please ignore the <b></b>s, they are irrelevant.)
As my grids selection model is MULTI, per default the click listener cannot register which row it is clicked on and selecting the row via checkbox is not what I want to have the data displayed. Simply, I would like to get the item for every row I click and have the location displayed as a notification.
So far, I found a solution for a similar issue but it deals with columns and the rows in Vaadin grids are rather different from what I am used to.
public static <T> void addColumnClickListener(Grid<T> grid, Consumer<Column<T>> listener)
{
String expression = "function(){const col=element.getEventContext(event).column;return col ? col.id : '';}()";
grid.getElement().addEventListener("click", e ->
{
String colId = e.getEventData().getString(expression);
Optional<Column<T>> column = grid.getColumns().stream().filter(col -> colId.equals(col.getId().get())).findFirst();
column.ifPresent(listener);
}
).addEventData(expression);
}
And I am to call the function like that:
addColumnClickListener(grid, column -> Notification.show("fubar"));
This code snippet is from the Vaadin forums and I do not quite understand it. The string expression seems to be that it contains possible JavaScript code and the rest overrides the type of the column. (I think, I really do not understand this snippet fully)
Is there any way to do something similar to the snippet above but for rows?
You can do this with an ItemClickListener on the Grid:
grid.addItemClickListener(item -> {
Notification.show(String.format("File location: %s", item.getLocation()));
});
I've made a chipgroup and I want to dynamically generate in java its content, populating it with filter chips made from strings. I've made the Chipgroup but trying to add chips I notice that, no matter what I do, the chips are not responding to clicks. I also tried to make a single chip in the design editor and moving it in the same chipgroup, the results is that the design editor created chip is working as intended (checking and unchecking it), the generated ones are static (in the same group).
the code I use for the single working one:
<com.google.android.material.chip.ChipGroup
android:id="#+id/iChipGroup"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:chipSpacing="8dp"
app:singleSelection="true" >
<com.google.android.material.chip.Chip
android:id="#+id/chip2"
style="#style/Widget.MaterialComponents.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="cwae" />
</com.google.android.material.chip.ChipGroup>
the way I create the dynamic ones
Chip chip = new Chip(iChipGroup.getContext());
ChipDrawable chipDrawable = ChipDrawable.createFromAttributes(getContext(), null, 0, R.style.Widget_MaterialComponents_Chip_Filter);
chip.setChipDrawable(chipDrawable);
chip.setText(myText);
iChipGroup.addView(chip);
I've also tried to set an OnCheckedhangeListener both on the single chips and ChipGroup, got nothing.
If it helps, my hierarchy is (inside a fragment):
frameLayout
-scrollView
--LinearLayout
---chipGroup
----chip...
managed to make the chip respond by changing the way I made them this way
LayoutInflater layoutInflater = getLayoutInflater();
Chip chip = (Chip)layoutInflater.inflate(R.layout.my_filter_chip,ingredientsChipGroup, false);
I am making an app similar to facebook where i have a news feed which shows all the posts. However, the number of post in this feed varies with each user, depending on the amount of friends they have and how many posts they have made. I want to create a CardView for every post item which will show the name of the user who posted it, the time it was posted and the actual post itself. The layout will be split horizontally once with the post in the bottom half and the name of the person with the time it was posted on the top half.
Currently i can only find ways to do this by altering the xml text, but i want to create these CardViews as and when i need them, in my Java code.
I know i can alter TextViews by using such functions as setText() & setTextSize(). Is there a way for me to use similar functions on a CardView which can alter the base layout.
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
CardView TVcard = new CardView(Home.this);
TextView TVposts = new TextView(Home.this);
TextView test = new TextView(Home.this);
TVcard.addView(TVposts);
TVcard.addView(test);
test.setText("test");
test.setBackgroundColor(Color.GREEN);
TVposts.setText(snapshot.getValue().toString());
TVposts.setTextColor(Color.WHITE);
TVposts.setTextSize(25);
TVposts.setBackgroundColor(Color.BLACK);
TVposts.setHeight(200);
linearLayout.addView(TVcard);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) TVcard.getLayoutParams();
params.setMargins(0, 20, 0, 0);
TVcard.setLayoutParams(params);
}
Thanks
I would like to create a view with a listener that acts sort of like a container or grocery bag. Any image or text that is dragged into it, gets collected and saved into a local database. Or rather the image name or string gets saved. I've created custom views before that displayed a custom row of data but I'm not sure how to create a "grocery bag" type of view. I've searched Google for creating a custom container view with listener but couldn't find anything related to what I am looking for. I'm not asking anyone to do it for me, just give me some advice or push in the right direction.
Edit
Just to clarify a little more. I already know how to drag and drop a view. The problem with that is that you can drop anywhere. What I want is a view that when something is dropped within its bounds, it gets the views' string or tag. Regardless of what kind of view that may be. Somehow this custom view has to know what kind of view was dropped within its bounds and remove that view on drop.
<view class="at.calista.quatscha.views.SwipebarLayout"
android:id="#+id/sbl"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<!-- Top View -->
<Button android:text="Top" android:id="#+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
<!-- Bottom View -->
<Button android:text="Bottom" android:id="#+id/Button02" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
You would need a method that determines whether two views overlap. For example, something like these methods could work for when the target view and the dragged item view are 2 distinct views in the same container view:
private Rect getScreenBounds(View view)
{
int[] location = new int[2];
view.getLocationOnScreen(location);
return new Rect(location[0], location[1], location[0] + view.getWidth(), location[1] + view.getHeight());
}
private boolean doViewsIntersect(View dropTarget, View item)
{
Rect dropRect = getScreenBounds(dropTarget);
Rect itemRect = getScreenBounds(item);
return Rect.intersects(dropRect, itemRect);
}
However, if the views being dragged are child views on a container, and that container has a special hit area where you want to perform the drop logic, then you can just use that hit area's Rect for the intersect test.
To save information on the View, you have a few options:
You can use view.setTag(key, object) and view.getTag(key) to store whatever information you'd like on each item.
If you are using a custom class for the items, you can just add a method to get the data from the view class.
If you are using multiple different classes for the items, you could make an interface, and implement that interface on each draggable view class.
On an item's release, you could then check whether the areas/views intersect, and if they do, get whatever information you need from the dragged item to process as necessary, either using getTag or the method added to the view.
For example, this could be triggered via an onTouchListener, when you receive a MotionEvent.ACTION_UP event. Here's an example of a listener that you can add on each item:
item.setOnTouchListener(new View.OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
if (event.getActionMasked() == MotionEvent.ACTION_UP)
{
if (doViewsIntesect(dropTarget, v))
{
Object data = v.getTag(DATA_KEY);
//process data
((ViewGroup) v.getParent()).removeView(v); // to remove the item afterwards
}
}
return false;
}
});
I have a basically all in one layout which has everything needed for my app's main feed. All variable items (images, video thumbnails.. Etc.) are set to GONE at first and set to VISIBLE when it is needed.
The problem is sometimes, might be due to RecyclerView's recycling behavior, the item which is supposedto be GONE is VISIBLE in the wrong places.
Example :
Item no 1 contains Text
Item no 2 contains Image
Item no 3 contains Image
I keep scrolling down to item no x, then scroll back up and here's what I get :
Item no 1 contains Image from item no x, sometimes item no 3
Item no 2 contains Image
Item no 3 contains Image
I'm using a custom ViewHolder which extends RecyclerView.ViewHolder.
The purpose of the CustomViewHolder is for layout declaration and initialization.
ProgressBar progressBar;
View viewDimmer;
RelativeLayout postListWrapper;
...
public ObjectViewHolder(View v) {
super(v);
progressBar = (ProgressBar)v.findViewById(R.id.post_inscroll_progressBar);
viewDimmer = (View)v.findViewById(R.id.post_inscroll_viewDimmer);
postListWrapper = (RelativeLayout)v.findViewById(R.id.post_inscroll_postListWrapper);
}
An example of how I load the image :
Picasso.with(context)
.load(youtubeThumbnailUrl)
.fit()
.centerCrop()
.into(
((ObjectViewHolder) holder).userPostYoutubeImage
);
I've set each visibility to GONE if no url is obtained from the server
((ObjectViewHolder) holder).userPostImageWrapper.setVisibility(View.GONE);
((ObjectViewHolder) holder).userPostYoutubeImageWrapper.setVisibility(View.GONE);
But somehow the image is still reused on the previous items (yes, not only Item no 1). Sometimes image are also in the wrong ImageView. Image D is supposed to be in ImageView D, but it's in ImageView A instead.
Any guide for setting RecyclerView up and going nicely?
If I miss anything, or need to supply more code, please do inform me :D
You need to put the else condition too. Like the example below.
// if no url is found from server
if(url == null){
((ObjectViewHolder) holder).userPostImageWrapper.setVisibility(View.GONE);
((ObjectViewHolder) holder).userPostYoutubeImageWrapper.setVisibility(View.GONE);
} else {
// Some url has found
((ObjectViewHolder) holder).userPostImageWrapper.setVisibility(View.VISIBLE);
((ObjectViewHolder) holder).userPostYoutubeImageWrapper.setVisibility(View.VISIBLE);
}
Do this for each of the items you've got there as the list item in case of you're setting their visibilities in runtime.
All your if conditions in onBindViewHolder() must have an else block too.
Don't leave any if condition without else. You can provide a default behaviour in the else block when if condition becomes false.