手把手教你仿一個知乎日報Android客戶端(三)主頁面設計
各位朋友,從本篇文章和開始,手把手教你仿一個Android客戶端就要正式開始探究怎樣實現我們前面的那些需求了。在此開發我們將會使用git作為版本控制工具,並且將程式碼託管到github,好啦,廢話少說,咱們開工。
一、建立專案
怎麼建立專案大家應該都知道哈,我就不贅述了,在這裡我的專案名為 “ZhiHudaily”,簡單的翻譯下就是知乎日報。
支援最低的SDK版本為 API 19也就是android 4.4
緊接著建立一個HomeActivity(MainActivity改名來的),顧名思義就是今天我們的主角— 噹噹噹當 —Home頁
二、配置CVS
具體的配置內容這裡就不講啦,各位可以參考下
三、正式開始
依照我個人的習慣呢,在正式開始編寫業務程式碼前有幾件事情要做
1.編寫BaseActivity
2.自己寫一個Toolbar
3.更換預設主題
首先建立一個BaseActivit,記得在AndroidManifest.xml中註冊哦
BaseActivity中主要是對Toolba的初始化以及對toolbar的左上角選單按鈕以及back按鈕
重要的 BaseActivity程式碼
public class BaseActivity extends AppCompatActivity{
public Toolbar toolbar;
/**
*
* @param title 標題欄標題
* @param type 標題型別,1為帶選單欄的標題欄,2為帶back鍵的標題欄
*/
public void setTitle(String title,int type){
toolbar= (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitleTextColor(Color.WHITE);//標題字型顏色
toolbar.setTitle(title);
setSupportActionBar(toolbar);//設定為actionbar
switch (type){
case 1:
toolbar.setNavigationIcon(R.drawable.menu);
break;
case 2:
toolbar.setNavigationIcon(R.drawable.back);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
}
}
如果你願意的話,甚至可以把Toast直接放到BaseActivity中單獨寫作一個方法,當要用到的時候,直接一行 showToast(“”);就搞定了
簡單的 Toolbar的程式碼
<?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">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:background="@color/colorPrimary"
android:layout_height="?attr/actionBarSize"/>
</LinearLayout>
我們建立好的專案在預設狀態下會使用DarkActionBar(layout上面的一個藍條),因為我們要用自己定義的toolbar,所以我們
修改style.xml
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
改為
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
此時我們可以對home頁進行編輯,首先插入事先寫好的toolbar,然後在activity中進行初始化以及設定
枯燥的 layout程式碼
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.administrator.zhihudaily.HomeActivity">
<include layout="@layout/toolbar"/>
</RelativeLayout>
枯燥的 HomeActivity程式碼
public class HomeActivity extends BaseActivity {
//記得,所有Activity都繼承自BaseActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
//初始化佈局
private void initView(){
setTitle("首頁",1);//設定標題內容,該方法繼承自父類,所以再寫一次
}
}
然後來看看樣子
新增開源庫
這個專案中我們將會用到BGABanner庫,以及v7包中的cardview,和Recycleview,以及圖片載入庫Gilde,網路訪問庫 Volley,Volley版本太多,所以我隨意找了一個
在build.gradle中新增以下依賴
compile ‘com.android.support:recyclerview-v7:25.3.1’
compile ‘com.android.support:cardview-v7:25.3.1’
compile ‘cn.bingoogolapple:bga-banner:[email protected]’
compile ‘com.github.bumptech.glide:glide:3.7.0’
compile ‘eu.the4thfloor.volley:com.android.volley:2015.05.28’
設計item
枯燥的 info_item.xml程式碼
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item"
android:background="#fff"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/item_headtitle"
android:layout_width="match_parent"
android:background="#fff"
android:layout_height="30dp"
android:visibility="gone"
android:layout_marginTop="10dp"
android:gravity="center|left"
android:paddingLeft="10dp"
android:text="頭部"/>
<android.support.v7.widget.CardView
android:layout_marginTop="10dp"
android:id="@+id/opencard"
android:background="#fff"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:background="#fff"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:background="#fff"
android:layout_weight="3"
android:layout_width="300dp"
android:gravity="center|left"
android:orientation="vertical"
android:layout_height="130dp">
<TextView
android:id="@+id/item_title"
android:background="#fff"
android:layout_width="wrap_content"
android:padding="10dp"
android:textColor="#000"
android:textSize="18sp"
android:gravity="left"
android:text="標題"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/data"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:text="20170417"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<ImageView
android:layout_weight="1"
android:layout_marginRight="5dp"
android:id="@+id/item_image"
android:layout_width="120dp"
android:layout_height="120dp" />
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
此段程式碼中,包含了item的標題以及item的頭部資訊。
Recycleview可以看做是ListView的升級版,它效能更好,玩法也更多,既然要用到列表,那我們就需要有一個介面卡,以及一個javabean類,用於生成列表中的新聞物件(?)
ItemBean
枯燥的 Item.class
package com.example.administrator.volleytest.UI.bean;
/**
* Created by Administrator on 2017/4/17 0017.
*/
public class Item {
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getImgurl() {
return imgurl;
}
public void setImgurl(String imgurl) {
this.imgurl = imgurl;
}
public String getHeadtitle() {
return headtitle;
}
public void setHeadtitle(String headtitle) {
this.headtitle = headtitle;
}
String headtitle;//頭部標題
String id;//id
String title;//文章標題
String date;//日期
String imgurl;//配圖地址
}
懵逼的 InfoListAdapter.class
public class InfoListAdapter extends RecyclerView.Adapter<InfoListAdapter.InfoViewHolder> {
private ArrayList<Item> mData;//用於儲存資料
private Context mContext;//上下文
InfoViewHolder holder=null; //viewholde,可以提高recycleview的效能
public InfoListAdapter(ArrayList<Item> data,Context context) {
//構造方法,用於接收上下文和展示資料
this.mData = data;
this.mContext=context;
}
@Override
public InfoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
holder=new InfoViewHolder(LayoutInflater.from(mContext).inflate(R.layout.info_item,parent,false));
return holder;
}
@Override
public void onBindViewHolder(InfoViewHolder holder, int position) {
//此方法內可以對佈局中的控制元件進行操作
holder.title.setText(mData.get(position).getTitle());//
Glide.with(mContext).load(mData.get(position).getImgurl()).into(holder.img);
}
@Override
public int getItemCount() {
//獲取資料長度
return mData.size();
}
class InfoViewHolder extends RecyclerView.ViewHolder {
//此部分我也難以用語言來解釋,諸位可以搜尋下網上各路大牛的詳解
//我也需要學習
TextView title;//標題
ImageView img;//顯示的圖片
TextView headTitle;//頭部標題
public InfoViewHolder(View itemView) {
super(itemView);
title= (TextView) itemView.findViewById(R.id.item_title);
img= (ImageView) itemView.findViewById(R.id.item_image);
headTitle= (TextView) itemView.findViewById(R.id.item_headtitle);
}
}
}
介面卡準備好後,我們要對HomeActivity和activity_main佈局 做一些簡單的修改用於測試介面卡是否能夠正常使用
首先,在activity_main.xml中新增RecycleView的控制元件,使其填滿整個佈局
activity_main.xml(部分)
<android.support.v7.widget.RecyclerView
android:id="@+id/infolist"
android:layout_marginTop="?attr/actionBarSize"
android:layout_width="match_parent"
android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
然後在Activity中,我們需要對控制元件進行繫結,建立介面卡以及新增模擬資料
將就能看的 HomeActiviy.java
public class HomeActivity extends BaseActivity {
private RecyclerView mInfoList;//用於顯示的列表
private ArrayList<Item> mDatas;//用於儲存資料
private InfoListAdapter adapter;//介面卡
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initDate();
initView();
}
private void initView() {
//初始化頁面
setTitle("首頁", 1);//設定標題
mInfoList= (RecyclerView) findViewById(R.id.infolist);//繫結RecycleView
mInfoList.setLayoutManager(new LinearLayoutManager(this));//設定佈局管理器,你可以通過這個來決定你是要做一個Listview還是瀑布流
adapter=new InfoListAdapter(mDatas,HomeActivity.this);//初始化介面卡
mInfoList.setAdapter(adapter);//為ReycleView設定介面卡
}
private void initDate(){
//初始化資料
mDatas=new ArrayList<>();
//新增模擬資料
for (int i='A';i<'z';i++){
Item item=new Item();
item.setTitle(""+(char)i);
item.setImgurl("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1496110531&di=281ed2731cabceee7c851e5b2ca83a85&imgtype=jpg&er=1&src=http%3A%2F%2Fpic.58pic.com%2F58pic%2F13%2F15%2F64%2F44c58PICsni_1024.jpg");
mDatas.add(item);
}
}
}
記得在AndroidManifest.xml中新增網路訪問許可權
<uses-permission android:name="android.permission.INTERNET"/>
現在我們再看下效果
大致效果就是這樣,不過這個圖片什麼鬼
接下來就要考慮資料的問題,點開文件,我們直接看第三條 最新訊息和第五條 過往訊息
- 最新訊息
URL: http://news-at.zhihu.com/api/4/news/latest
響應例項:
{
date: “20140523”,
stories: [
{
title: “中國古代傢俱發展到今天有兩個高峰,一個兩宋一個明末(多圖)”,
ga_prefix: “052321”,
images: [
“http://p1.zhimg.com/45/b9/45b9f057fc1957ed2c946814342c0f02.jpg”
],
type: 0,
id: 3930445
},
…
],
top_stories: [
{
title: “商場和很多人家裡,竹製傢俱越來越多(多圖)”,
image: “http://p2.zhimg.com/9a/15/9a1570bb9e5fa53ae9fb9269a56ee019.jpg“,
ga_prefix: “052315”,
type: 0,
id: 3930883
},
…
]
}
分析:
date : 日期
stories : 當日新聞
title : 新聞標題
images : 影象地址(官方 API 使用陣列形式。目前暫未有使用多張圖片的情形出現,曾見無 images 屬性的情況,請在使用中注意 )
ga_prefix : 供 Google Analytics 使用
type : 作用未知
id : url 與 share_url 中最後的數字(應為內容的 id)
multipic : 訊息是否包含多張圖片(僅出現在包含多圖的新聞中)
top_stories : 介面頂部 ViewPager 滾動顯示的顯示內容(子項格式同上)(請注意區分此處的 image 屬性與 stories 中的 images 屬性)
我只貼出了第三條的資料,沒有貼出第五條,因為第三條和第五條除了url後面帶的引數不同,其返回形式是相同的
文件的作者已經將資料請求的連結以及返回資料的格式和 解釋給出來了,下一步我們來寫一個網路請求方法,將資料新增到ArrayList中
我們在HomeActivity中新增一個
初步展示的 HomeActivity.class
private int otherdate=0;//從今日算起,倒數第幾天 eg:昨天 就是1 前天就是 2
private RequestQueue mQueue;
private void initDate(){
//將此處之前的for迴圈插入虛擬資料刪除
mDatas=new ArrayList<>();
getInfoFromNet();
}
private void getInfoFromNet(){
//獲取網路資料
mQueue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest("http://news.at.zhihu.com/api/4/news/before/" + getDate(), null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
JSONArray list = null;
try {
list = response.getJSONArray("stories");
//獲取返回資料的內容
} catch (JSONException e) {
e.printStackTrace();
}
//開始解析資料
for (int i = 0; i < list.length(); i++) {
JSONObject item = list.getJSONObject(i);
JSONArray images = item.getJSONArray("images");
Item listItem = new Item();
//建立list中的每一個物件,並設定資料
listItem.setTitle(item.getString("title"));
listItem.setImgurl(images.getString(0));
listItem.setDate(getDate());
listItem.setId(item.getString("id"));
mDatas.add(listItem);
}
adapter.notifyDataSetChanged();//通知介面卡 重新整理資料啦 啊喂
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
//如果遇到異常,在這裡通知使用者
@Override
public void onErrorResponse(VolleyError error) {
showToast("碰到了一點問題");
//此處的showToast();是已經在BaseActivity中寫好的,可以直接拿來用
}
});
mQueue.add(jsonObjectRequest);//開始任務
}
private String getDate(){
//獲取當前需要載入的資料的日期
Calendar c = Calendar.getInstance();
c.setTime(new Date());
c.add(Calendar.DAY_OF_MONTH, -otherdate);//otherdate天前的日子
String date = new SimpleDateFormat("yyyyMMdd").format(c.getTime());
//將日期轉化為20170520這樣的格式
return date;
}
我們再來看下效果
然後和知乎日報對比下
可能有人要問了,Banner你吃了嘛?還有下面顯示的內容和你這個不一樣啊,還有那些今日熱聞什麼的,你到底會不會呀
嗯,我也注意到了,讓我們來一項一項解決它
1.顯示資料不準確
經過我的觀察,雖然今天是2017年5月23日,但是去用20170523請求到的是昨天的資料,但是如果用20170524請求到的資料是不包含banner也就是“top_stories”欄位,那麼應該是請求的問題了
我們來對比下新內容和歷史內容的請求連結
新的:http://news-at.zhihu.com/api/4/news/latest
歷史內容:http://news.at.zhihu.com/api/4/news/before/20170523
嗯,剛才果然粗心大意了,那麼程式碼又要改改。
## 更改後的程式碼 HomeActivity →getInfoFromNet()
mQueue = Volley.newRequestQueue(this);
String url=null;
if (otherdate==0){
//如果是今日就用最後的資料
url="http://news-at.zhihu.com/api/4/news/latest";
}else {
//否則就是之前的判斷流程
url= "http://news.at.zhihu.com/api/4/news/before/" + getDate();
}
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(url, null,
//將此處之前的地址換為url引數
……
//為了防止重複載入當前日的資料,我們需要讓日子往後挪一天
c.add(Calendar.DAY_OF_MONTH, -otherdate-1);//otherdate天前的日子
……
再來對比下
知乎日報
這樣一來,最簡單的資料問題解決了
2,Banner去哪兒了
我以前一直以為上面的banner是遊離於listview之外的,知道我發現了headview這個東西,現在我們就要向recycleview中新增一個headview
先寫一個headview的佈局
headview.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="230dp"
>
<cn.bingoogolapple.bgabanner.BGABanner
android:id="@+id/banner"
app:banner_pageChangeDuration="1000"
app:banner_pointAutoPlayAble="true"
app:banner_tipTextSize="17sp"
app:banner_pointTopBottomMargin="10dp"
android:layout_width="match_parent"
android:layout_height="230dp"/>
</LinearLayout>
對InfoListAdapter新增以下程式碼
修改InfoListAdapter
public class InfoListAdapter extends RecyclerView.Adapter<InfoListAdapter.InfoViewHolder> {
private ArrayList<Item> mData;//用於儲存資料
private Context mContext;//上下文
InfoViewHolder holder=null; //viewholde,可以提高recycleview的效能
public InfoListAdapter(ArrayList<Item> data,Context context) {
//構造方法,用於接收上下文和展示資料
this.mData = data;
this.mContext=context;
}
@Override
public InfoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//這裡進行過改動
if (headView!=null && viewType==TYPE_HEADER) return new InfoViewHolder(headView);
holder=new InfoViewHolder(LayoutInflater.from(mContext).inflate(R.layout.info_item,parent,false));
return holder;
}
@Override
public void onBindViewHolder(InfoViewHolder holder, int position) {
//此方法內可以對佈局中的控制元件進行操作
//這裡進行過改動
if (getItemViewType(position)==TYPE_HEADER) return;
final int pos=getRealPosition(holder);
holder.title.setText(mData.get(pos).getTitle());//
Glide.with(mContext).load(mData.get(pos).getImgurl()).into(holder.img);
}
@Override
public int getItemCount() {
//獲取資料長度
//這裡進行過改動
return headView==null? mData.size():mData.size()+1;
}
class InfoViewHolder extends RecyclerView.ViewHolder {
//此部分我難以用語言來解釋,諸位可以搜尋下網上各路大牛的詳解
//我也需要學習
TextView title;//標題
ImageView img;//顯示的圖片
TextView headTitle;//頭部標題
public InfoViewHolder(View itemView) {
super(itemView);
title= (TextView) itemView.findViewById(R.id.item_title);
img= (ImageView) itemView.findViewById(R.id.item_image);
headTitle= (TextView) itemView.findViewById(R.id.item_headtitle);
}
}
//下面的是新新增的
public static final int TYPE_HEADER = 0;//顯示headvuiew
public static final int TYPE_NORMAL = 1;//顯示普通的item
private View headView;//這傢伙就是Banner
public void setHeadView(View headView){
this.headView=headView;
notifyItemInserted(0);
}
public View getHeadView(){
return headView;
}
@Override
public int getItemViewType(int position) {
if (headView==null)
return TYPE_NORMAL;
if (position==0)
return TYPE_HEADER;
return TYPE_NORMAL;
}
private int getRealPosition(RecyclerView.ViewHolder holder) {
int position=holder.getLayoutPosition();
return headView==null? position:position-1;
}
}
向HomeActivity中新增以下程式碼
HomeActivity→initBanner();
private ArrayList<Item> bannerList;//banner控制元件
private ArrayList<String> titles;//存放banner中的標題
private ArrayList<String> images;//存放banner中的圖片
private ArrayList<String> ids;//存放每一項的id
private void initBanner() {
//初始化banner
titles=new ArrayList<>();
ids=new ArrayList<>();
images=new ArrayList<>();
bannerList = new ArrayList<>();
mQueue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest("http://news-at.zhihu.com/api/4/news/latest", null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
//解析banner中的資料
JSONArray topinfos = response.getJSONArray("top_stories");
Log.d("TAG", "onResponse: "+topinfos);
for (int i = 0; i < topinfos.length(); i++) {
JSONObject item = topinfos.getJSONObject(i);
Item item1 = new Item();
item1.setImgurl(item.getString("image"));
item1.setTitle(item.getString("title"));
item1.setId(item.getString("id"));
bannerList.add(item1);
titles.add(item1.getTitle());
images.add(item1.getImgurl());
ids.add(item1.getId());
}
setHeader(mInfoList, images, titles, ids);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
mQueue.add(jsonObjectRequest);
}
private void setHeader(RecyclerView view, ArrayList<String> urls, ArrayList<String> titles, final ArrayList<String> ids) {
View header = LayoutInflater.from(this).inflate(R.layout.headview, view, false);
//找到banner所在的佈局
BGABanner banner = (BGABanner) header.findViewById(R.id.banner);
//繫結banner
banner.setAdapter(new BGABanner.Adapter<ImageView, String>() {
@Override
public void fillBannerItem(BGABanner banner, ImageView itemView, String model, int position) {
Glide.with(HomeActivity.this)
.load(model)
.centerCrop()
.dontAnimate()
.into(itemView);
}
});
banner.setDelegate(new BGABanner.Delegate() {
@Override
public void onBannerItemClick(BGABanner banner, View itemView, Object model, int position) {
//此處可設定banner子項的點選事件
}
});
banner.setData(urls, titles);
adapter.setHeadView(header);//向介面卡中新增banner
}
我們再來看一次效果
由於(不知道什麼原因有限),這次就和大家交流這些,在下一篇博文中將會把我們在知乎日報上看到的日期頭以及載入更多,重新整理還有點選檢視詳細內容等功能實現出來。如果大家有不懂的歡迎在評論中說出來,如果我有哪部分表述的不準確,也希望能夠得到指點。
願與諸位同進步
謝謝。
相關推薦
手把手教你仿一個知乎日報Android客戶端(三)主頁面設計
各位朋友,從本篇文章和開始,手把手教你仿一個Android客戶端就要正式開始探究怎樣實現我們前面的那些需求了。在此開發我們將會使用git作為版本控制工具,並且將程式碼託管到github,好啦,廢話少說,咱們開工。 一、建立專案 怎麼建立專案大家應該都知道
手把手教你仿一個知乎日報Android客戶端(一)多圖
本文為作者原創,轉載請註明出處@大蘑菇的部落格 圖片託管服務由貼相簿提供 作為一隻網蟲,肯定是經常泡在網路的海洋裡,有一天偶然看到了知乎日報的API,各方面介面都還挺全面,於是本著“不用白不用”的真理,我決定仿一個知乎日報Adnroid客戶端。
手把手教你打造一個心電圖效果View Android自定義View
大家好,看我像不像蘑菇…因為我在學校呆的發黴了。 思而不學則殆 麗麗說得對,我有奇怪的疑問,大都是思而不學造成的,在我書讀不夠的情況下想太多,大多等於白想,所以革命沒成功,同志仍需努力。 好了廢話不說了,由於布總要做一個心電圖的玩意,所以做來練練手
手把手教你如何玩轉外掛:分頁外掛(Pagehelper)
情景引入:小白:起床起床,,,快起床!!!我:怎麼怎麼了,小白你到底又怎麼了。。小白:我發現在Web系統中,分頁是一種很常見的功能,可是,我之前寫的方法都比較麻煩,移植性不是很高,有沒有什麼好辦法可以快速實現分頁的呢?我:確實是的,分頁功能幾乎在每個系統中都是存在的,它的實現
基於React Native構建的仿京東客戶端(三)
ImageButton.js檔案完整的程式碼如下:import React, { Component } from 'react';import { StyleSheet, Text, View, Image, TouchableWithoutFeedback,}
手把手教你打造一個高仿雷達掃描效果和仿水波紋中心擴散效果
高仿雷達掃描效果和仿水波紋中心擴散效果,手把手教你擼一個炫酷的自定義view。我們先看效果圖吧對於仿水波紋中心擴脈衝效果思路大家一看就應該知道,一張圖片在不斷的放大,且顏色漸變。那不就是自定義屬性動畫嗎沒錯就是這麼神奇。ScaleAnimation+AlphaA
Flutter:手把手教你實現一個仿QQ側滑選單的功能
一個類似於QQ側滑選單的功能,支援從上、下、左、右四個方法開啟選單欄。可以通過自定義transform實現更加炫酷的動效! 先上效果圖: slide from left.gif slide from right.gif slide from top
手把手教你做一個吸引人的購物網站
網站建設 購物網站 自助建站 購物網站盈利能力相信很多用戶都是有目共睹的,因此不少的中小企業對購物網站的建設也是趨之若鶩,怎麽企業設計購物網站有什麽方法能夠為購物網站提高人氣呢?下面看看凡科網站建設帶來的一些分析。 要對用戶的跟隨心理進行分析。無論是實體銷售還是線上的銷售,用戶都會有一種莫名
手把手教你編寫一個簡單的PHP模塊形態的後門
cpp rest xtu job ring 事先 們的 original call 看到Freebuf 小編發表的用這個隱藏於PHP模塊中的rootkit,就能持久接管服務器文章,很感興趣,苦無作者沒留下PoC,自己研究一番,有了此文 0×00. 引言 PHP是一個非常流行
手把手教你實現一個完整的BST(超級詳細)
查找樹 str image isempty 使用 this 根據 數據 false 查找基本分類如下: 線性表的查找 順序查找 折半查找 分塊查找 樹表的查找 二叉排序樹 平衡二叉樹 B樹 B+樹 散列表的查找 今天介紹二叉排序樹。 二叉排序樹 ( Binary
大神手把手教你寫一個頁面模板引擎,只需20行Javascript代碼!
[1] 表達 最終 strong ice ali 開頭 syntax years 只用20行Javascript代碼就寫出一個頁面模板引擎的大神是AbsurdJS的作者,下面是他分享的全文,轉需。 不知道你有木有聽說過一個基於Javascript的Web頁面預處理器,叫做A
手把手教你搭建一個加密貨幣交易模擬器,不用投錢就能玩
box NPU nec idp reat 監控 最簡 data- 自己 手把手教你搭建一個加密貨幣交易模擬器,不用投錢就能玩 大數據文摘,編譯:汪小七、黃文暢、小魚 我雖然不是交易員,但對加密貨幣的交易非常感興趣。然而,我不會在自己什麽都不清楚的時候就盲目投
騰訊雲技術專家盧萌凱手把手教你Demo一個人臉識別程序!
方案設計 如果 簡介 同學會 分析 ref 視頻轉碼 頭像 根據 歡迎大家前往騰訊雲+社區,獲取更多騰訊海量技術實踐幹貨哦~ 本文來自騰訊雲技術沙龍,本次沙龍主題為Serverless架構開發與SCF部署實踐 盧萌凱:畢業於東南大學,曾就職於華為,熟悉雲行業解決方案。
手把手教你構建一個音視訊小程式
歡迎大家前往騰訊雲+社群,獲取更多騰訊海量技術實踐乾貨哦~ 本文由騰訊視訊雲終端團隊發表於雲+社群專欄 騰訊雲提供了全套技術文件和原始碼來幫助您快速構建一個音視訊小程式,但是再好的原始碼和文件也有學習成本,為了儘快的能除錯起來,我們還提供了一個免費的一鍵部署服務:您只需輕點幾下滑鼠,就可以在自己
WebRTC系列(1)-手把手教你實現一個瀏覽器拍照室Demo
1.WebRTC開發背景 由於業務需求,需要在專案中實現實時音視訊通話功能,之前基於瀏覽器開發的Web專案要進行音視訊通話,需要安裝flash外掛才能實現或者使用C/S客戶端進行通訊。隨著網際網路技術的驅動下,在很多場景下需要進行音視訊通訊,在生活中我們現在使用電話越來越少,使用微信和視訊越來越多。在一
Vue+ElementUI: 手把手教你做一個audio元件
目的 本專案的目的是教你如何實現一個簡單的音樂播放器(這並不難) 本專案並不是一個可以用於生產環境的element播放器,所以並沒有考慮太多的相容性問題 本專案不是ElementUI的一個音訊外掛,只是一個教程,不過你可以自行擴充套件實現 本專案只是為了學習audio相關事件以及API
手把手教你實現一個 Vue 進度條組件!
內容 分享圖片 軟件 pen export padding eight 自己 自動完成 最近在個人的項目中,想對頁面之間跳轉的過程進行優化,想到了很多文檔或 npm 等都用到的頁面跳轉進度條,於是便想自己去實現一個,特此記錄。 來看下 npm 搜索組件時候的效果: so
手把手教你實現一個 Vue 進度條元件!
最近在個人的專案中,想對頁面之間跳轉的過程進行優化,想到了很多文件或 npm 等都用到的頁面跳轉進度條,於是便想自己去實現一個,特此記錄。 來看下 npm 搜尋元件時候的效果: so 下面咱們一起動手實現一下唄。 定義使用方式 想實現一個元件的前提,一定要想好你的需求是什麼,還要自己去定義一
手把手教你擼一個Loading
點選上面藍色字型關注 “IT大飛說” 置頂公眾號( ID:ITBigFly)第一時間收到推送 作為 Android 開發者,無奈經常會碰到各種各樣的奇葩需求,現在大多公司 UI 設計圖、標註都是按 IOS 來設計的,包括一個
手把手教你做一個自己的chrome擴充套件程式
手把手教你做一個自己的chrome擴充套件程式 [目錄] first.效果 1.收藏夾修改 (1).滑鼠移動到收藏夾上的動作效果 (2).收藏夾框 (3)百度搜索框功能 2.右上文字修改 3.背景圖片修改 4