Android使用ListView實(shí)現(xiàn)滾輪的動(dòng)畫效果實(shí)例
之前收到一個(gè)需求,需要把一個(gè)數(shù)據(jù)展示列表頁面做成像滾輪那樣的動(dòng)畫效果:中間最大然后向上下兩端逐漸縮小。我想了想iOS那邊自帶滾輪組件,安卓得自己去實(shí)現(xiàn),目前網(wǎng)上仿ios的滾輪組件的也有一些,但是感覺不適合我,我的要求沒那么復(fù)雜,于是決定自己動(dòng)手去實(shí)現(xiàn)一下。
動(dòng)手前先分析一下應(yīng)該怎么做,歸根到底只是要實(shí)現(xiàn)縮放效果,由中間向兩邊變小,當(dāng)一個(gè)item越接近中間就放大,越遠(yuǎn)離中間就縮小。那么可以通過先獲取ListView的中點(diǎn),然后獲取當(dāng)前可視的所有item跟ListView的中點(diǎn)的垂直距離計(jì)算出一個(gè)比例,然后將item的大小根據(jù)這個(gè)比例進(jìn)行縮放,各個(gè)item跟ListView的中點(diǎn)的垂直距離不同,計(jì)算出來的比例也就不同,然后每次滾動(dòng)的時(shí)候都計(jì)算比例然后進(jìn)行縮放,這樣應(yīng)該就能實(shí)現(xiàn)我們想要的效果了。
因?yàn)橐婚_始我的列表展示就是用ListView做的,有其他效果在里面,也不方便換其他組件,所以依然還是用ListView實(shí)現(xiàn)就好了。由于我們是每次一滾動(dòng)都要進(jìn)行縮放,ListView有提供一個(gè)OnScrollListener,它的onScroll方法每次一開始滾動(dòng)就會(huì)調(diào)用,所以我們選擇重寫它。當(dāng)它被調(diào)用的時(shí)候,我們就開始獲取ListView中點(diǎn),然后開始計(jì)算每個(gè)item的距離進(jìn)行縮放.
/**
* 中點(diǎn)的Y坐標(biāo)
*/
private float centerY = 0f;
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
//計(jì)算中點(diǎn)
centerY = getHeight()/2;
//判斷中點(diǎn)的有效性
if(centerY <= 0){
return;
}
//開始對(duì)當(dāng)前顯示的View進(jìn)行縮放
for(int i = 0; i < visibleItemCount; i++){
//獲取item
View temp_view = getChildAt(i);
//計(jì)算item的中點(diǎn)Y坐標(biāo)
float itemY = temp_view.getBottom()-(temp_view.getHeight()/2);
//計(jì)算離中點(diǎn)的距離
float distance = centerY;
if(itemY > centerY){
distance = itemY - centerY;
}else{
distance = centerY - itemY;
}
//根據(jù)距離進(jìn)行縮放
temp_view.setScaleY(1.1f - (distance / centerY) < 0 ? 0 : 1.1f - (distance / centerY));
temp_view.setScaleX(1.1f - (distance / centerY) < 0 ? 0 : 1.1f - (distance / centerY));
//根據(jù)距離改變透明度
temp_view.setAlpha(1.1f - (distance / centerY) < 0 ? 0 : 1.1f - (distance / centerY));
}
}
后面不想加demo了,所以直接上整個(gè)ListView的代碼吧
/**
* 模仿滾輪動(dòng)畫縮放的ListView
* Created by xu on 2017/3/3.
*/
public class XuListView extends ListView implements AbsListView.OnScrollListener {
private static final String TAG = "XuListView";
/**
* 中點(diǎn)的Y坐標(biāo)
*/
private float centerY = 0f;
public XuListView(Context context, AttributeSet attrs) {
super(context, attrs);
//設(shè)置一個(gè)滾動(dòng)監(jiān)聽
setOnScrollListener(this);
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
//計(jì)算中點(diǎn)
centerY = getHeight()/2;
//判斷中點(diǎn)的有效性
if(centerY <= 0){
return;
}
//開始對(duì)當(dāng)前顯示的View進(jìn)行縮放
for(int i = 0; i < visibleItemCount; i++){
//獲取item
View temp_view = getChildAt(i);
//計(jì)算item的中點(diǎn)Y坐標(biāo)
float itemY = temp_view.getBottom()-(temp_view.getHeight()/2);
//計(jì)算離中點(diǎn)的距離
float distance = centerY;
if(itemY > centerY){
distance = itemY - centerY;
}else{
distance = centerY - itemY;
}
//根據(jù)距離進(jìn)行縮放
temp_view.setScaleY(1.1f - (distance / centerY) < 0 ? 0 : 1.1f - (distance / centerY));
temp_view.setScaleX(1.1f - (distance / centerY) < 0 ? 0 : 1.1f - (distance / centerY));
//根據(jù)距離改變透明度
temp_view.setAlpha(1.1f - (distance / centerY) < 0 ? 0 : 1.1f - (distance / centerY));
}
}
}
這樣基本就實(shí)現(xiàn)了我們想要的效果了

但是現(xiàn)在有一個(gè)問題,就是第一個(gè)item和最后一個(gè)item無法滾動(dòng)到中間從而放大突出顯示。對(duì)此我暫時(shí)想了兩個(gè)方法去解決:1、在頭尾各種添加一些空白的item,使我們需要顯示的數(shù)據(jù)都可以滾動(dòng)到最中間。(我現(xiàn)在就是這么做的);2、使整個(gè)列表實(shí)現(xiàn)循環(huán)滾動(dòng)。
添加空白的item的話,我是通過修改adapter去實(shí)現(xiàn)的。數(shù)據(jù)源是一個(gè)數(shù)組,我在數(shù)組前面和后面各加一些特殊的數(shù)據(jù),adapter實(shí)現(xiàn)getview的時(shí)候,如果發(fā)現(xiàn)當(dāng)前item的數(shù)據(jù)是特殊數(shù)據(jù),那么item就變透明,從而實(shí)現(xiàn)了我們?cè)疽@示的數(shù)據(jù)都可以被滾動(dòng)最中間;
先從數(shù)據(jù)源下手,從頭尾填充特殊的數(shù)據(jù)
public class MainActivity extends AppCompatActivity {
XuListView mLisetview;
MyAdapter adapter;
ArrayList<String> nos = new ArrayList<String>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLisetview = (XuListView) findViewById(R.id.list_test);
ArrayList<String> temp = new ArrayList<String>();
for(int i = 0;i<10;i++){
temp.add(i+"");
}
adapter = new MyAdapter(this,temp);
mLisetview.setAdapter(adapter);
resetitem(mLisetview);
}
/**
* 在頭尾填充透明的item數(shù)據(jù)
*/
private void resetitem(ListView listview) {
if(listview == null){
return;
}
//獲取屏幕高度
WindowManager wm =getWindowManager();
int displayheight = wm.getDefaultDisplay().getHeight();
//計(jì)算一個(gè)item的高度
int itemhight = 0;
if(adapter!=null){
View v=(View)adapter.getView(0, null, listview);
v.measure(
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
itemhight=v.getMeasuredHeight();
}
//根據(jù)Item的高度和屏幕的高度計(jì)算需要多少個(gè)item可以填滿一半的屏幕
int newcount = ((displayheight/2)/itemhight);
//填充前面的空白item
for (int i = 1; i <= newcount; i++) {
nos.add("full");
}
//添加我們需要顯示的數(shù)據(jù)
for(int i = 0;i<10;i++){
nos.add(i+"");
}
//填充后面的空白item
for (int i = 1; i <= newcount; i++) {
nos.add("full");
}
//刷新數(shù)據(jù)
adapter.refreshData(nos);
}
}
然后adapter里面對(duì)頭尾的特殊數(shù)據(jù)進(jìn)行識(shí)別,將item變?yōu)橥该鞯摹?br />
public class MyAdapter extends BaseAdapter {
ArrayList<String> nos = new ArrayList<String>();
private Context context;
public MyAdapter(Context context, ArrayList<String> nos){
this.context = context;
this.nos = nos;
}
public void refreshData(ArrayList<String> nos) {
this.nos = nos;
notifyDataSetChanged();
}
@Override
public int getCount() {
return nos.size();
}
@Override
public Object getItem(int position) {
return nos.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
// 如果是第一次顯示該頁面(要記得保存到viewholder中供下次直接從緩存中調(diào)用)
holder = new ViewHolder();
convertView = LayoutInflater.from(context).inflate(R.layout.item_test, null);
holder.tv_no = (TextView) convertView.findViewById(R.id.tv_no);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tv_no.setText(nos.get(position));
if(nos.get(position).equals("full")){
convertView.setVisibility(View.INVISIBLE);
}else{
convertView.setVisibility(View.VISIBLE);
}
return convertView;
}
private class ViewHolder {
TextView tv_no;
}
}
這樣我們就實(shí)現(xiàn)可以第一種解決方法

第二種方法,就是讓整個(gè)ListView實(shí)現(xiàn)循環(huán)滾動(dòng),實(shí)現(xiàn)的方式有很多,大家可以自行百度,我這里就通過修改adapter的getCount方法去實(shí)現(xiàn),就是在getCount方法return一個(gè)很大的值,getView獲取數(shù)據(jù)的時(shí)候要模原本的數(shù)組大小,不然數(shù)組就越界了。然后ListView滾動(dòng)到最中間,這樣就實(shí)現(xiàn)偽循環(huán)滾動(dòng)了
public class MainActivity extends AppCompatActivity {
XuListView mLisetview;
MyAdapter adapter;
ArrayList<String> nos = new ArrayList<String>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLisetview = (XuListView) findViewById(R.id.list_test);
ArrayList<String> temp = new ArrayList<String>();
for(int i = 0;i<10;i++){
temp.add(i+"");
}
adapter = new MyAdapter(this,temp);
mLisetview.setAdapter(adapter);
//滾動(dòng)到中間
mLisetview.setSelection(adapter.getCount()/2);
}
}
/**
* Created by xu on 2017/6/27.
*/
public class MyAdapter extends BaseAdapter {
ArrayList<String> nos = new ArrayList<String>();
private Context context;
public MyAdapter(Context context, ArrayList<String> nos){
this.context = context;
this.nos = nos;
}
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public Object getItem(int position) {
return nos.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
// 如果是第一次顯示該頁面(要記得保存到viewholder中供下次直接從緩存中調(diào)用)
holder = new ViewHolder();
convertView = LayoutInflater.from(context).inflate(R.layout.item_test, null);
holder.tv_no = (TextView) convertView.findViewById(R.id.tv_no);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tv_no.setText(nos.get(position%nos.size()));
return convertView;
}
private class ViewHolder {
TextView tv_no;
}
}
這樣我們就實(shí)現(xiàn)了使列表進(jìn)行循環(huán)滾動(dòng),從而達(dá)到每個(gè)item都可以滾動(dòng)到中間突出顯示的效果了

既然我們把動(dòng)畫效果都做出來了,那么也可以直接做成一個(gè)滾輪選擇器,只需要加多兩步:1、把最靠近中間的item滾動(dòng)到中間;2、把中間的item的序號(hào)通過一個(gè)接口返回出去。 我就直接貼代碼吧,反正也不難。
把最靠近中間的item滾動(dòng)到中間的實(shí)現(xiàn)我是這么做的:首先決定好整個(gè)ListView可視的的item數(shù)量是多少,必須是奇數(shù),這樣才能只有一個(gè)item處于正中間,然后根據(jù)ListView的高度計(jì)算出每個(gè)item符合要求的高度,然后更改現(xiàn)有的item的高度,同時(shí)對(duì)內(nèi)容進(jìn)行縮放(不縮放內(nèi)容單純高度變小的話布局就亂了)。最后我們利用smoothScrollToPosition方法回正可視item中的第一個(gè)item,就實(shí)現(xiàn)了將最中間的item回滾到最中間的效果了。因?yàn)榭梢暤膇tem我們是根據(jù)ListView的高度去計(jì)算item的高度的,所有的可視item剛好鋪滿ListView,所以只要頂部那個(gè)回正了,其他的item也會(huì)回正。所以我們可以重寫一下OnScrollListener的onScrollStateChanged方法,每次滾動(dòng)結(jié)束就執(zhí)行一次回滾
/**
* 可視的item數(shù)
*/
private int mVisibleItemCount = -1;
/**
* 沒調(diào)整之前每個(gè)item的高度
*/
private float olditemheight = 0;
/**
* 調(diào)整過后的每個(gè)item的高度
*/
private float newitemheight = -1;
/**
* 調(diào)整每個(gè)可視的item的高度 以及對(duì)內(nèi)容進(jìn)行縮放
*/
public void reSetItemHeight() {
for (int i = 0; i < getChildCount(); i++) {
//獲取item
View temp_view = getChildAt(i);
//設(shè)置item的高度
ViewGroup.LayoutParams lp = temp_view.getLayoutParams();
lp.height = (int) newitemheight;
temp_view.setLayoutParams(lp);
//縮放內(nèi)容 我的item的內(nèi)容用一個(gè)LinearLayout包了起來 所以直接縮放LinearLayout
LinearLayout item_ll_value = (LinearLayout) temp_view.findViewById(R.id.item_ll_value);
item_ll_value.setScaleY((newitemheight / olditemheight) < 0 ? 0 : (newitemheight / olditemheight));
item_ll_value.setScaleX((newitemheight / olditemheight) < 0 ? 0 : (newitemheight / olditemheight));
}
}
/**
* 計(jì)算在給定的可視item數(shù)目下 每個(gè)item應(yīng)該設(shè)置的高度
* */
private void getNewItemHeight() {
//先把舊的item存起來
olditemheight = getChildAt(0).getHeight();
//計(jì)算新的高度
newitemheight = getHeight() / mVisibleItemCount;
if ((getHeight() / mVisibleItemCount) % newitemheight > 0) {
//除不盡的情況下把余數(shù)分給各個(gè)item,暫時(shí)發(fā)現(xiàn)分一次余數(shù)就夠了,如果效果不理想就做個(gè)遞歸多分幾次
float remainder = (getHeight() / mVisibleItemCount) % newitemheight;
newitemheight = remainder / mVisibleItemCount;
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
//滾動(dòng)結(jié)束之后開始回滾item
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE && mVisibleItemCount != -1) {
//使離中間最近的item回滾到中點(diǎn)位置
smoothScrollToPosition(getFirstVisiblePosition());
}
}
實(shí)現(xiàn)了把最靠近中間的item滾動(dòng)到中間,那么選擇的item就是滾動(dòng)結(jié)束后處于最中間的item。對(duì)此我們需要再次重寫一下OnScrollListener的onScrollStateChanged方法。每次滾動(dòng)結(jié)束后,取可視item中的第一個(gè)item的序號(hào)加上我們之前設(shè)置的可視item數(shù)的一半(舍去小數(shù)部分)就是最中間的item的序號(hào)了,也是當(dāng)前選擇項(xiàng)的序號(hào)。
/**
* 當(dāng)前選中項(xiàng)發(fā)生變化的監(jiān)聽者
*/
private onSelectionChangeLisenter selectionChangeLisenter;
/**
* 設(shè)置選中項(xiàng)的監(jiān)聽者
*/
public void setSelectionChangeLisenter(onSelectionChangeLisenter selectionChangeLisenter) {
this.selectionChangeLisenter = selectionChangeLisenter;
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
//滾動(dòng)結(jié)束之后開始正?;貪Litem并記錄最中間的item為選中項(xiàng) (必須設(shè)置可視項(xiàng),ListView才會(huì)改為選擇器模式)
if( scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE && mVisibleItemCount != -1){
//使離中間最近的item回滾到中點(diǎn)位置
smoothScrollToPosition(getFirstVisiblePosition());
//計(jì)算當(dāng)前選中項(xiàng)的序號(hào)
int nowPosition = getFirstVisiblePosition() + mVisibleItemCount/2;
//把當(dāng)前選中項(xiàng)的序號(hào)存起來并通過listener回調(diào)出去
if(selectionChangeLisenter != null && nowPosition != curPosition){
curPosition = nowPosition;
selectionChangeLisenter.onSelectionChange(curPosition);
}
}
}
此處我是使用了一個(gè)接口去,用以實(shí)時(shí)把最新的數(shù)據(jù)返回出去
/**
* Created by xu on 2017/3/3.
*/
public interface onSelectionChangeLisenter {
void onSelectionChange(int position);
}
使用這個(gè)滾輪選擇器的方法也非常簡單,除了跟正常的ListView初始化和綁定adapter之外,只需要額外調(diào)用兩個(gè)方法就行了
//設(shè)置ListView的可視item數(shù)(必須是奇數(shù))
mLisetview.setVisibleItemCount(3);
//設(shè)置監(jiān)聽者監(jiān)聽選中項(xiàng)的變化
mLisetview.setSelectionChangeLisenter(new onSelectionChangeLisenter() {
@Override
public void onSelectionChange(final int position) {
mHandler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this,"選擇項(xiàng)發(fā)生變化 當(dāng)前選中序號(hào):"+(temp.get(position)),Toast.LENGTH_SHORT).show();
}
});
}
});
這樣我們就實(shí)現(xiàn)滾輪數(shù)字選擇器的效果了

現(xiàn)在貼下整個(gè)滾輪選擇器的完整代碼
/**
* 模仿滾輪動(dòng)畫縮放的ListView
* Created by xu on 2017/3/3.
*/
public class XuListView extends ListView implements AbsListView.OnScrollListener {
private static final String TAG = "XuListView";
/**
* 中點(diǎn)的Y坐標(biāo)
*/
private float centerY = 0f;
/**
* 可視的item數(shù)
*/
private int mVisibleItemCount = -1;
/**
* 沒調(diào)整之前每個(gè)item的高度
*/
private float olditemheight = 0;
/**
* 調(diào)整過后的每個(gè)item的高度
*/
private float newitemheight = -1;
/**
* 當(dāng)前選中項(xiàng)發(fā)生變化的監(jiān)聽者
*/
private onSelectionChangeLisenter selectionChangeLisenter;
/**
* 當(dāng)前選中項(xiàng)的序號(hào)
*/
private int curPosition = -1;
public XuListView(Context context, AttributeSet attrs) {
super(context, attrs);
//設(shè)置一個(gè)滾動(dòng)監(jiān)聽
setOnScrollListener(this);
}
/**
* 設(shè)置選中項(xiàng)的監(jiān)聽者
*/
public void setSelectionChangeLisenter(onSelectionChangeLisenter selectionChangeLisenter) {
this.selectionChangeLisenter = selectionChangeLisenter;
}
/**
* 設(shè)置ListView的顯示item數(shù)
* @param count :必須是奇數(shù) 如果為-1 則表示只是使用動(dòng)畫效果的普通ListView
*/
public boolean setVisibleItemCount(int count){
if(count % 2 == 0){
return false;
}else{
mVisibleItemCount = count;
return true;
}
}
/**
* 在這里第一次調(diào)整item高度
*/
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
if(mVisibleItemCount != -1){
getNewItemHeight();
reSetItemHeight();
}
}
/**
* 調(diào)整每個(gè)可視的item的高度 以及對(duì)內(nèi)容進(jìn)行縮放
*/
public void reSetItemHeight(){
for(int i = 0; i < getChildCount(); i++){
//獲取item
View temp_view = getChildAt(i);
//設(shè)置item的高度
ViewGroup.LayoutParams lp = temp_view.getLayoutParams();
lp.height = (int)newitemheight;
temp_view.setLayoutParams(lp);
//縮放內(nèi)容 我的item的內(nèi)容用一個(gè)LinearLayout包了起來 所以直接縮放LinearLayout
LinearLayout item_ll_value = (LinearLayout)temp_view.findViewById(R.id.item_ll_value);
item_ll_value.setScaleY((newitemheight / olditemheight) < 0 ? 0 : (newitemheight / olditemheight));
item_ll_value.setScaleX((newitemheight / olditemheight) < 0 ? 0 : (newitemheight / olditemheight));
}
}
/**
* 計(jì)算在給定的可視item數(shù)目下 每個(gè)item應(yīng)該設(shè)置的高度
*/
private void getNewItemHeight(){
//先把舊的item存起來
olditemheight = getChildAt(0).getHeight();
//計(jì)算新的高度
newitemheight = getHeight()/mVisibleItemCount;
if((getHeight()/mVisibleItemCount) % newitemheight > 0){
//除不盡的情況下把余數(shù)分給各個(gè)item,暫時(shí)發(fā)現(xiàn)分一次余數(shù)就夠了,如果效果不理想就做個(gè)遞歸多分幾次
float remainder = (getHeight()/mVisibleItemCount) % newitemheight;
newitemheight = remainder/mVisibleItemCount;
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
//滾動(dòng)結(jié)束之后開始正?;貪Litem并記錄最中間的item為選中項(xiàng) (必須設(shè)置可視項(xiàng),ListView才會(huì)改為選擇器模式)
if( scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE && mVisibleItemCount != -1){
//使離中間最近的item回滾到中點(diǎn)位置
smoothScrollToPosition(getFirstVisiblePosition());
//計(jì)算當(dāng)前選中項(xiàng)的序號(hào)
int nowPosition = getFirstVisiblePosition() + mVisibleItemCount/2;
//把當(dāng)前選中項(xiàng)的序號(hào)存起來并通過listener回調(diào)出去
if(selectionChangeLisenter != null && nowPosition != curPosition){
curPosition = nowPosition;
selectionChangeLisenter.onSelectionChange(curPosition);
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
//計(jì)算中點(diǎn)
centerY = getHeight()/2;
//判斷中點(diǎn)的有效性
if(centerY <= 0){
return;
}
//開始對(duì)當(dāng)前顯示的View進(jìn)行縮放
for(int i = 0; i < visibleItemCount; i++){
//獲取item
View temp_view = getChildAt(i);
//計(jì)算item的中點(diǎn)Y坐標(biāo)
float itemY = temp_view.getBottom()-(temp_view.getHeight()/2);
//計(jì)算離中點(diǎn)的距離
float distance = centerY;
if(itemY > centerY){
distance = itemY - centerY;
}else{
distance = centerY - itemY;
}
//根據(jù)距離進(jìn)行縮放
temp_view.setScaleY(1.1f - (distance / centerY) < 0 ? 0 : 1.1f - (distance / centerY));
temp_view.setScaleX(1.1f - (distance / centerY) < 0 ? 0 : 1.1f - (distance / centerY));
//根據(jù)距離改變透明度
temp_view.setAlpha(1.1f - (distance / centerY) < 0 ? 0 : 1.1f - (distance / centerY));
}
}
}
注釋很詳細(xì) 相信小白看了也沒什么難度。
滾輪效果的實(shí)現(xiàn)方式有很多,解決頭尾兩個(gè)item無法滾動(dòng)到中間的方法也很多,我說的方法僅供參考,沒有最好的方法,只有最符合自己的需求的方法。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Notification與NotificationManager詳細(xì)介紹
在Android系統(tǒng)中,發(fā)一個(gè)狀態(tài)欄通知還是很方便的。下面我們就來看一下,怎么發(fā)送狀態(tài)欄通知,狀態(tài)欄通知又有哪些參數(shù)可以設(shè)置2012-11-11
Android手機(jī)開發(fā) 使用線性布局和相對(duì)布局實(shí)現(xiàn)Button垂直水平居中
本文主要結(jié)合自己的理解分別對(duì)使用LinearLayout和RelativeLayout兩種方式實(shí)現(xiàn)居中做了總結(jié),希望對(duì)大家有所幫助。2016-05-05
android實(shí)現(xiàn)桌面移動(dòng)懸浮窗口
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)桌面移動(dòng)懸浮窗口,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07
Android事件分發(fā)機(jī)制(上) ViewGroup的事件分發(fā)
這篇文章主要為大家詳細(xì)介紹了Android ViewGroup的事件分發(fā)機(jī)制上篇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01
Android 開機(jī)充電圖標(biāo)和充電動(dòng)畫效果
這篇文章主要介紹了Android 開機(jī)充電圖標(biāo)和充電動(dòng)畫效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-12-12
Android編程中號(hào)碼匹配位數(shù)修改的方法
這篇文章主要介紹了Android編程中號(hào)碼匹配位數(shù)修改的方法,涉及Android編程中參數(shù)修改的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11

