This commit is contained in:
wangcongtao
2020-01-08 18:08:42 +08:00
parent 2b2e998421
commit d5c87148a5
17 changed files with 408 additions and 114 deletions

View File

@@ -61,7 +61,7 @@ dependencies {
// implementation rootProject.ext.dependencies.moduledemo
// implementation rootProject.ext.dependencies.moduledemo2
implementation rootProject.ext.dependencies.modulechatting
// implementation rootProject.ext.dependencies.modulechatting
implementation rootProject.ext.dependencies.moduleonlinecar

View File

@@ -6,10 +6,8 @@ import androidx.multidex.MultiDex;
import com.mogo.commons.AbsMogoApplication;
import com.mogo.commons.debug.DebugConfig;
import com.mogo.module.carchatting.CallChatConstant;
import com.mogo.module.common.MogoModule;
import com.mogo.module.common.MogoModulePaths;
import com.mogo.module.onlinecar.OnLineCarConstants;
import com.mogo.tanlu.constant.TanluConstants;
/**
@@ -28,7 +26,7 @@ public class MogoApplication extends AbsMogoApplication {
DebugConfig.setNetMode( DebugConfig.NET_MODE_QA );
MogoModulePaths.addModule( new MogoModule( TanluConstants.TAG, "CARD_TYPE_ROAD_CODITION" ) );
// MogoModulePaths.addModule(new MogoModule(OnLineCarConstants.TAG, "CARD_TYPE_ROAD_ONLINECAR"));
MogoModulePaths.addModule(new MogoModule( CallChatConstant.PROVIDER, CallChatConstant.MODULE_NAME));
// MogoModulePaths.addModule(new MogoModule( CallChatConstant.PROVIDER, CallChatConstant.MODULE_NAME));
}
@Override

View File

@@ -33,7 +33,7 @@ public class AIAssist implements VoiceClient.VoiceCmdCallBack {
}
private final VoiceClient mVoiceClient;
private Map< String, IMogoVoiceCmdCallBack > mUnWakeupCmdMap = new HashMap<>();
private Map< String, IMogoVoiceCmdCallBack > mCmdMap = new HashMap<>();
private AIAssist( Context context ) {
// private constructor
@@ -43,7 +43,7 @@ public class AIAssist implements VoiceClient.VoiceCmdCallBack {
@Override
public void onCmdSelected( String cmd ) {
final IMogoVoiceCmdCallBack cmdCallBack = mUnWakeupCmdMap.get( cmd );
final IMogoVoiceCmdCallBack cmdCallBack = mCmdMap.get( cmd );
if ( cmdCallBack != null ) {
cmdCallBack.onCmdSelected( cmd );
}
@@ -51,17 +51,23 @@ public class AIAssist implements VoiceClient.VoiceCmdCallBack {
@Override
public void onCmdAction( String speakText ) {
IMogoVoiceCmdCallBack cmdCallBack = mCmdMap.remove( speakText );
if ( cmdCallBack != null ) {
cmdCallBack.onCmdAction( speakText );
}
}
@Override
public void onCmdCancel( String speakText ) {
IMogoVoiceCmdCallBack cmdCallBack = mCmdMap.remove( speakText );
if ( cmdCallBack != null ) {
cmdCallBack.onCmdCancel( speakText );
}
}
@Override
public void onSpeakEnd( String speakText ) {
IMogoVoiceCmdCallBack callBack = mUnWakeupCmdMap.get( speakText );
IMogoVoiceCmdCallBack callBack = mCmdMap.remove( speakText );
if ( callBack != null ) {
callBack.onSpeakEnd( speakText );
}
@@ -69,34 +75,81 @@ public class AIAssist implements VoiceClient.VoiceCmdCallBack {
@Override
public void onSpeakSelectTimeOut( String speakText ) {
IMogoVoiceCmdCallBack callBack = mUnWakeupCmdMap.get( speakText );
IMogoVoiceCmdCallBack callBack = mCmdMap.remove( speakText );
if ( callBack != null ) {
callBack.onSpeakSelectTimeOut( speakText );
}
}
public void speakTTSVoice( String text ) {
/**
* 语音播报
*
* @param text
*/
public void speakTTSVoice( String text, IMogoVoiceCmdCallBack callBack ) {
try {
mCmdMap.put( text, callBack );
mVoiceClient.speakDefault( text );
} catch ( Exception e ) {
}
}
/**
* 语音播报
*
* @param text 播报内容
* @param type 播报策略
*/
public void speakTTSVoice( String text, VoicePreemptType type, IMogoVoiceCmdCallBack callBack ) {
try {
mCmdMap.put( text, callBack );
mVoiceClient.speakTypeText( text, type.getPreemptType() );
} catch ( Exception e ) {
}
}
/**
* 问答类型语音注册:默认确认和取消
*
* @param tts 播报内容
*/
public void speakQAndACmd( String tts, IMogoVoiceCmdCallBack callBack ) {
mCmdMap.put( tts, callBack );
mVoiceClient.speakTtsAndRegistCmd( tts );
}
/**
* 问答类型语音注册
*
* @param tts 播报内容
* @param okCmds 确认命令唤醒词
* @param cancelCmds 取消命令唤醒词
*/
public void speakQAndACmd( String tts, String[] okCmds, String[] cancelCmds, IMogoVoiceCmdCallBack callBack ) {
mCmdMap.put( tts, callBack );
mVoiceClient.speakTtsAndRegistCmd( tts, okCmds, cancelCmds );
}
/**
* 注册免唤醒命令
*
* @param cmd
* @param cmdWords
* @param callBack
*/
public void registerUnWakeupCommand( String cmd, String[] cmdWords, IMogoVoiceCmdCallBack callBack ) {
mUnWakeupCmdMap.put( cmd, callBack );
mCmdMap.put( cmd, callBack );
mVoiceClient.registerCustomWakeupCmd( cmd, cmdWords );
}
/**
* 注销免唤醒命令
*
* @param cmd
*/
public void unregisterUnWakeupCommand( String cmd ) {
mUnWakeupCmdMap.remove( cmd );
mCmdMap.remove( cmd );
mVoiceClient.unRegisterCustomWakeupCmd( cmd );
}
public void registerTTSCallback( String tts, IMogoVoiceCmdCallBack cmdCallBack ) {
mUnWakeupCmdMap.put( tts, cmdCallBack );
}
public void unregisterTTSCallback( String tts ) {
mUnWakeupCmdMap.remove( tts );
}
}

View File

@@ -0,0 +1,23 @@
package com.mogo.commons.voice;
import com.zhidao.auto.platform.voice.VoiceClient;
public enum VoicePreemptType {
PREEMPT_TYPE_NONE( VoiceClient.PreemptType.PREEMPT_TYPE_NONE ), //不打断
PREEMPT_TYPE_IMMEADIATELY( VoiceClient.PreemptType.PREEMPT_TYPE_IMMEADIATELY ), //立即打断取消当前的tts插队播放
PREEMPT_TYPE_NEXT( VoiceClient.PreemptType.PREEMPT_TYPE_NEXT ), //下一个插入不取消当前的tts插队下一个播放
PREEMPT_TYPE_FLUSH( VoiceClient.PreemptType.PREEMPT_TYPE_FLUSH ), //清空队列
PREEMPT_TYPE_IMMEADIATELY_WITHOUT_CANCLE( VoiceClient.PreemptType.PREEMPT_TYPE_IMMEADIATELY_WITHOUT_CANCLE ); //立即打断不取消当前tts
public VoiceClient.PreemptType preemptType;
VoicePreemptType( VoiceClient.PreemptType preemptType ) {
this.preemptType = preemptType;
}
public VoiceClient.PreemptType getPreemptType() {
return preemptType;
}
}

View File

@@ -0,0 +1,20 @@
package com.mogo.module.apps;
import android.content.pm.PackageInfo;
/**
* @author congtaowang
* @since 2020-01-08
* <p>
* app 过滤规则
*/
public interface AppFilter {
/**
* 过滤包
*
* @param packageInfo
* @return true - 过滤 false - 不过滤
*/
boolean filter( PackageInfo packageInfo );
}

View File

@@ -0,0 +1,55 @@
package com.mogo.module.apps;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import java.util.Arrays;
import java.util.List;
/**
* @author congtaowang
* @since 2020-01-08
* <p>
* 过滤 app
*/
public class AppFilterImpl implements AppFilter {
private final Context mContext;
private List< String > mFilterPackages;
public AppFilterImpl( Context context ) {
mContext = context;
final String[] values = context.getResources().getStringArray( R.array.module_apps_array_filter_packages );
if ( values != null ) {
mFilterPackages = Arrays.asList( values );
}
}
@Override
public boolean filter( PackageInfo packageInfo ) {
// if ( isSystemApp( packageInfo ) ) {
// return true;
// }
if ( isFilterPackages( packageInfo ) ) {
return true;
}
if ( noLaunchIntent( packageInfo ) ) {
return true;
}
return false;
}
private boolean isSystemApp( PackageInfo packageInfo ) {
return ( packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM ) != 0;
}
private boolean isFilterPackages( PackageInfo packageInfo ) {
return mFilterPackages.contains( packageInfo.packageName );
}
private boolean noLaunchIntent( PackageInfo packageInfo ) {
return mContext.getPackageManager().getLaunchIntentForPackage( packageInfo.packageName ) == null;
}
}

View File

@@ -3,11 +3,11 @@ package com.mogo.module.apps;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.mogo.module.apps.model.AppInfo;
@@ -19,53 +19,59 @@ import java.util.List;
* <p>
* 描述
*/
public class AppsAdapter extends RecyclerView.Adapter< AppsAdapter.AppsViewHolder > {
public class AppsAdapter extends BaseAdapter {
private List< AppInfo > mAppInfos;
public AppsAdapter( List< AppInfo > appInfos ) {
this.mAppInfos = appInfos;
}
private View.OnClickListener onClickListener;
public void refreshAppInfos( List< AppInfo > mAppInfos ) {
this.mAppInfos = mAppInfos;
notifyDataSetChanged();
}
@NonNull
@Override
public AppsViewHolder onCreateViewHolder( @NonNull ViewGroup parent, int viewType ) {
return new AppsViewHolder( LayoutInflater.from( parent.getContext() ).inflate( R.layout.module_apps_item_app, null ) );
}
@Override
public void onBindViewHolder( @NonNull AppsViewHolder holder, int position ) {
final AppInfo appInfo = mAppInfos.get( position );
holder.mIcon.setImageDrawable( appInfo.getIcon() );
holder.mName.setText( appInfo.getName() );
holder.itemView.setTag(appInfo);
holder.itemView.setOnClickListener(onClickListener);
}
@Override
public int getItemCount() {
public int getCount() {
return mAppInfos == null ? 0 : mAppInfos.size();
}
public static class AppsViewHolder extends RecyclerView.ViewHolder {
@Override
public AppInfo getItem( int position ) {
return mAppInfos.get( position );
}
@Override
public long getItemId( int position ) {
return position;
}
@Override
public View getView( int position, View convertView, ViewGroup parent ) {
AppViewHolder holder = null;
if ( convertView == null ) {
holder = new AppViewHolder( LayoutInflater.from( parent.getContext() ).inflate( R.layout.module_apps_item_app, null ) );
} else {
holder = ( ( AppViewHolder ) convertView.getTag() );
}
AppInfo appInfo = getItem( position );
holder.mIcon.setImageDrawable( appInfo.getIcon() );
holder.mName.setText( appInfo.getName() );
return holder.mItemView;
}
public static class AppViewHolder {
private View mItemView;
public ImageView mIcon;
public TextView mName;
public AppsViewHolder( @NonNull View itemView ) {
super( itemView );
public AppViewHolder( @NonNull View itemView ) {
mItemView = itemView;
mIcon = itemView.findViewById( R.id.module_apps_id_app_icon );
mName = itemView.findViewById( R.id.module_apps_id_app_name );
mItemView.setTag( this );
}
}
public void setOnClickListener(View.OnClickListener onClickListener) {
this.onClickListener = onClickListener;
}
}

View File

@@ -0,0 +1,12 @@
package com.mogo.module.apps;
/**
* @author congtaowang
* @since 2020-01-08
* <p>
* 描述
*/
public class AppsConst {
public static final int TOTAL_SIZE_EACH_PAGE = 12;
}

View File

@@ -1,16 +1,21 @@
package com.mogo.module.apps;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager.widget.ViewPager;
import com.alibaba.android.arouter.launcher.ARouter;
import com.mogo.commons.mvp.MvpFragment;
import com.mogo.module.apps.model.AppInfo;
import com.mogo.service.MogoServicePaths;
import com.mogo.service.fragmentmanager.IMogoFragmentManager;
import com.mogo.utils.logger.Logger;
import java.util.List;
import java.util.Map;
/**
* @author congtaowang
@@ -23,8 +28,11 @@ public class AppsFragment extends MvpFragment< AppsView, AppsPresenter > impleme
public static final String TAG = "AppsFragment";
// private BottomSheetBehavior mBottomSheetBehavior;
private RecyclerView mAppsList;
private AppsAdapter mAppsAdapter;
private ViewPager mAppsPager;
private AppsPagerAdapter mAppsPagerAdapter;
private View mExit;
private IMogoFragmentManager mMogoFragmentManager;
@Override
protected int getLayoutId() {
@@ -33,8 +41,13 @@ public class AppsFragment extends MvpFragment< AppsView, AppsPresenter > impleme
@Override
protected void initViews() {
mAppsList = findViewById( R.id.module_apps_id_apps );
mAppsList.setLayoutManager( new GridLayoutManager( getContext(), 8 ) );
mAppsPager = findViewById( R.id.module_apps_id_apps_pager );
mExit = findViewById( R.id.module_apps_id_apps_exit );
mExit.setOnClickListener( view -> {
mMogoFragmentManager.pop();
} );
// mAppsList = findViewById( R.id.module_apps_id_apps );
// mAppsList.setLayoutManager( new GridLayoutManager( getContext(), 8 ) );
// mBottomSheetBehavior = BottomSheetBehavior.from( mAppsList );
// mBottomSheetBehavior.setSkipCollapsed( true );
// mBottomSheetBehavior.setBottomSheetCallback( new BottomSheetBehavior.BottomSheetCallback() {
@@ -60,23 +73,20 @@ public class AppsFragment extends MvpFragment< AppsView, AppsPresenter > impleme
@Override
public void onActivityCreated( @Nullable Bundle savedInstanceState ) {
super.onActivityCreated( savedInstanceState );
mMogoFragmentManager = ( IMogoFragmentManager ) ARouter.getInstance().build( MogoServicePaths.PATH_FRAGMENT_MANAGER ).navigation();
}
@Override
public void renderApps( List< AppInfo > appInfos ) {
if ( mAppsAdapter == null ) {
mAppsAdapter = new AppsAdapter( appInfos );
mAppsList.setAdapter( mAppsAdapter );
bindListener();
public void renderApps( Map< Integer, List< AppInfo > > appInfos ) {
if ( mAppsPagerAdapter == null ) {
mAppsPagerAdapter = new AppsPagerAdapter( appInfos );
mAppsPager.setAdapter( mAppsPagerAdapter );
mAppsPagerAdapter.setOnAppClickedListener( ( appInfo, position ) -> {
Logger.i( TAG, "position = %d clicked. name = %s", position, appInfo.getName() );
mPresenter.launch( appInfo );
} );
} else {
mAppsAdapter.refreshAppInfos( appInfos );
mAppsPagerAdapter.setPagedApps( appInfos );
}
}
private void bindListener() {
mAppsAdapter.setOnClickListener( view -> {
AppInfo app = ( AppInfo ) view.getTag();
mPresenter.launch( app );
} );
}
}

View File

@@ -0,0 +1,85 @@
package com.mogo.module.apps;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.GridView;
import androidx.annotation.NonNull;
import androidx.viewpager.widget.PagerAdapter;
import com.mogo.module.apps.model.AppInfo;
import java.util.List;
import java.util.Map;
/**
* @author congtaowang
* @since 2020-01-08
* <p>
* 描述
*/
public class AppsPagerAdapter extends PagerAdapter {
private Map< Integer, List< AppInfo > > mPagedApps;
private OnAppClickedListener mOnAppClickedListener;
public AppsPagerAdapter( Map< Integer, List< AppInfo > > apps ) {
this.mPagedApps = apps;
}
@Override
public int getCount() {
return mPagedApps == null ? 0 : mPagedApps.size();
}
public void setOnAppClickedListener( OnAppClickedListener onAppClickedListener ) {
this.mOnAppClickedListener = onAppClickedListener;
}
public OnAppClickedListener getOnAppClickedListener() {
return mOnAppClickedListener;
}
@Override
public boolean isViewFromObject( @NonNull View view, @NonNull Object object ) {
return view == object;
}
public void setPagedApps( Map< Integer, List< AppInfo > > pagedApps ) {
this.mPagedApps = pagedApps;
notifyDataSetChanged();
}
@NonNull
@Override
public Object instantiateItem( @NonNull ViewGroup container, int position ) {
View pager = LayoutInflater.from( container.getContext() ).inflate( R.layout.module_apps_item_app_pager, null );
GridView page = pager.findViewById( R.id.module_apps_id_apps_page );
page.setAdapter( new AppsAdapter( mPagedApps.get( position ) ) );
page.setOnItemClickListener( ( parent, view, appPosition, id ) -> {
if ( getOnAppClickedListener() != null ) {
getOnAppClickedListener().onClick( mPagedApps.get( position ).get( appPosition ), position * AppsConst.TOTAL_SIZE_EACH_PAGE + appPosition );
}
} );
container.addView( page );
return page;
}
@Override
public void destroyItem( @NonNull ViewGroup container, int position, @NonNull Object object ) {
if ( object instanceof View ) {
container.removeView( ( ( View ) object ) );
}
}
@Override
public int getItemPosition( @NonNull Object object ) {
return POSITION_NONE;
}
public interface OnAppClickedListener {
void onClick( AppInfo appInfo, int position );
}
}

View File

@@ -13,11 +13,14 @@ import androidx.lifecycle.Observer;
import com.mogo.commons.mvp.Presenter;
import com.mogo.module.apps.model.AppInfo;
import com.mogo.utils.ThreadPoolService;
import com.mogo.utils.TipToast;
import com.mogo.utils.UiThreadHandler;
import com.mogo.utils.logger.Logger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author congtaowang
@@ -29,13 +32,12 @@ public class AppsPresenter extends Presenter< AppsView > {
private static final String TAG = "AppsPresenter";
private AppFilter mAppFilter;
public AppsPresenter( AppsView view ) {
super( view );
RefreshAppsListLiveData.getInstance().observeForever( new Observer< String >() {
@Override
public void onChanged( String s ) {
renderAppsList();
}
RefreshAppsListLiveData.getInstance().observeForever( s -> {
renderAppsList();
} );
}
@@ -46,55 +48,58 @@ public class AppsPresenter extends Presenter< AppsView > {
}
private void renderAppsList() {
ThreadPoolService.execute( new Runnable() {
@Override
public void run() {
final List< AppInfo > appInfoList = loadAppsList();
UiThreadHandler.post( new Runnable() {
@Override
public void run() {
if ( mView != null ) {
mView.renderApps( appInfoList );
}
}
} );
}
ThreadPoolService.execute( () -> {
final Map< Integer, List< AppInfo > > appInfoList = loadAppsList();
UiThreadHandler.post( () -> {
if ( mView != null ) {
mView.renderApps( appInfoList );
}
} );
} );
}
private List< AppInfo > loadAppsList() {
private Map< Integer, List< AppInfo > > loadAppsList() {
Logger.i( TAG, "load apps list." );
final List< AppInfo > appInfos = new ArrayList<>();
if ( mAppFilter == null ) {
mAppFilter = new AppFilterImpl( getContext() );
}
final Map< Integer, List< AppInfo > > pagedApps = new HashMap<>();
final PackageManager packageManager = getContext().getPackageManager();
List< PackageInfo > packages = packageManager.getInstalledPackages( 0 );
int counter = 0;
for ( int i = 0; i < packages.size(); ++i ) {
PackageInfo packageInfo = packages.get( i );
//获取非系统应用
if ( ( packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM ) == 0 ) {
String appName = packageInfo.applicationInfo.loadLabel( packageManager ).toString();
String packageName = packageInfo.packageName;
String versionName = packageInfo.versionName;
int versionCode = packageInfo.versionCode;
Drawable appIcon = packageInfo.applicationInfo.loadIcon( packageManager );
AppInfo appInfo = new AppInfo( appName, packageName, versionName, versionCode, appIcon );
appInfos.add( appInfo );
if ( mAppFilter.filter( packageInfo ) ) {
continue;
}
int page = counter++ / AppsConst.TOTAL_SIZE_EACH_PAGE;
if ( !pagedApps.containsKey( page ) ) {
pagedApps.put( page, new ArrayList<>() );
}
String appName = packageInfo.applicationInfo.loadLabel( packageManager ).toString();
String packageName = packageInfo.packageName;
String versionName = packageInfo.versionName;
int versionCode = packageInfo.versionCode;
Drawable appIcon = packageInfo.applicationInfo.loadIcon( packageManager );
AppInfo appInfo = new AppInfo( appName, packageName, versionName, versionCode, appIcon );
pagedApps.get( page ).add( appInfo );
}
return appInfos;
return pagedApps;
}
public void launch( AppInfo appInfo ) {
if ( appInfo == null ) {
return;
}
Intent intent = getContext().getPackageManager().getLaunchIntentForPackage( appInfo.getPackageName() );
if ( intent == null ) {
Logger.e( TAG, "can't launch app: %s", appInfo.toString() );
return;
try {
Intent intent = getContext().getPackageManager().getLaunchIntentForPackage( appInfo.getPackageName() );
intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
getContext().startActivity( intent );
} catch ( Exception e ) {
TipToast.shortTip( R.string.module_apps_str_no_app );
}
intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
getContext().startActivity( intent );
}
}

View File

@@ -4,6 +4,7 @@ import com.mogo.commons.mvp.IView;
import com.mogo.module.apps.model.AppInfo;
import java.util.List;
import java.util.Map;
/**
* @author congtaowang
@@ -18,5 +19,5 @@ public interface AppsView extends IView {
*
* @param appInfos
*/
void renderApps( List< AppInfo > appInfos );
void renderApps( Map< Integer, List< AppInfo > > appInfos );
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -12,15 +12,22 @@
<!-- app:layout_behavior="@string/bottom_sheet_behavior" />-->
<!--</androidx.coordinatorlayout.widget.CoordinatorLayout>-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:background="#0C0C0C">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/module_apps_id_apps"
<ImageView
android:id="@+id/module_apps_id_apps_exit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/module_apps_ic_retract" />
<androidx.viewpager.widget.ViewPager
android:id="@+id/module_apps_id_apps_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:behavior_hideable="false"
app:behavior_peekHeight="76dp" />
</LinearLayout>
android:layout_marginTop="@dimen/dp_210" />
</FrameLayout>

View File

@@ -8,13 +8,16 @@
<ImageView
android:id="@+id/module_apps_id_app_icon"
android:layout_width="60dp"
android:layout_height="60dp" />
android:layout_width="@dimen/dp_120"
android:layout_height="@dimen/dp_120" />
<TextView
android:id="@+id/module_apps_id_app_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_32"
android:gravity="center"
android:maxLines="2" />
android:maxLines="2"
android:textColor="#FFFFFF"
android:textSize="@dimen/dp_32" />
</LinearLayout>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/module_apps_id_apps_page"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="6"
android:orientation="vertical"
android:paddingLeft="@dimen/dp_220"
android:paddingRight="@dimen/dp_220"
android:verticalSpacing="@dimen/dp_154">
</GridView>

View File

@@ -1,3 +1,7 @@
<resources>
<string name="app_name">mogo-module-apps</string>
<string name="module_apps_str_no_app">APP 未安装</string>
<string-array name="module_apps_array_filter_packages">
<item>com.mogo.launcher</item>
</string-array>
</resources>