问题
I am trying to create the CardView ScrollBar UI like Google Play.
I was following this tutorial but stuck at the models classes and can't move further.
My Json is like this:
{
"Cards": {
"Recently Updated": [
{
"Name": "A",
"img": "a.png",
"link": "alink.com"
},
{
"Name": "B",
"img": "b.png",
"link": "blink.com"
},
{
"Name": "C",
"img": "c.png",
"link": "clink.com"
}
],
"Newly Arrives": [
{
"Name": "A",
"img": "a.png",
"link": "alink.com"
},
{
"Name": "L",
"img": "L.png",
"link": "Llink.com"
},
{
"Name": "z",
"img": "z.png",
"link": "zlink.com"
}
]
}
}
Please help to create the same.
I want to achive like this :
How can i add cardview scrollbar like above image
回答1:
To create a model you need to follow the tree the JSON is showing you. Look at the picture from the outside rectangles to the inside rectangles.
First of all, you have all the JSON content as a block.
This is going to be my first model class
MainCard.java
public class MainCard {
@SerializedName("Cards")
public Cards cards;
}
Notice that my MainCard (my first and biggest rectangle) contains inside the Cards rectangle. That is why it has the public variable Cards.
Second, let's move to the second rectangle. (Cards)
Cards.java
public class Cards {
@SerializedName("Recently Updated")
public List<Item> recentlyUpdates;
@SerializedName("Newly Arrives")
public List<Item> newlyArrives;
}
The Cards rectangle has two rectangles inside it, Recently Updated and Newly Arrives, that is why I created this two variables.
Finally, notice that the rectangle inside Recently Updated and the rectangles inside Newly Arrives is a List of something (which I called Item - [name, img, link]). That's why I created the recentlyUpdated variable as a List.
Item.java
public class Item {
@SerializedName("Name")
public String name;
@SerializedName("img")
public String img_url;
public String link;
}
NOTES
@SerializedName should contain the exact same name your JSON provides, for example, in Cards.java, my variable name is recentlyUpdates and my @SerializedName("") is Recently Updated (which is the exact same name we have in the JSON response). However, if your variable name is the same as your JSON, you do not need to put @SerializedName, this happens in Item.java in the link variable.
Retrofit
If you JSON is on an online server, you should use some library to call this content. I would recommend you to use retrofit 2 by square.
Add the dependencies to your build.gradle (Module:app) file under the dependencies section.
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0-rc02'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
// Retrofit 2
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
}
Then you should create a service that will call your JSON object.
CardsService.java (Note: this is an interface)
public interface CardsService {
String BASE_URL = "http://yourbaseurl.api/";
@GET("endpoint")
Call<MainCard> getCards();
}
And in your MainActivity you call the service to get the JSON data.
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(CardsService.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
CardsService service = retrofit.create(CardsService.class);
Call<MainCard> call = service.getCards();
call.enqueue(new Callback<MainCard>() {
@Override
public void onResponse(Call<MainCard> call, Response<MainCard> response) {
if (response.isSuccessful()) {
// Got a successful response (Code 200...300)
MainCard mainCard = response.body();
if (mainCard != null && mainCard.cards != null) {
List<Item> recentlyUpdates = mainCard.cards.recentlyUpdates;
List<Item> newlyArrives = mainCard.cards.newlyArrives;
// Use your information to set up the recyclerview as the tutorial you
// showed describe.
setupRecyclerView(recentlyUpdates, newlyArrives);
}
} else {
// Got a unsucessful response (Code 401, 405, 409...)
}
}
@Override
public void onFailure(Call<MainCard> call, Throwable t) {
// Failed to connect to the server
// Possible causes: No internet connection, Server is broken.
}
});
}
}
If you are not family with retrofit you should read some tutorials on medium, as this one, and you can also check this project to learn more about the topic.
EDIT
HOW TO SETUP THE ITEMS IN A RECYCLER VIEW?
After you get a successful response you can call the setupRecyclerView(List<Item> items)
method to display your items in a recycler view. I'll do it using only the recentlyUpdates list, then you customize in the way you want to display both.
if (response.isSuccessful()) {
// Got a successful response (Code 200...300)
MainCard mainCard = response.body();
if (mainCard != null && mainCard.cards != null) {
List<Item> recentlyUpdates = mainCard.cards.recentlyUpdates;
List<Item> newlyArrives = mainCard.cards.newlyArrives;
// ***** Use your information to set up the recyclerview. *****
// I am going to set up only the recentlyUpdates list.
setupRecyclerView(recentlyUpdates);
}
}
Create a RecyclerView in your xml file
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</android.support.constraint.ConstraintLayout>
MainActivity.java
Back in your activity, cast the recycler view, add the layout manager and the adapter.
private void setupRecyclerView(List<Item> itemsList) {
RecyclerView mRecyclerView = findViewById(R.id.recycler_view);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(linearLayoutManager);
mRecyclerView.setAdapter(new MyCardsAdapter(itemsList, this));
}
MyCardsAdapter.java
public class MyCardsAdapter extends RecyclerView.Adapter<MyCardsAdapter.ItemHolder> {
private List<Item> itemsList;
private Context context;
public MyReposAdapter(List<Item> itemsList, Context context) {
this.itemsList = itemsList;
this.context = context;
}
@NonNull
@Override
public ItemHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_item, parent, false);
return new ItemHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ItemHolder holder, int position) {
// Get each item.
Item singleItem = itemsList.get(position);
// singleItem is each Item.java you created. And holder contains the widgets you created in single_item.xml to display the items information.
holder.textViewName.setText(singleItem.name);
holder.textViewImage.setText(sigleItem.image_url);
holder.textViewLink.setText(singleItem.link);
}
@Override
public int getItemCount() {
return itemList.size();
}
public class ItemHolder extends RecyclerView.ViewHolder {
public TextView textViewName;
public TextView textViewImage;
public TextView textViewLink;
public ItemHolder(View itemView) {
super(itemView);
textViewName = itemView.findViewById(R.id.text_name);
textViewImage = itemView.findViewById(R.id.text_image);
textViewLink = itemView.findViewById(R.id.text_link);
}
}
}
single_item.xml
This is the layout of each item that will be displyed in the recyclerview.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp">
<!-- 1. Name -->
<TextView
android:id="@+id/text_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="Name"
android:textSize="22sp"
android:textColor="@color/colorBlack"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintTop_toTopOf="parent"/>
<!-- 2. Image URL -->
<TextView
android:id="@+id/text_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="URL"
android:textSize="18sp"
android:textColor="@color/colorPrimary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintTop_toBottomOf="@+id/text_name"/>
<!-- 3. Link -->
<TextView
android:id="@+id/text_link"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="Language"
android:textSize="16sp"
android:textColor="@color/colorBlack"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintTop_toBottomOf="@+id/text_url"/>
</android.support.constraint.ConstraintLayout>
</android.support.v7.widget.CardView>
</android.support.constraint.ConstraintLayout>
来源:https://stackoverflow.com/questions/52455685/creating-horizontal-scroll-bar-using-json