We introduce material design
It's time to switch to Lollipop, friends. No matter how funny it sounds.
Just yesterday, we at Surfingbird updated the design of the application and today, in the wake of it, I would like to share our impressions of the transition to material design.
Preparatory stage.
To minimize the number of problems, it is better to update everything)
Implementing RecyclerView
RecyclerView is a new ViewGroup component that replaced List / GridView. But he is not their descendant; rather, it is an alternative branch of evolution. On the one hand, it is a much more flexible and more efficient component, on the other hand, it is missing from the box, or some things that we are used to in List / GridView (separators, fast scrolling, selectors, headers, etc.) are done differently. P.).
Firstly, according to subjective feelings, scrolling became smoother than when using listview + viewholder, and secondly, many beautiful things appeared, so the game is undoubtedly worth the candle.
Switching to this component is very simple. We drop the corresponding sdk ▸ extras ▸ android ▸ support ▸ v7 ▸ recyclerview ▸ libs▸ android-support-v7-recyclerview.jar / into the libraries / plug it into thegodless gradle or whatever you use.
1. Update the adapter, if you have already used the view-holder pattern, then everything is familiar
Replace BaseAdapter (or whatever you had there) with RecyclerView.Adapter
In onCreateViewHolder - parsim layout
where, actually, ViewHolder is a familiar stub
and transfer the view filling logic from getView to onBindViewHolder (referring to the holder - holder.stgvImageView, etc.).
We delete the methods that get no longer needed like getItem
2. Replace the ListView with a RecyclerView
3. We continue the conversation.
Work with the adapter has not changed.
The method of disconnecting the adapter at the time of the change (DataSetInvalidated) became unnecessary, the notification of the change remained unchanged
The method for calculating the last visible element has changed (to automatically load the next portion). I suppose that it is better to transfer this logic to the adapter, but if it’s very once, then you can, for example:
In general, scrolling has become a lower level, now you can get information where and how much is scrolled right in this method (forgive my English)
At this point, everything should work for you. If, for example, you need to add separators, you can add them by overriding the DividerItemDecoration class, for example like this: (vertical dividers)
(Akhtung, copy-paste you yourself know from which site)
But do not rush it! Because beautiful Cards have appeared!
We are introducing CardView
I remember when I was still a very young android developer, the interest came out and all ofigeli. We spent hours looking at how they implemented variable height cards, floating buttons (or was it in Path?), It doesn’t matter. Now you can get good-looking cards (including those of variable height and just like in the interest) in just a couple of lines of code.
We connect cardview as a library project / prescribe the magic line in the build system, drop the jar, do not forget to update the support librari version.
In fact, cards are a frame around your layout with shadows and rounds, so just frame them with your layout:
Done, my lord!
Now, let's say for the tablet version we set the display in two columns, and for phones in one:
(Ahtung, copy-paste you yourself know from which site)
And we set different display formats for different devices:
It should be something like this:
Some nuances:
Result
The developer’s eye is “blurred”, it’s hard to say whether it turned out well or so-so. For some reason, I expected more, to be honest. Dynamically falling shadows when scrolling, for example, more magic. But in general, everything turned out a little fresher. Although, of course, we have not yet fully fallen apart. You can see the result in the market .
I probably forgot something. Share the nuances, recipes and tips for switching to Lollipop in the comments. The topic is relevant, all of us will be useful and interesting.
Just yesterday, we at Surfingbird updated the design of the application and today, in the wake of it, I would like to share our impressions of the transition to material design.
Preparatory stage.
To minimize the number of problems, it is better to update everything)
- Install the lollipop image on your
nexusphone - We update Java to version 7, if not already
- Updating the IDE, we use the Intellij Idea
- Update SDK, do not forget to update Tools, Platform-tools, Build-tools, Sdk and Support library
Implementing RecyclerView
RecyclerView is a new ViewGroup component that replaced List / GridView. But he is not their descendant; rather, it is an alternative branch of evolution. On the one hand, it is a much more flexible and more efficient component, on the other hand, it is missing from the box, or some things that we are used to in List / GridView (separators, fast scrolling, selectors, headers, etc.) are done differently. P.).
Firstly, according to subjective feelings, scrolling became smoother than when using listview + viewholder, and secondly, many beautiful things appeared, so the game is undoubtedly worth the candle.
Switching to this component is very simple. We drop the corresponding sdk ▸ extras ▸ android ▸ support ▸ v7 ▸ recyclerview ▸ libs▸ android-support-v7-recyclerview.jar / into the libraries / plug it into the
1. Update the adapter, if you have already used the view-holder pattern, then everything is familiar
Replace BaseAdapter (or whatever you had there) with RecyclerView.Adapter
In onCreateViewHolder - parsim layout
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = layoutInflater.inflate(R.layout.main_adapter_griditem, null);
return new ViewHolder(view);
}
where, actually, ViewHolder is a familiar stub
class ViewHolder extends RecyclerView.ViewHolder{
private ImageView stgvImageView;
public ViewHolder(View holderView) {
super(holderView);
stgvImageView = (ImageView) holderView.findViewById(R.id.stgvImageView);
}
}
and transfer the view filling logic from getView to onBindViewHolder (referring to the holder - holder.stgvImageView, etc.).
We delete the methods that get no longer needed like getItem
2. Replace the ListView with a RecyclerView
public RecyclerView gridView;//здесь был Grid/ListView
public AdapterMain adapterMain;
public ArrayList rows;
//Это способ отображения recycleview. Кроме сетки с столбцами переменной высоты есть более канонические
//GridLayoutManager (Grid) и LinearLayoutManager (List)
public StaggeredGridLayoutManager mLayoutManager;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
aq = new AQuery(getActivity());
//Не пугайтесь это просто контейнер
final LinearLayout linearLayout = new LinearLayout(getActivity());
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.setGravity(Gravity.CENTER);
gridView = new RecyclerView(getActivity());
gridView.setHasFixedSize(true);
mLayoutManager = new StaggeredGridLayoutManager(UtilsScreen.getDisplayColumns(getActivity()),StaggeredGridLayoutManager.VERTICAL);
//можно задать горизонтальную ориентацию. Будет свежо и необычно. Наверное
gridView.setLayoutManager(mLayoutManager);
gridView.setItemAnimator(new DefaultItemAnimator());
//Это новый метод для задания divider
//gridView.addItemDecoration(new DividerItemDecoration(getActivity()));
//Этих методов больше нет
//gridView.setSmoothScrollbarEnabled(true);
//gridView.setDivider(new ColorDrawable(this.getResources().getColor(R.color.gray_divider)));
//gridView.setDividerHeight(UtilsScreen.dpToPx(8));
rows = new ArrayList();
linearLayout.addView(gridView);
return linearLayout;
}
3. We continue the conversation.
Work with the adapter has not changed.
@Override
public void onViewCreated(View view,Bundle savedInstanceState) {
super.onViewCreated(view,savedInstanceState);
adapterMain = new AdapterMain(getActivity(),rows);
gridView.setAdapter(adapterMain);
gridView.setOnScrollListener(onScroll);
}
The method of disconnecting the adapter at the time of the change (DataSetInvalidated) became unnecessary, the notification of the change remained unchanged
adapterMain.notifyDataSetChanged();
if (page == 1) gridView.scrollToPosition(0);//точно не помню как раньше назывался этот метод
The method for calculating the last visible element has changed (to automatically load the next portion). I suppose that it is better to transfer this logic to the adapter, but if it’s very once, then you can, for example:
gridView.setOnScrollListener(onScroll);
//---
private RecyclerView.OnScrollListener onScroll = new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int[] visibleItems = ((StaggeredGridLayoutManager) gridView.getLayoutManager()).findLastVisibleItemPositions(null);
int lastitem=0;
for (int i:visibleItems) {
lastitem = Math.max(lastitem,i);
}
if (lastitem>0 && lastitem>adapterMain.data.size()-5 && !isRunning) {
if (!internetIsOver) {
refresh();
}
}
}
};
In general, scrolling has become a lower level, now you can get information where and how much is scrolled right in this method (forgive my English)
At this point, everything should work for you. If, for example, you need to add separators, you can add them by overriding the DividerItemDecoration class, for example like this: (vertical dividers)
(Akhtung, copy-paste you yourself know from which site)
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
};
private Drawable mDivider;
private int offset = 0;
public DividerItemDecoration(Context context) {
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
offset = UtilsScreen.dpToPx(16);
a.recycle();
}
@Override
public void onDraw(Canvas c, RecyclerView parent) {
drawVertical(c, parent);
}
public void drawVertical(Canvas c, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + offset;//mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
@Override
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
outRect.set(0, 0, 0, offset);//mDivider.getIntrinsicHeight());
}
}
But do not rush it! Because beautiful Cards have appeared!
We are introducing CardView
I remember when I was still a very young android developer, the interest came out and all ofigeli. We spent hours looking at how they implemented variable height cards, floating buttons (or was it in Path?), It doesn’t matter. Now you can get good-looking cards (including those of variable height and just like in the interest) in just a couple of lines of code.
We connect cardview as a library project / prescribe the magic line in the build system, drop the jar, do not forget to update the support librari version.
In fact, cards are a frame around your layout with shadows and rounds, so just frame them with your layout:
//---
Done, my lord!
Now, let's say for the tablet version we set the display in two columns, and for phones in one:
(Ahtung, copy-paste you yourself know from which site)
public static boolean isTablet(Context context) {
boolean xlarge = ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == 4);
boolean large = ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE);
return (xlarge || large);
}
public static int getDisplayColumns(Activity activity) {
int columnCount = 1;
if (isTablet(activity)) {
columnCount = 2;
}
return columnCount;
}
And we set different display formats for different devices:
mLayoutManager = new StaggeredGridLayoutManager(UtilsScreen.getDisplayColumns(getActivity()),StaggeredGridLayoutManager.VERTICAL);
It should be something like this:
Some nuances:
- After we posted the application on the side, on some devices (for some reason on the nexus) and for some reason including 4.4.4 - the application began to fall in a strange way in the support librari area (and on our phones (including the nexus) everything worked). I had to disable proguard, it helped but the sediment remained.
- We didn’t really like the font color in the default light theme. It is very tender, considering that the color rendition is different on all android devices, therefore we decided to turn off the font color a little darker.
- You can now disable the shadow on an action bar, for example, like this: getSupportActionBar (). SetElevation (0);
- The application will not work on beta Lollipop in the same way that all other applications in Lollipop design do not work on it (gmail, press)
- The action bar icons have become smaller. We just moved them to the folder (xxhdpi)
- So far we decided to score on the animation. Before the eyes of the Google press and everything seems to spin wildly / spinning / swims / blinks beautifully, but we are not yet ready for such a decisive animation.
Result
The developer’s eye is “blurred”, it’s hard to say whether it turned out well or so-so. For some reason, I expected more, to be honest. Dynamically falling shadows when scrolling, for example, more magic. But in general, everything turned out a little fresher. Although, of course, we have not yet fully fallen apart. You can see the result in the market .
I probably forgot something. Share the nuances, recipes and tips for switching to Lollipop in the comments. The topic is relevant, all of us will be useful and interesting.